|
|
@@ -15,7 +15,6 @@ TimeGrid.mixin({
|
|
|
businessContainerEls: null,
|
|
|
|
|
|
// arrays of different types of displayed segments
|
|
|
- fgSegs: null,
|
|
|
bgSegs: null,
|
|
|
helperSegs: null,
|
|
|
highlightSegs: null,
|
|
|
@@ -24,6 +23,49 @@ TimeGrid.mixin({
|
|
|
|
|
|
eventRenderUtilsClass: SegChronoComponentMixin.eventRenderUtilsClass.extend({
|
|
|
|
|
|
+ timeGrid: null,
|
|
|
+ fgSegs: null,
|
|
|
+
|
|
|
+
|
|
|
+ constructor: function(timeGrid) {
|
|
|
+ SegChronoComponentMixin.eventRenderUtilsClass.call(this, timeGrid);
|
|
|
+ this.timeGrid = timeGrid;
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ renderFgSegs: function(segs) {
|
|
|
+ segs = this.renderFgSegsIntoContainers(segs, this.timeGrid.fgContainerEls);
|
|
|
+
|
|
|
+ this.fgSegs = segs;
|
|
|
+
|
|
|
+ return segs; // needed for Grid::renderEvents
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ // Given an array of foreground segments, render a DOM element for each, computes position,
|
|
|
+ // and attaches to the column inner-container elements.
|
|
|
+ renderFgSegsIntoContainers: function(segs, containerEls) {
|
|
|
+ var segsByCol;
|
|
|
+ var col;
|
|
|
+
|
|
|
+ segs = this.renderFgSegEls(segs);
|
|
|
+ segsByCol = this.timeGrid.groupSegsByCol(segs);
|
|
|
+
|
|
|
+ for (col = 0; col < this.timeGrid.colCnt; col++) {
|
|
|
+ this.updateFgSegCoords(segsByCol[col]);
|
|
|
+ }
|
|
|
+
|
|
|
+ this.timeGrid.attachSegsByCol(segsByCol, containerEls);
|
|
|
+
|
|
|
+ return segs;
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ unrenderFgSegs: function() {
|
|
|
+ this.timeGrid.unrenderNamedSegs('fgSegs');
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
// Computes a default event time formatting string if `timeFormat` is not explicitly defined
|
|
|
computeEventTimeFormat: function() {
|
|
|
return this.opt('noMeridiemTimeFormat'); // like "6:30" (no AM/PM)
|
|
|
@@ -113,6 +155,154 @@ TimeGrid.mixin({
|
|
|
''
|
|
|
) +
|
|
|
'</a>';
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ // Given segments that are assumed to all live in the *same column*,
|
|
|
+ // compute their verical/horizontal coordinates and assign to their elements.
|
|
|
+ updateFgSegCoords: function(segs) {
|
|
|
+ this.timeGrid.computeSegVerticals(segs); // horizontals relies on this
|
|
|
+ this.computeFgSegHorizontals(segs); // compute horizontal coordinates, z-index's, and reorder the array
|
|
|
+ this.timeGrid.assignSegVerticals(segs);
|
|
|
+ this.assignFgSegHorizontals(segs);
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ // Given an array of segments that are all in the same column, sets the backwardCoord and forwardCoord on each.
|
|
|
+ // NOTE: Also reorders the given array by date!
|
|
|
+ computeFgSegHorizontals: function(segs) {
|
|
|
+ var levels;
|
|
|
+ var level0;
|
|
|
+ var i;
|
|
|
+
|
|
|
+ this.sortEventSegs(segs); // order by certain criteria
|
|
|
+ levels = buildSlotSegLevels(segs);
|
|
|
+ computeForwardSlotSegs(levels);
|
|
|
+
|
|
|
+ if ((level0 = levels[0])) {
|
|
|
+
|
|
|
+ for (i = 0; i < level0.length; i++) {
|
|
|
+ computeSlotSegPressures(level0[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < level0.length; i++) {
|
|
|
+ this.computeFgSegForwardBack(level0[i], 0, 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ // Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range
|
|
|
+ // from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and
|
|
|
+ // seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left.
|
|
|
+ //
|
|
|
+ // The segment might be part of a "series", which means consecutive segments with the same pressure
|
|
|
+ // who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of
|
|
|
+ // segments behind this one in the current series, and `seriesBackwardCoord` is the starting
|
|
|
+ // coordinate of the first segment in the series.
|
|
|
+ computeFgSegForwardBack: function(seg, seriesBackwardPressure, seriesBackwardCoord) {
|
|
|
+ var forwardSegs = seg.forwardSegs;
|
|
|
+ var i;
|
|
|
+
|
|
|
+ if (seg.forwardCoord === undefined) { // not already computed
|
|
|
+
|
|
|
+ if (!forwardSegs.length) {
|
|
|
+
|
|
|
+ // if there are no forward segments, this segment should butt up against the edge
|
|
|
+ seg.forwardCoord = 1;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+
|
|
|
+ // sort highest pressure first
|
|
|
+ this.sortForwardSegs(forwardSegs);
|
|
|
+
|
|
|
+ // this segment's forwardCoord will be calculated from the backwardCoord of the
|
|
|
+ // highest-pressure forward segment.
|
|
|
+ this.computeFgSegForwardBack(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord);
|
|
|
+ seg.forwardCoord = forwardSegs[0].backwardCoord;
|
|
|
+ }
|
|
|
+
|
|
|
+ // calculate the backwardCoord from the forwardCoord. consider the series
|
|
|
+ seg.backwardCoord = seg.forwardCoord -
|
|
|
+ (seg.forwardCoord - seriesBackwardCoord) / // available width for series
|
|
|
+ (seriesBackwardPressure + 1); // # of segments in the series
|
|
|
+
|
|
|
+ // use this segment's coordinates to computed the coordinates of the less-pressurized
|
|
|
+ // forward segments
|
|
|
+ for (i=0; i<forwardSegs.length; i++) {
|
|
|
+ this.computeFgSegForwardBack(forwardSegs[i], 0, seg.forwardCoord);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ sortForwardSegs: function(forwardSegs) {
|
|
|
+ forwardSegs.sort(proxy(this, 'compareForwardSegs'));
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ // A cmp function for determining which forward segment to rely on more when computing coordinates.
|
|
|
+ compareForwardSegs: function(seg1, seg2) {
|
|
|
+ // put higher-pressure first
|
|
|
+ return seg2.forwardPressure - seg1.forwardPressure ||
|
|
|
+ // put segments that are closer to initial edge first (and favor ones with no coords yet)
|
|
|
+ (seg1.backwardCoord || 0) - (seg2.backwardCoord || 0) ||
|
|
|
+ // do normal sorting...
|
|
|
+ this.compareEventSegs(seg1, seg2);
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ // Given foreground event segments that have already had their position coordinates computed,
|
|
|
+ // assigns position-related CSS values to their elements.
|
|
|
+ assignFgSegHorizontals: function(segs) {
|
|
|
+ var i, seg;
|
|
|
+
|
|
|
+ for (i = 0; i < segs.length; i++) {
|
|
|
+ seg = segs[i];
|
|
|
+ seg.el.css(this.generateFgSegHorizontalCss(seg));
|
|
|
+
|
|
|
+ // if the height is short, add a className for alternate styling
|
|
|
+ if (seg.bottom - seg.top < 30) {
|
|
|
+ seg.el.addClass('fc-short');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ // Generates an object with CSS properties/values that should be applied to an event segment element.
|
|
|
+ // Contains important positioning-related properties that should be applied to any event element, customized or not.
|
|
|
+ generateFgSegHorizontalCss: function(seg) {
|
|
|
+ var shouldOverlap = this.opt('slotEventOverlap');
|
|
|
+ var backwardCoord = seg.backwardCoord; // the left side if LTR. the right side if RTL. floating-point
|
|
|
+ var forwardCoord = seg.forwardCoord; // the right side if LTR. the left side if RTL. floating-point
|
|
|
+ var props = this.timeGrid.generateSegVerticalCss(seg); // get top/bottom first
|
|
|
+ var left; // amount of space from left edge, a fraction of the total width
|
|
|
+ var right; // amount of space from right edge, a fraction of the total width
|
|
|
+
|
|
|
+ if (shouldOverlap) {
|
|
|
+ // double the width, but don't go beyond the maximum forward coordinate (1.0)
|
|
|
+ forwardCoord = Math.min(1, backwardCoord + (forwardCoord - backwardCoord) * 2);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.timeGrid.isRTL) {
|
|
|
+ left = 1 - forwardCoord;
|
|
|
+ right = backwardCoord;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ left = backwardCoord;
|
|
|
+ right = 1 - forwardCoord;
|
|
|
+ }
|
|
|
+
|
|
|
+ props.zIndex = seg.level + 1; // convert from 0-base to 1-based
|
|
|
+ props.left = left * 100 + '%';
|
|
|
+ props.right = right * 100 + '%';
|
|
|
+
|
|
|
+ if (shouldOverlap && seg.forwardPressure) {
|
|
|
+ // add padding to the edge so that forward stacked events don't cover the resizer's icon
|
|
|
+ props[this.isRTL ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width
|
|
|
+ }
|
|
|
+
|
|
|
+ return props;
|
|
|
}
|
|
|
|
|
|
}),
|
|
|
@@ -157,22 +347,6 @@ TimeGrid.mixin({
|
|
|
},
|
|
|
|
|
|
|
|
|
- /* Foreground Events
|
|
|
- ------------------------------------------------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-
|
|
|
- renderFgSegs: function(segs) {
|
|
|
- segs = this.renderFgSegsIntoContainers(segs, this.fgContainerEls);
|
|
|
- this.fgSegs = segs;
|
|
|
- return segs; // needed for Grid::renderEvents
|
|
|
- },
|
|
|
-
|
|
|
-
|
|
|
- unrenderFgSegs: function() {
|
|
|
- this.unrenderNamedSegs('fgSegs');
|
|
|
- },
|
|
|
-
|
|
|
-
|
|
|
/* Foreground Helper Events
|
|
|
------------------------------------------------------------------------------------------------------------------*/
|
|
|
|
|
|
@@ -182,7 +356,7 @@ TimeGrid.mixin({
|
|
|
var i, seg;
|
|
|
var sourceEl;
|
|
|
|
|
|
- segs = this.renderFgSegsIntoContainers(segs, this.helperContainerEls);
|
|
|
+ segs = this.eventRenderUtils.renderFgSegsIntoContainers(segs, this.helperContainerEls);
|
|
|
|
|
|
// Try to make the segment that is in the same row as sourceSeg look the same
|
|
|
for (i = 0; i < segs.length; i++) {
|
|
|
@@ -315,30 +489,6 @@ TimeGrid.mixin({
|
|
|
},
|
|
|
|
|
|
|
|
|
-
|
|
|
- /* Foreground Event Rendering Utils
|
|
|
- ------------------------------------------------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-
|
|
|
- // Given an array of foreground segments, render a DOM element for each, computes position,
|
|
|
- // and attaches to the column inner-container elements.
|
|
|
- renderFgSegsIntoContainers: function(segs, containerEls) {
|
|
|
- var segsByCol;
|
|
|
- var col;
|
|
|
-
|
|
|
- segs = this.eventRenderUtils.renderFgSegEls(segs);
|
|
|
- segsByCol = this.groupSegsByCol(segs);
|
|
|
-
|
|
|
- for (col = 0; col < this.colCnt; col++) {
|
|
|
- this.updateFgSegCoords(segsByCol[col]);
|
|
|
- }
|
|
|
-
|
|
|
- this.attachSegsByCol(segsByCol, containerEls);
|
|
|
-
|
|
|
- return segs;
|
|
|
- },
|
|
|
-
|
|
|
-
|
|
|
/* Seg Position Utils
|
|
|
------------------------------------------------------------------------------------------------------------------*/
|
|
|
|
|
|
@@ -384,158 +534,6 @@ TimeGrid.mixin({
|
|
|
top: seg.top,
|
|
|
bottom: -seg.bottom // flipped because needs to be space beyond bottom edge of event container
|
|
|
};
|
|
|
- },
|
|
|
-
|
|
|
-
|
|
|
- /* Foreground Event Positioning Utils
|
|
|
- ------------------------------------------------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-
|
|
|
- // Given segments that are assumed to all live in the *same column*,
|
|
|
- // compute their verical/horizontal coordinates and assign to their elements.
|
|
|
- updateFgSegCoords: function(segs) {
|
|
|
- this.computeSegVerticals(segs); // horizontals relies on this
|
|
|
- this.computeFgSegHorizontals(segs); // compute horizontal coordinates, z-index's, and reorder the array
|
|
|
- this.assignSegVerticals(segs);
|
|
|
- this.assignFgSegHorizontals(segs);
|
|
|
- },
|
|
|
-
|
|
|
-
|
|
|
- // Given an array of segments that are all in the same column, sets the backwardCoord and forwardCoord on each.
|
|
|
- // NOTE: Also reorders the given array by date!
|
|
|
- computeFgSegHorizontals: function(segs) {
|
|
|
- var levels;
|
|
|
- var level0;
|
|
|
- var i;
|
|
|
-
|
|
|
- this.sortEventSegs(segs); // order by certain criteria
|
|
|
- levels = buildSlotSegLevels(segs);
|
|
|
- computeForwardSlotSegs(levels);
|
|
|
-
|
|
|
- if ((level0 = levels[0])) {
|
|
|
-
|
|
|
- for (i = 0; i < level0.length; i++) {
|
|
|
- computeSlotSegPressures(level0[i]);
|
|
|
- }
|
|
|
-
|
|
|
- for (i = 0; i < level0.length; i++) {
|
|
|
- this.computeFgSegForwardBack(level0[i], 0, 0);
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
-
|
|
|
- // Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range
|
|
|
- // from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and
|
|
|
- // seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left.
|
|
|
- //
|
|
|
- // The segment might be part of a "series", which means consecutive segments with the same pressure
|
|
|
- // who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of
|
|
|
- // segments behind this one in the current series, and `seriesBackwardCoord` is the starting
|
|
|
- // coordinate of the first segment in the series.
|
|
|
- computeFgSegForwardBack: function(seg, seriesBackwardPressure, seriesBackwardCoord) {
|
|
|
- var forwardSegs = seg.forwardSegs;
|
|
|
- var i;
|
|
|
-
|
|
|
- if (seg.forwardCoord === undefined) { // not already computed
|
|
|
-
|
|
|
- if (!forwardSegs.length) {
|
|
|
-
|
|
|
- // if there are no forward segments, this segment should butt up against the edge
|
|
|
- seg.forwardCoord = 1;
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- // sort highest pressure first
|
|
|
- this.sortForwardSegs(forwardSegs);
|
|
|
-
|
|
|
- // this segment's forwardCoord will be calculated from the backwardCoord of the
|
|
|
- // highest-pressure forward segment.
|
|
|
- this.computeFgSegForwardBack(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord);
|
|
|
- seg.forwardCoord = forwardSegs[0].backwardCoord;
|
|
|
- }
|
|
|
-
|
|
|
- // calculate the backwardCoord from the forwardCoord. consider the series
|
|
|
- seg.backwardCoord = seg.forwardCoord -
|
|
|
- (seg.forwardCoord - seriesBackwardCoord) / // available width for series
|
|
|
- (seriesBackwardPressure + 1); // # of segments in the series
|
|
|
-
|
|
|
- // use this segment's coordinates to computed the coordinates of the less-pressurized
|
|
|
- // forward segments
|
|
|
- for (i=0; i<forwardSegs.length; i++) {
|
|
|
- this.computeFgSegForwardBack(forwardSegs[i], 0, seg.forwardCoord);
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
-
|
|
|
- sortForwardSegs: function(forwardSegs) {
|
|
|
- forwardSegs.sort(proxy(this, 'compareForwardSegs'));
|
|
|
- },
|
|
|
-
|
|
|
-
|
|
|
- // A cmp function for determining which forward segment to rely on more when computing coordinates.
|
|
|
- compareForwardSegs: function(seg1, seg2) {
|
|
|
- // put higher-pressure first
|
|
|
- return seg2.forwardPressure - seg1.forwardPressure ||
|
|
|
- // put segments that are closer to initial edge first (and favor ones with no coords yet)
|
|
|
- (seg1.backwardCoord || 0) - (seg2.backwardCoord || 0) ||
|
|
|
- // do normal sorting...
|
|
|
- this.compareEventSegs(seg1, seg2);
|
|
|
- },
|
|
|
-
|
|
|
-
|
|
|
- // Given foreground event segments that have already had their position coordinates computed,
|
|
|
- // assigns position-related CSS values to their elements.
|
|
|
- assignFgSegHorizontals: function(segs) {
|
|
|
- var i, seg;
|
|
|
-
|
|
|
- for (i = 0; i < segs.length; i++) {
|
|
|
- seg = segs[i];
|
|
|
- seg.el.css(this.generateFgSegHorizontalCss(seg));
|
|
|
-
|
|
|
- // if the height is short, add a className for alternate styling
|
|
|
- if (seg.bottom - seg.top < 30) {
|
|
|
- seg.el.addClass('fc-short');
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
-
|
|
|
- // Generates an object with CSS properties/values that should be applied to an event segment element.
|
|
|
- // Contains important positioning-related properties that should be applied to any event element, customized or not.
|
|
|
- generateFgSegHorizontalCss: function(seg) {
|
|
|
- var shouldOverlap = this.opt('slotEventOverlap');
|
|
|
- var backwardCoord = seg.backwardCoord; // the left side if LTR. the right side if RTL. floating-point
|
|
|
- var forwardCoord = seg.forwardCoord; // the right side if LTR. the left side if RTL. floating-point
|
|
|
- var props = this.generateSegVerticalCss(seg); // get top/bottom first
|
|
|
- var left; // amount of space from left edge, a fraction of the total width
|
|
|
- var right; // amount of space from right edge, a fraction of the total width
|
|
|
-
|
|
|
- if (shouldOverlap) {
|
|
|
- // double the width, but don't go beyond the maximum forward coordinate (1.0)
|
|
|
- forwardCoord = Math.min(1, backwardCoord + (forwardCoord - backwardCoord) * 2);
|
|
|
- }
|
|
|
-
|
|
|
- if (this.isRTL) {
|
|
|
- left = 1 - forwardCoord;
|
|
|
- right = backwardCoord;
|
|
|
- }
|
|
|
- else {
|
|
|
- left = backwardCoord;
|
|
|
- right = 1 - forwardCoord;
|
|
|
- }
|
|
|
-
|
|
|
- props.zIndex = seg.level + 1; // convert from 0-base to 1-based
|
|
|
- props.left = left * 100 + '%';
|
|
|
- props.right = right * 100 + '%';
|
|
|
-
|
|
|
- if (shouldOverlap && seg.forwardPressure) {
|
|
|
- // add padding to the edge so that forward stacked events don't cover the resizer's icon
|
|
|
- props[this.isRTL ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width
|
|
|
- }
|
|
|
-
|
|
|
- return props;
|
|
|
}
|
|
|
|
|
|
});
|