|
|
@@ -631,6 +631,149 @@ var DateComponent = FC.DateComponent = Component.extend({
|
|
|
|
|
|
_getDateProfile: function() {
|
|
|
return this._getView().get('dateProfile');
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ // Generates HTML for an anchor to another view into the calendar.
|
|
|
+ // Will either generate an <a> tag or a non-clickable <span> tag, depending on enabled settings.
|
|
|
+ // `gotoOptions` can either be a moment input, or an object with the form:
|
|
|
+ // { date, type, forceOff }
|
|
|
+ // `type` is a view-type like "day" or "week". default value is "day".
|
|
|
+ // `attrs` and `innerHtml` are use to generate the rest of the HTML tag.
|
|
|
+ buildGotoAnchorHtml: function(gotoOptions, attrs, innerHtml) {
|
|
|
+ var date, type, forceOff;
|
|
|
+ var finalOptions;
|
|
|
+
|
|
|
+ if ($.isPlainObject(gotoOptions)) {
|
|
|
+ date = gotoOptions.date;
|
|
|
+ type = gotoOptions.type;
|
|
|
+ forceOff = gotoOptions.forceOff;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ date = gotoOptions; // a single moment input
|
|
|
+ }
|
|
|
+ date = FC.moment(date); // if a string, parse it
|
|
|
+
|
|
|
+ finalOptions = { // for serialization into the link
|
|
|
+ date: date.format('YYYY-MM-DD'),
|
|
|
+ type: type || 'day'
|
|
|
+ };
|
|
|
+
|
|
|
+ if (typeof attrs === 'string') {
|
|
|
+ innerHtml = attrs;
|
|
|
+ attrs = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ attrs = attrs ? ' ' + attrsToStr(attrs) : ''; // will have a leading space
|
|
|
+ innerHtml = innerHtml || '';
|
|
|
+
|
|
|
+ if (!forceOff && this.opt('navLinks')) {
|
|
|
+ return '<a' + attrs +
|
|
|
+ ' data-goto="' + htmlEscape(JSON.stringify(finalOptions)) + '">' +
|
|
|
+ innerHtml +
|
|
|
+ '</a>';
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return '<span' + attrs + '>' +
|
|
|
+ innerHtml +
|
|
|
+ '</span>';
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ getAllDayHtml: function() {
|
|
|
+ return this.opt('allDayHtml') || htmlEscape(this.opt('allDayText'));
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ // Computes HTML classNames for a single-day element
|
|
|
+ getDayClasses: function(date, noThemeHighlight) {
|
|
|
+ var view = this._getView();
|
|
|
+ var classes = [];
|
|
|
+ var today;
|
|
|
+
|
|
|
+ if (!this.dateProfile.activeUnzonedRange.containsDate(date)) {
|
|
|
+ classes.push('fc-disabled-day'); // TODO: jQuery UI theme?
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ classes.push('fc-' + dayIDs[date.day()]);
|
|
|
+
|
|
|
+ if (view.isDateInOtherMonth(date, this.dateProfile)) { // TODO: use DateComponent subclass somehow
|
|
|
+ classes.push('fc-other-month');
|
|
|
+ }
|
|
|
+
|
|
|
+ today = view.calendar.getNow();
|
|
|
+
|
|
|
+ if (date.isSame(today, 'day')) {
|
|
|
+ classes.push('fc-today');
|
|
|
+
|
|
|
+ if (noThemeHighlight !== true) {
|
|
|
+ classes.push(view.calendar.theme.getClass('today'));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (date < today) {
|
|
|
+ classes.push('fc-past');
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ classes.push('fc-future');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return classes;
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ // Utility for formatting a range. Accepts a range object, formatting string, and optional separator.
|
|
|
+ // Displays all-day ranges naturally, with an inclusive end. Takes the current isRTL into account.
|
|
|
+ // The timezones of the dates within `range` will be respected.
|
|
|
+ formatRange: function(range, isAllDay, formatStr, separator) {
|
|
|
+ var end = range.end;
|
|
|
+
|
|
|
+ if (isAllDay) {
|
|
|
+ end = end.clone().subtract(1); // convert to inclusive. last ms of previous day
|
|
|
+ }
|
|
|
+
|
|
|
+ return formatRange(range.start, end, formatStr, separator, this.isRTL);
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ // Compute the number of the give units in the "current" range.
|
|
|
+ // Will return a floating-point number. Won't round.
|
|
|
+ currentRangeAs: function(unit) {
|
|
|
+ return this._getDateProfile().currentUnzonedRange.as(unit);
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ // Returns the date range of the full days the given range visually appears to occupy.
|
|
|
+ // Returns a plain object with start/end, NOT an UnzonedRange!
|
|
|
+ computeDayRange: function(unzonedRange) {
|
|
|
+ var calendar = this._getCalendar();
|
|
|
+ var startDay = calendar.msToUtcMoment(unzonedRange.startMs, true); // the beginning of the day the range starts
|
|
|
+ var end = calendar.msToUtcMoment(unzonedRange.endMs);
|
|
|
+ var endTimeMS = +end.time(); // # of milliseconds into `endDay`
|
|
|
+ var endDay = end.clone().stripTime(); // the beginning of the day the range exclusively ends
|
|
|
+
|
|
|
+ // If the end time is actually inclusively part of the next day and is equal to or
|
|
|
+ // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`.
|
|
|
+ // Otherwise, leaving it as inclusive will cause it to exclude `endDay`.
|
|
|
+ if (endTimeMS && endTimeMS >= this.nextDayThreshold) {
|
|
|
+ endDay.add(1, 'days');
|
|
|
+ }
|
|
|
+
|
|
|
+ // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day.
|
|
|
+ if (endDay <= startDay) {
|
|
|
+ endDay = startDay.clone().add(1, 'days');
|
|
|
+ }
|
|
|
+
|
|
|
+ return { start: startDay, end: endDay };
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ // Does the given range visually appear to occupy more than one day?
|
|
|
+ isMultiDayRange: function(unzonedRange) {
|
|
|
+ var dayRange = this.computeDayRange(unzonedRange);
|
|
|
+
|
|
|
+ return dayRange.end.diff(dayRange.start, 'days') > 1;
|
|
|
}
|
|
|
|
|
|
});
|