| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951 |
- /* An abstract class from which other views inherit from
- ----------------------------------------------------------------------------------------------------------------------*/
- var View = FC.View = InteractiveDateComponent.extend({
- type: null, // subclass' view name (string)
- name: null, // deprecated. use `type` instead
- title: null, // the text that will be displayed in the header's title
- calendar: null, // owner Calendar object
- viewSpec: null,
- options: null, // hash containing all options. already merged with view-specific-options
- isDatesRendered: false,
- queuedScroll: null,
- isSelected: false, // boolean whether a range of time is user-selected or not
- selectedEventInstance: null,
- eventOrderSpecs: null, // criteria for ordering events when they have same date/time
- // for date utils, computed from options
- isHiddenDayHash: null,
- // now indicator
- isNowIndicatorRendered: null,
- initialNowDate: null, // result first getNow call
- initialNowQueriedMs: null, // ms time the getNow was called
- nowIndicatorTimeoutID: null, // for refresh timing of now indicator
- nowIndicatorIntervalID: null, // "
- constructor: function(calendar, viewSpec) {
- this.calendar = calendar;
- this.viewSpec = viewSpec;
- // shortcuts
- this.type = viewSpec.type;
- this.options = viewSpec.options;
- // .name is deprecated
- this.name = this.type;
- InteractiveDateComponent.call(this);
- this.initHiddenDays();
- this.eventOrderSpecs = parseFieldSpecs(this.opt('eventOrder'));
- // legacy
- if (this.initialize) {
- this.initialize();
- }
- },
- _getView: function() {
- return this;
- },
- // Retrieves an option with the given name
- opt: function(name) {
- return this.options[name];
- },
- /* Title and Date Formatting
- ------------------------------------------------------------------------------------------------------------------*/
- // Computes what the title at the top of the calendar should be for this view
- computeTitle: function(dateProfile) {
- var unzonedRange;
- // for views that span a large unit of time, show the proper interval, ignoring stray days before and after
- if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) {
- unzonedRange = dateProfile.currentUnzonedRange;
- }
- else { // for day units or smaller, use the actual day range
- unzonedRange = dateProfile.activeUnzonedRange;
- }
- return this.formatRange(
- {
- start: this.calendar.msToMoment(unzonedRange.startMs, dateProfile.isRangeAllDay),
- end: this.calendar.msToMoment(unzonedRange.endMs, dateProfile.isRangeAllDay)
- },
- dateProfile.isRangeAllDay,
- this.opt('titleFormat') || this.computeTitleFormat(),
- this.opt('titleRangeSeparator')
- );
- },
- // Generates the format string that should be used to generate the title for the current date range.
- // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.
- computeTitleFormat: function() {
- var currentRangeUnit = this.get('dateProfile').currentRangeUnit;
- if (currentRangeUnit == 'year') {
- return 'YYYY';
- }
- else if (currentRangeUnit == 'month') {
- return this.opt('monthYearFormat'); // like "September 2014"
- }
- else if (this.currentRangeAs('days') > 1) {
- return 'll'; // multi-day range. shorter, like "Sep 9 - 10 2014"
- }
- else {
- return 'LL'; // one day. longer, like "September 9 2014"
- }
- },
- // Element
- // -----------------------------------------------------------------------------------------------------------------
- setElement: function(el) {
- var _this = this;
- InteractiveDateComponent.prototype.setElement.apply(this, arguments);
- this.bindBaseRenderHandlers();
- // TODO: not best place for this
- // TODO: better way of forwarding options from calendar -> view
- this.calendar.optionsModel.watch('viewRawBusinessHours', [ 'businessHours' ], function(deps) {
- _this.set('rawBusinessHours', deps.businessHours);
- }, function() {
- _this.unset('rawBusinessHours');
- });
- },
- removeElement: function() {
- this.unsetDate();
- this.unbindBaseRenderHandlers();
- this.calendar.optionsModel.unwatch('viewRawBusinessHours');
- InteractiveDateComponent.prototype.removeElement.apply(this, arguments);
- },
- // Date Setting/Unsetting
- // -----------------------------------------------------------------------------------------------------------------
- setDate: function(date) {
- var currentDateProfile = this.get('dateProfile');
- var newDateProfile = this.buildDateProfile(date, null, true); // forceToValid=true
- if (
- !currentDateProfile ||
- !currentDateProfile.activeUnzonedRange.equals(newDateProfile.activeUnzonedRange)
- ) {
- this.set('dateProfile', newDateProfile);
- }
- },
- unsetDate: function() {
- this.unset('dateProfile');
- },
- handleDateProfileSet: function(dateProfile) {
- InteractiveDateComponent.prototype.handleDateProfileSet.apply(this, arguments);
- var calendar = this.calendar;
- // DEPRECATED, but we need to keep it updated...
- this.start = calendar.msToMoment(dateProfile.activeUnzonedRange.startMs, dateProfile.isRangeAllDay);
- this.end = calendar.msToMoment(dateProfile.activeUnzonedRange.endMs, dateProfile.isRangeAllDay);
- this.intervalStart = calendar.msToMoment(dateProfile.currentUnzonedRange.startMs, dateProfile.isRangeAllDay);
- this.intervalEnd = calendar.msToMoment(dateProfile.currentUnzonedRange.endMs, dateProfile.isRangeAllDay);
- this.title = this.computeTitle(dateProfile);
- calendar.reportViewDatesChanged(this, dateProfile); // TODO: reverse the pubsub
- },
- // Event Data
- // -----------------------------------------------------------------------------------------------------------------
- fetchInitialEvents: function(dateProfile) {
- var calendar = this.calendar;
- var forceAllDay = dateProfile.isRangeAllDay && !this.usesMinMaxTime;
- return calendar.requestEvents(
- calendar.msToMoment(dateProfile.activeUnzonedRange.startMs, forceAllDay),
- calendar.msToMoment(dateProfile.activeUnzonedRange.endMs, forceAllDay)
- );
- },
- bindEventChanges: function() {
- // can write this shorter?
- this.listenTo(this.calendar, 'eventsReset', this.handleEventsReset);
- //this.listenTo(this.calendar, 'eventAdd', this.handleEventAddOrUpdate);
- //this.listenTo(this.calendar, 'eventUpdate', this.handleEventAddOrUpdate);
- //this.listenTo(this.calendar, 'eventRemove', this.handleEventRemove);
- },
- unbindEventChanges: function() {
- // can write this shorter?
- this.stopListeningTo(this.calendar, 'eventsReset');
- //this.stopListeningTo(this.calendar, 'eventAdd');
- //this.stopListeningTo(this.calendar, 'eventUpdate');
- //this.stopListeningTo(this.calendar, 'eventRemove');
- },
- // Date High-level Rendering
- // -----------------------------------------------------------------------------------------------------------------
- // if dateProfile not specified, uses current
- executeDateRender: function(dateProfile, skipScroll) {
- if (this.render) {
- this.render(); // TODO: deprecate
- }
- this.renderDates(dateProfile);
- this.startNowIndicator(); // shouldn't render yet because updateSize will be called soon
- if (!skipScroll) {
- this.addScroll(this.computeInitialDateScroll());
- }
- this.isDatesRendered = true;
- this.trigger('datesRendered');
- },
- executeDateUnrender: function() {
- this.unselect();
- this.stopNowIndicator();
- this.trigger('before:datesUnrendered');
- this.unrenderDates();
- if (this.destroy) {
- this.destroy(); // TODO: deprecate
- }
- this.isDatesRendered = false;
- },
- // Determing when the "meat" of the view is rendered (aka the base)
- // -----------------------------------------------------------------------------------------------------------------
- bindBaseRenderHandlers: function() {
- var _this = this;
- this.on('datesRendered.baseHandler', function() {
- _this.onBaseRender();
- });
- this.on('before:datesUnrendered.baseHandler', function() {
- _this.onBeforeBaseUnrender();
- });
- },
- unbindBaseRenderHandlers: function() {
- this.off('.baseHandler');
- },
- onBaseRender: function() {
- this.applyScreenState(); // TODO: only call if hasHandlers
- this.publiclyTrigger('viewRender', {
- context: this,
- args: [ this, this.el ]
- });
- },
- onBeforeBaseUnrender: function() {
- this.applyScreenState(); // TODO: only call if hasHandlers
- this.publiclyTrigger('viewDestroy', {
- context: this,
- args: [ this, this.el ]
- });
- },
- // Misc view rendering utils
- // -----------------------------------------------------------------------------------------------------------------
- // Binds DOM handlers to elements that reside outside the view container, such as the document
- bindGlobalHandlers: function() {
- InteractiveDateComponent.prototype.bindGlobalHandlers.apply(this, arguments);
- this.listenTo(GlobalEmitter.get(), {
- touchstart: this.processUnselect,
- mousedown: this.handleDocumentMousedown
- });
- },
- // Unbinds DOM handlers from elements that reside outside the view container
- unbindGlobalHandlers: function() {
- InteractiveDateComponent.prototype.unbindGlobalHandlers.apply(this, arguments);
- this.stopListeningTo(GlobalEmitter.get());
- },
- /* Now Indicator
- ------------------------------------------------------------------------------------------------------------------*/
- // Immediately render the current time indicator and begins re-rendering it at an interval,
- // which is defined by this.getNowIndicatorUnit().
- // TODO: somehow do this for the current whole day's background too
- startNowIndicator: function() {
- var _this = this;
- var unit;
- var update;
- var delay; // ms wait value
- if (this.opt('nowIndicator')) {
- unit = this.getNowIndicatorUnit();
- if (unit) {
- update = proxy(this, 'updateNowIndicator'); // bind to `this`
- this.initialNowDate = this.calendar.getNow();
- this.initialNowQueriedMs = +new Date();
- this.renderNowIndicator(this.initialNowDate);
- this.isNowIndicatorRendered = true;
- // wait until the beginning of the next interval
- delay = this.initialNowDate.clone().startOf(unit).add(1, unit) - this.initialNowDate;
- this.nowIndicatorTimeoutID = setTimeout(function() {
- _this.nowIndicatorTimeoutID = null;
- update();
- delay = +moment.duration(1, unit);
- delay = Math.max(100, delay); // prevent too frequent
- _this.nowIndicatorIntervalID = setInterval(update, delay); // update every interval
- }, delay);
- }
- }
- },
- // rerenders the now indicator, computing the new current time from the amount of time that has passed
- // since the initial getNow call.
- updateNowIndicator: function() {
- if (this.isNowIndicatorRendered) {
- this.unrenderNowIndicator();
- this.renderNowIndicator(
- this.initialNowDate.clone().add(new Date() - this.initialNowQueriedMs) // add ms
- );
- }
- },
- // Immediately unrenders the view's current time indicator and stops any re-rendering timers.
- // Won't cause side effects if indicator isn't rendered.
- stopNowIndicator: function() {
- if (this.isNowIndicatorRendered) {
- if (this.nowIndicatorTimeoutID) {
- clearTimeout(this.nowIndicatorTimeoutID);
- this.nowIndicatorTimeoutID = null;
- }
- if (this.nowIndicatorIntervalID) {
- clearTimeout(this.nowIndicatorIntervalID);
- this.nowIndicatorIntervalID = null;
- }
- this.unrenderNowIndicator();
- this.isNowIndicatorRendered = false;
- }
- },
- /* Dimensions
- ------------------------------------------------------------------------------------------------------------------*/
- updateSize: function(totalHeight, isAuto, isResize) {
- InteractiveDateComponent.prototype.updateSize.apply(this, arguments);
- this.updateNowIndicator();
- },
- /* Scroller
- ------------------------------------------------------------------------------------------------------------------*/
- addForcedScroll: function(scroll) {
- this.addScroll(
- $.extend(scroll, { isForced: true })
- );
- },
- addScroll: function(scroll) {
- var queuedScroll = this.queuedScroll || (this.queuedScroll = {});
- if (!queuedScroll.isForced) {
- $.extend(queuedScroll, scroll);
- }
- },
- popScroll: function() {
- this.applyQueuedScroll();
- this.queuedScroll = null;
- },
- applyQueuedScroll: function() {
- if (this.queuedScroll) {
- this.applyScroll(this.queuedScroll);
- }
- },
- queryScroll: function() {
- var scroll = {};
- if (this.isDatesRendered) {
- $.extend(scroll, this.queryDateScroll());
- }
- return scroll;
- },
- applyScroll: function(scroll) {
- if (this.isDatesRendered) {
- this.applyDateScroll(scroll);
- }
- },
- computeInitialDateScroll: function() {
- return {}; // subclasses must implement
- },
- queryDateScroll: function() {
- return {}; // subclasses must implement
- },
- applyDateScroll: function(scroll) {
- ; // subclasses must implement
- },
- // Event High-level Rendering
- // -----------------------------------------------------------------------------------------------------------------
- executeEventsRender: function(eventsPayload) {
- if (this.renderEvents) { // for legacy custom views
- this.renderEvents(convertEventsPayloadToLegacyArray(eventsPayload));
- }
- else {
- this.renderEventsPayload(eventsPayload);
- }
- this.onEventsRender();
- },
- executeEventsUnrender: function() {
- this.onBeforeEventsUnrender();
- if (this.destroyEvents) {
- this.destroyEvents(); // TODO: deprecate
- }
- this.unrenderEvents();
- },
- // Event Rendering Triggers
- // -----------------------------------------------------------------------------------------------------------------
- // Signals that all events have been rendered
- onEventsRender: function() {
- var _this = this;
- var hasSingleHandlers = this.hasPublicHandlers('eventAfterRender');
- if (hasSingleHandlers || this.hasPublicHandlers('eventAfterAllRender')) {
- this.applyScreenState();
- }
- if (hasSingleHandlers) {
- this.getEventSegs().forEach(function(seg) {
- var legacy;
- if (seg.el) { // necessary?
- legacy = seg.footprint.getEventLegacy();
- _this.publiclyTrigger('eventAfterRender', {
- context: legacy,
- args: [ legacy, seg.el, _this ]
- });
- }
- });
- }
- this.publiclyTrigger('eventAfterAllRender', {
- context: this,
- args: [ this ]
- });
- },
- // Signals that all event elements are about to be removed
- onBeforeEventsUnrender: function() {
- var _this = this;
- if (this.hasPublicHandlers('eventDestroy')) {
- this.applyScreenState();
- this.getEventSegs().forEach(function(seg) {
- var legacy;
- if (seg.el) { // necessary?
- legacy = seg.footprint.getEventLegacy();
- _this.publiclyTrigger('eventDestroy', {
- context: legacy,
- args: [ legacy, seg.el, _this ]
- });
- }
- });
- }
- },
- // TODO: move this to Calendar, as well as scroll system
- applyScreenState: function() {
- // bring to natural height, then freeze again
- this.calendar.updateViewSize();
- this.calendar.thawContentHeight();
- this.calendar.freezeContentHeight();
- this.applyQueuedScroll();
- },
- // Event Rendering Utils
- // -----------------------------------------------------------------------------------------------------------------
- // TODO: move this to DateComponent
- // Hides all rendered event segments linked to the given event
- showEventsWithId: function(eventDefId) {
- this.getEventSegs().forEach(function(seg) {
- if (
- seg.footprint.eventDef.id === eventDefId &&
- seg.el // necessary?
- ) {
- seg.el.css('visibility', '');
- }
- });
- },
- // Shows all rendered event segments linked to the given event
- hideEventsWithId: function(eventDefId) {
- this.getEventSegs().forEach(function(seg) {
- if (
- seg.footprint.eventDef.id === eventDefId &&
- seg.el // necessary?
- ) {
- seg.el.css('visibility', 'hidden');
- }
- });
- },
- /* Event Drag-n-Drop
- ------------------------------------------------------------------------------------------------------------------*/
- reportEventDrop: function(eventInstance, eventMutation, el, ev) {
- var eventManager = this.calendar.eventManager;
- var undoFunc = eventManager.mutateEventsWithId(
- eventInstance.def.id,
- eventMutation,
- this.calendar
- );
- var dateMutation = eventMutation.dateMutation;
- // update the EventInstance, for handlers
- if (dateMutation) {
- eventInstance.dateProfile = dateMutation.buildNewDateProfile(
- eventInstance.dateProfile,
- this.calendar
- );
- }
- this.triggerEventDrop(
- eventInstance,
- // a drop doesn't necessarily mean a date mutation (ex: resource change)
- (dateMutation && dateMutation.dateDelta) || moment.duration(),
- undoFunc,
- el, ev
- );
- },
- // Triggers event-drop handlers that have subscribed via the API
- triggerEventDrop: function(eventInstance, dateDelta, undoFunc, el, ev) {
- this.publiclyTrigger('eventDrop', {
- context: el[0],
- args: [
- eventInstance.toLegacy(),
- dateDelta,
- undoFunc,
- ev,
- {}, // {} = jqui dummy
- this
- ]
- });
- },
- /* External Element Drag-n-Drop
- ------------------------------------------------------------------------------------------------------------------*/
- // Must be called when an external element, via jQuery UI, has been dropped onto the calendar.
- // `meta` is the parsed data that has been embedded into the dragging event.
- // `dropLocation` is an object that contains the new zoned start/end/allDay values for the event.
- reportExternalDrop: function(singleEventDef, isEvent, isSticky, el, ev, ui) {
- if (isEvent) {
- this.calendar.eventManager.addEventDef(singleEventDef, isSticky);
- }
- this.triggerExternalDrop(singleEventDef, isEvent, el, ev, ui);
- },
- // Triggers external-drop handlers that have subscribed via the API
- triggerExternalDrop: function(singleEventDef, isEvent, el, ev, ui) {
- // trigger 'drop' regardless of whether element represents an event
- this.publiclyTrigger('drop', {
- context: el[0],
- args: [
- singleEventDef.dateProfile.start.clone(),
- ev,
- ui,
- this
- ]
- });
- if (isEvent) {
- // signal an external event landed
- this.publiclyTrigger('eventReceive', {
- context: this,
- args: [
- singleEventDef.buildInstance().toLegacy(),
- this
- ]
- });
- }
- },
- /* Event Resizing
- ------------------------------------------------------------------------------------------------------------------*/
- // Must be called when an event in the view has been resized to a new length
- reportEventResize: function(eventInstance, eventMutation, el, ev) {
- var eventManager = this.calendar.eventManager;
- var undoFunc = eventManager.mutateEventsWithId(
- eventInstance.def.id,
- eventMutation,
- this.calendar
- );
- // update the EventInstance, for handlers
- eventInstance.dateProfile = eventMutation.dateMutation.buildNewDateProfile(
- eventInstance.dateProfile,
- this.calendar
- );
- this.triggerEventResize(
- eventInstance,
- eventMutation.dateMutation.endDelta,
- undoFunc,
- el, ev
- );
- },
- // Triggers event-resize handlers that have subscribed via the API
- triggerEventResize: function(eventInstance, durationDelta, undoFunc, el, ev) {
- this.publiclyTrigger('eventResize', {
- context: el[0],
- args: [
- eventInstance.toLegacy(),
- durationDelta,
- undoFunc,
- ev,
- {}, // {} = jqui dummy
- this
- ]
- });
- },
- /* Selection (time range)
- ------------------------------------------------------------------------------------------------------------------*/
- // Selects a date span on the view. `start` and `end` are both Moments.
- // `ev` is the native mouse event that begin the interaction.
- select: function(footprint, ev) {
- this.unselect(ev);
- this.renderSelectionFootprint(footprint);
- this.reportSelection(footprint, ev);
- },
- renderSelectionFootprint: function(footprint, ev) {
- if (this.renderSelection) { // legacy method in custom view classes
- this.renderSelection(
- footprint.toLegacy(this.calendar)
- );
- }
- else {
- InteractiveDateComponent.prototype.renderSelectionFootprint.apply(this, arguments);
- }
- },
- // Called when a new selection is made. Updates internal state and triggers handlers.
- reportSelection: function(footprint, ev) {
- this.isSelected = true;
- this.triggerSelect(footprint, ev);
- },
- // Triggers handlers to 'select'
- triggerSelect: function(footprint, ev) {
- var dateProfile = this.calendar.footprintToDateProfile(footprint); // abuse of "Event"DateProfile?
- this.publiclyTrigger('select', {
- context: this,
- args: [
- dateProfile.start,
- dateProfile.end,
- ev,
- this
- ]
- });
- },
- // Undoes a selection. updates in the internal state and triggers handlers.
- // `ev` is the native mouse event that began the interaction.
- unselect: function(ev) {
- if (this.isSelected) {
- this.isSelected = false;
- if (this.destroySelection) {
- this.destroySelection(); // TODO: deprecate
- }
- this.unrenderSelection();
- this.publiclyTrigger('unselect', {
- context: this,
- args: [ ev, this ]
- });
- }
- },
- /* Event Selection
- ------------------------------------------------------------------------------------------------------------------*/
- selectEventInstance: function(eventInstance) {
- if (
- !this.selectedEventInstance ||
- this.selectedEventInstance !== eventInstance
- ) {
- this.unselectEventInstance();
- this.getEventSegs().forEach(function(seg) {
- if (
- seg.footprint.eventInstance === eventInstance &&
- seg.el // necessary?
- ) {
- seg.el.addClass('fc-selected');
- }
- });
- this.selectedEventInstance = eventInstance;
- }
- },
- unselectEventInstance: function() {
- if (this.selectedEventInstance) {
- this.getEventSegs().forEach(function(seg) {
- if (seg.el) { // necessary?
- seg.el.removeClass('fc-selected');
- }
- });
- this.selectedEventInstance = null;
- }
- },
- isEventDefSelected: function(eventDef) {
- // event references might change on refetchEvents(), while selectedEventInstance doesn't,
- // so compare IDs
- return this.selectedEventInstance && this.selectedEventInstance.def.id === eventDef.id;
- },
- /* Mouse / Touch Unselecting (time range & event unselection)
- ------------------------------------------------------------------------------------------------------------------*/
- // TODO: move consistently to down/start or up/end?
- // TODO: don't kill previous selection if touch scrolling
- handleDocumentMousedown: function(ev) {
- if (isPrimaryMouseButton(ev)) {
- this.processUnselect(ev);
- }
- },
- processUnselect: function(ev) {
- this.processRangeUnselect(ev);
- this.processEventUnselect(ev);
- },
- processRangeUnselect: function(ev) {
- var ignore;
- // is there a time-range selection?
- if (this.isSelected && this.opt('unselectAuto')) {
- // only unselect if the clicked element is not identical to or inside of an 'unselectCancel' element
- ignore = this.opt('unselectCancel');
- if (!ignore || !$(ev.target).closest(ignore).length) {
- this.unselect(ev);
- }
- }
- },
- processEventUnselect: function(ev) {
- if (this.selectedEventInstance) {
- if (!$(ev.target).closest('.fc-selected').length) {
- this.unselectEventInstance();
- }
- }
- },
- /* Day Click
- ------------------------------------------------------------------------------------------------------------------*/
- // Triggers handlers to 'dayClick'
- // Span has start/end of the clicked area. Only the start is useful.
- triggerDayClick: function(footprint, dayEl, ev) {
- var dateProfile = this.calendar.footprintToDateProfile(footprint); // abuse of "Event"DateProfile?
- this.publiclyTrigger('dayClick', {
- context: dayEl,
- args: [ dateProfile.start, ev, this ]
- });
- }
- });
- // responsible for populating data that DateComponent relies on
- View.watch('businessHours', [ 'rawBusinessHours', 'dateProfile' ], function(deps) {
- return new BusinessHours(
- deps.rawBusinessHours,
- deps.dateProfile.activeUnzonedRange,
- this.calendar
- );
- });
- View.watch('initialEvents', [ 'dateProfile' ], function(deps) {
- return this.fetchInitialEvents(deps.dateProfile);
- });
- View.watch('bindingEvents', [ 'initialEvents' ], function(deps) {
- this.handleEventsSet(deps.initialEvents);
- this.bindEventChanges();
- }, function() {
- this.unbindEventChanges();
- this.handleEventsUnset();
- });
- // legacy
- function convertEventsPayloadToLegacyArray(eventsPayload) {
- var legacyEvents = [];
- var id;
- var eventInstances;
- var i;
- for (id in eventsPayload) {
- eventInstances = eventsPayload[id].eventInstances;
- for (i = 0; i < eventInstances.length; i++) {
- legacyEvents.push(
- eventInstances[i].toLegacy()
- );
- }
- }
- return legacyEvents;
- }
|