fullcalendar.io-rails 2.3.2 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3e0c3f8226be35a93a659007d0fa20fd66a6ff65
4
- data.tar.gz: ae678572c60154cf91d4519c95315749b13fa9e8
3
+ metadata.gz: 3e95fa760c253b1bcbbdaacc80fd045d1126a39c
4
+ data.tar.gz: 44c65ae292b3c364da1454c5a7838185105f2a69
5
5
  SHA512:
6
- metadata.gz: ac1647ad46ab72f4aedd60e60825dd7cbb1e76a255969f4a0bc2700e04772e0e2d6e213a3e17b121ae62f3712963cc9e036e35cf38e28cb809ef85e093477d4e
7
- data.tar.gz: 1b987ab4011b943ac1fef1f48f7b9111de448f46efbd0abe68cf62fa52bc4fd46072d9aa66a5ebbb56f58849890e81251176338a7ae0128411d164b4c2a28cb8
6
+ metadata.gz: 0aae9e839f7247dac108bb1b750543e22dc486f377ca34b70026670f2b7e103da8e57639158cab448d6ae6ddc9bfceccc469d43e07a6da7ee4b235fa1d2f2299
7
+ data.tar.gz: 28ae98115d58895d0f313f312194b4f9e293ba4e0ce6fab912d6df267ec9b7ab476b8dfffdf71ad44794a87dd9013b7787267dfcd829090812ad3ca07d5e6132
@@ -1,5 +1,5 @@
1
1
  module Fullcalendario
2
2
  module Rails
3
- VERSION = "2.3.2"
3
+ VERSION = "2.4.0"
4
4
  end
5
5
  end
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * FullCalendar v2.3.2
2
+ * FullCalendar v2.4.0
3
3
  * Docs & License: http://fullcalendar.io/
4
4
  * (c) 2015 Adam Shaw
5
5
  */
@@ -18,7 +18,7 @@
18
18
 
19
19
  ;;
20
20
 
21
- var fc = $.fullCalendar = { version: "2.3.2" };
21
+ var fc = $.fullCalendar = { version: "2.4.0" };
22
22
  var fcViews = fc.views = {};
23
23
 
24
24
 
@@ -419,6 +419,7 @@ function isPrimaryMouseButton(ev) {
419
419
  /* Geometry
420
420
  ----------------------------------------------------------------------------------------------------------------------*/
421
421
 
422
+ fc.intersectRects = intersectRects;
422
423
 
423
424
  // Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false
424
425
  function intersectRects(rect1, rect2) {
@@ -463,6 +464,90 @@ function diffPoints(point1, point2) {
463
464
  }
464
465
 
465
466
 
467
+ /* Object Ordering by Field
468
+ ----------------------------------------------------------------------------------------------------------------------*/
469
+
470
+ fc.parseFieldSpecs = parseFieldSpecs;
471
+ fc.compareByFieldSpecs = compareByFieldSpecs;
472
+ fc.compareByFieldSpec = compareByFieldSpec;
473
+ fc.flexibleCompare = flexibleCompare;
474
+
475
+
476
+ function parseFieldSpecs(input) {
477
+ var specs = [];
478
+ var tokens = [];
479
+ var i, token;
480
+
481
+ if (typeof input === 'string') {
482
+ tokens = input.split(/\s*,\s*/);
483
+ }
484
+ else if (typeof input === 'function') {
485
+ tokens = [ input ];
486
+ }
487
+ else if ($.isArray(input)) {
488
+ tokens = input;
489
+ }
490
+
491
+ for (i = 0; i < tokens.length; i++) {
492
+ token = tokens[i];
493
+
494
+ if (typeof token === 'string') {
495
+ specs.push(
496
+ token.charAt(0) == '-' ?
497
+ { field: token.substring(1), order: -1 } :
498
+ { field: token, order: 1 }
499
+ );
500
+ }
501
+ else if (typeof token === 'function') {
502
+ specs.push({ func: token });
503
+ }
504
+ }
505
+
506
+ return specs;
507
+ }
508
+
509
+
510
+ function compareByFieldSpecs(obj1, obj2, fieldSpecs) {
511
+ var i;
512
+ var cmp;
513
+
514
+ for (i = 0; i < fieldSpecs.length; i++) {
515
+ cmp = compareByFieldSpec(obj1, obj2, fieldSpecs[i]);
516
+ if (cmp) {
517
+ return cmp;
518
+ }
519
+ }
520
+
521
+ return 0;
522
+ }
523
+
524
+
525
+ function compareByFieldSpec(obj1, obj2, fieldSpec) {
526
+ if (fieldSpec.func) {
527
+ return fieldSpec.func(obj1, obj2);
528
+ }
529
+ return flexibleCompare(obj1[fieldSpec.field], obj2[fieldSpec.field]) *
530
+ (fieldSpec.order || 1);
531
+ }
532
+
533
+
534
+ function flexibleCompare(a, b) {
535
+ if (!a && !b) {
536
+ return 0;
537
+ }
538
+ if (b == null) {
539
+ return -1;
540
+ }
541
+ if (a == null) {
542
+ return 1;
543
+ }
544
+ if ($.type(a) === 'string' || $.type(b) === 'string') {
545
+ return String(a).localeCompare(String(b));
546
+ }
547
+ return a - b;
548
+ }
549
+
550
+
466
551
  /* FullCalendar-specific Misc Utilities
467
552
  ----------------------------------------------------------------------------------------------------------------------*/
468
553
 
@@ -512,6 +597,9 @@ function intersectionToSeg(subjectRange, constraintRange) {
512
597
  ----------------------------------------------------------------------------------------------------------------------*/
513
598
 
514
599
  fc.computeIntervalUnit = computeIntervalUnit;
600
+ fc.divideRangeByDuration = divideRangeByDuration;
601
+ fc.divideDurationByDuration = divideDurationByDuration;
602
+ fc.multiplyDuration = multiplyDuration;
515
603
  fc.durationHasTime = durationHasTime;
516
604
 
517
605
  var dayIDs = [ 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat' ];
@@ -583,6 +671,55 @@ function computeRangeAs(unit, start, end) {
583
671
  }
584
672
 
585
673
 
674
+ // Intelligently divides a range (specified by a start/end params) by a duration
675
+ function divideRangeByDuration(start, end, dur) {
676
+ var months;
677
+
678
+ if (durationHasTime(dur)) {
679
+ return (end - start) / dur;
680
+ }
681
+ months = dur.asMonths();
682
+ if (Math.abs(months) >= 1 && isInt(months)) {
683
+ return end.diff(start, 'months', true) / months;
684
+ }
685
+ return end.diff(start, 'days', true) / dur.asDays();
686
+ }
687
+
688
+
689
+ // Intelligently divides one duration by another
690
+ function divideDurationByDuration(dur1, dur2) {
691
+ var months1, months2;
692
+
693
+ if (durationHasTime(dur1) || durationHasTime(dur2)) {
694
+ return dur1 / dur2;
695
+ }
696
+ months1 = dur1.asMonths();
697
+ months2 = dur2.asMonths();
698
+ if (
699
+ Math.abs(months1) >= 1 && isInt(months1) &&
700
+ Math.abs(months2) >= 1 && isInt(months2)
701
+ ) {
702
+ return months1 / months2;
703
+ }
704
+ return dur1.asDays() / dur2.asDays();
705
+ }
706
+
707
+
708
+ // Intelligently multiplies a duration by a number
709
+ function multiplyDuration(dur, n) {
710
+ var months;
711
+
712
+ if (durationHasTime(dur)) {
713
+ return moment.duration(dur * n);
714
+ }
715
+ months = dur.asMonths();
716
+ if (Math.abs(months) >= 1 && isInt(months)) {
717
+ return moment.duration({ months: months * n });
718
+ }
719
+ return moment.duration({ days: dur.asDays() * n });
720
+ }
721
+
722
+
586
723
  // Returns a boolean about whether the given duration has any time parts (hours/minutes/seconds/ms)
587
724
  function durationHasTime(dur) {
588
725
  return Boolean(dur.hours() || dur.minutes() || dur.seconds() || dur.milliseconds());
@@ -600,6 +737,29 @@ function isTimeString(str) {
600
737
  }
601
738
 
602
739
 
740
+ /* Logging and Debug
741
+ ----------------------------------------------------------------------------------------------------------------------*/
742
+
743
+ fc.log = function() {
744
+ var console = window.console;
745
+
746
+ if (console && console.log) {
747
+ return console.log.apply(console, arguments);
748
+ }
749
+ };
750
+
751
+ fc.warn = function() {
752
+ var console = window.console;
753
+
754
+ if (console && console.warn) {
755
+ return console.warn.apply(console, arguments);
756
+ }
757
+ else {
758
+ return fc.log.apply(fc, arguments);
759
+ }
760
+ };
761
+
762
+
603
763
  /* General Utilities
604
764
  ----------------------------------------------------------------------------------------------------------------------*/
605
765
 
@@ -1592,6 +1752,59 @@ Class.mixin = function(members) {
1592
1752
  };
1593
1753
  ;;
1594
1754
 
1755
+ var Emitter = fc.Emitter = Class.extend({
1756
+
1757
+ callbackHash: null,
1758
+
1759
+
1760
+ on: function(name, callback) {
1761
+ this.getCallbacks(name).add(callback);
1762
+ return this; // for chaining
1763
+ },
1764
+
1765
+
1766
+ off: function(name, callback) {
1767
+ this.getCallbacks(name).remove(callback);
1768
+ return this; // for chaining
1769
+ },
1770
+
1771
+
1772
+ trigger: function(name) { // args...
1773
+ var args = Array.prototype.slice.call(arguments, 1);
1774
+
1775
+ this.triggerWith(name, this, args);
1776
+
1777
+ return this; // for chaining
1778
+ },
1779
+
1780
+
1781
+ triggerWith: function(name, context, args) {
1782
+ var callbacks = this.getCallbacks(name);
1783
+
1784
+ callbacks.fireWith(context, args);
1785
+
1786
+ return this; // for chaining
1787
+ },
1788
+
1789
+
1790
+ getCallbacks: function(name) {
1791
+ var callbacks;
1792
+
1793
+ if (!this.callbackHash) {
1794
+ this.callbackHash = {};
1795
+ }
1796
+
1797
+ callbacks = this.callbackHash[name];
1798
+ if (!callbacks) {
1799
+ callbacks = this.callbackHash[name] = $.Callbacks();
1800
+ }
1801
+
1802
+ return callbacks;
1803
+ }
1804
+
1805
+ });
1806
+ ;;
1807
+
1595
1808
  /* A rectangular panel that is absolutely positioned over other content
1596
1809
  ------------------------------------------------------------------------------------------------------------------------
1597
1810
  Options:
@@ -4389,6 +4602,21 @@ Grid.mixin({
4389
4602
  }
4390
4603
 
4391
4604
  return segs;
4605
+ },
4606
+
4607
+
4608
+ sortSegs: function(segs) {
4609
+ segs.sort(proxy(this, 'compareSegs'));
4610
+ },
4611
+
4612
+
4613
+ // A cmp function for determining which segments should take visual priority
4614
+ // DOES NOT WORK ON INVERTED BACKGROUND EVENTS because they have no eventStartMS/eventDurationMS
4615
+ compareSegs: function(seg1, seg2) {
4616
+ return seg1.eventStartMS - seg2.eventStartMS || // earlier events go first
4617
+ seg2.eventDurationMS - seg1.eventDurationMS || // tie? longer events go first
4618
+ seg2.event.allDay - seg1.event.allDay || // tie? put all-day events first (booleans cast to 0/1)
4619
+ compareByFieldSpecs(seg1.event, seg2.event, this.view.eventOrderSpecs);
4392
4620
  }
4393
4621
 
4394
4622
  });
@@ -4433,18 +4661,6 @@ function compareNormalRanges(range1, range2) {
4433
4661
  }
4434
4662
 
4435
4663
 
4436
- // A cmp function for determining which segments should take visual priority
4437
- // DOES NOT WORK ON INVERTED BACKGROUND EVENTS because they have no eventStartMS/eventDurationMS
4438
- function compareSegs(seg1, seg2) {
4439
- return seg1.eventStartMS - seg2.eventStartMS || // earlier events go first
4440
- seg2.eventDurationMS - seg1.eventDurationMS || // tie? longer events go first
4441
- seg2.event.allDay - seg1.event.allDay || // tie? put all-day events first (booleans cast to 0/1)
4442
- (seg1.event.title || '').localeCompare(seg2.event.title); // tie? alphabetically by title
4443
- }
4444
-
4445
- fc.compareSegs = compareSegs; // export
4446
-
4447
-
4448
4664
  /* External-Dragging-Element Data
4449
4665
  ----------------------------------------------------------------------------------------------------------------------*/
4450
4666
 
@@ -5220,7 +5436,7 @@ DayGrid.mixin({
5220
5436
 
5221
5437
  // Give preference to elements with certain criteria, so they have
5222
5438
  // a chance to be closer to the top.
5223
- segs.sort(compareSegs);
5439
+ this.sortSegs(segs);
5224
5440
 
5225
5441
  for (i = 0; i < segs.length; i++) {
5226
5442
  seg = segs[i];
@@ -5621,7 +5837,7 @@ DayGrid.mixin({
5621
5837
  );
5622
5838
 
5623
5839
  // force an order because eventsToSegs doesn't guarantee one
5624
- segs.sort(compareSegs);
5840
+ this.sortSegs(segs);
5625
5841
 
5626
5842
  return segs;
5627
5843
  },
@@ -5673,7 +5889,8 @@ var TimeGrid = Grid.extend({
5673
5889
  minTime: null, // Duration object that denotes the first visible time of any given day
5674
5890
  maxTime: null, // Duration object that denotes the exclusive visible end time of any given day
5675
5891
  colDates: null, // whole-day dates for each column. left to right
5676
- axisFormat: null, // formatting string for times running along vertical axis
5892
+ labelFormat: null, // formatting string for times running along vertical axis
5893
+ labelInterval: null, // duration of how often a label should be displayed for a slot
5677
5894
 
5678
5895
  dayEls: null, // cells elements in the day-row background
5679
5896
  slatEls: null, // elements running horizontally across all columns
@@ -5734,29 +5951,28 @@ var TimeGrid = Grid.extend({
5734
5951
  var view = this.view;
5735
5952
  var isRTL = this.isRTL;
5736
5953
  var html = '';
5737
- var slotNormal = this.slotDuration.asMinutes() % 15 === 0;
5738
5954
  var slotTime = moment.duration(+this.minTime); // wish there was .clone() for durations
5739
5955
  var slotDate; // will be on the view's first day, but we only care about its time
5740
- var minutes;
5956
+ var isLabeled;
5741
5957
  var axisHtml;
5742
5958
 
5743
5959
  // Calculate the time for each slot
5744
5960
  while (slotTime < this.maxTime) {
5745
- slotDate = this.start.clone().time(slotTime); // will be in UTC but that's good. to avoid DST issues
5746
- minutes = slotDate.minutes();
5961
+ slotDate = this.start.clone().time(slotTime); // after .time() will be in UTC. but that's good, avoids DST issues
5962
+ isLabeled = isInt(divideDurationByDuration(slotTime, this.labelInterval));
5747
5963
 
5748
5964
  axisHtml =
5749
5965
  '<td class="fc-axis fc-time ' + view.widgetContentClass + '" ' + view.axisStyleAttr() + '>' +
5750
- ((!slotNormal || !minutes) ? // if irregular slot duration, or on the hour, then display the time
5966
+ (isLabeled ?
5751
5967
  '<span>' + // for matchCellWidths
5752
- htmlEscape(slotDate.format(this.axisFormat)) +
5968
+ htmlEscape(slotDate.format(this.labelFormat)) +
5753
5969
  '</span>' :
5754
5970
  ''
5755
5971
  ) +
5756
5972
  '</td>';
5757
5973
 
5758
5974
  html +=
5759
- '<tr ' + (!minutes ? '' : 'class="fc-minor"') + '>' +
5975
+ '<tr ' + (isLabeled ? '' : 'class="fc-minor"') + '>' +
5760
5976
  (!isRTL ? axisHtml : '') +
5761
5977
  '<td class="' + view.widgetContentClass + '"/>' +
5762
5978
  (isRTL ? axisHtml : '') +
@@ -5778,6 +5994,7 @@ var TimeGrid = Grid.extend({
5778
5994
  var view = this.view;
5779
5995
  var slotDuration = view.opt('slotDuration');
5780
5996
  var snapDuration = view.opt('snapDuration');
5997
+ var input;
5781
5998
 
5782
5999
  slotDuration = moment.duration(slotDuration);
5783
6000
  snapDuration = snapDuration ? moment.duration(snapDuration) : slotDuration;
@@ -5789,7 +6006,41 @@ var TimeGrid = Grid.extend({
5789
6006
  this.minTime = moment.duration(view.opt('minTime'));
5790
6007
  this.maxTime = moment.duration(view.opt('maxTime'));
5791
6008
 
5792
- this.axisFormat = view.opt('axisFormat') || view.opt('smallTimeFormat');
6009
+ // might be an array value (for TimelineView).
6010
+ // if so, getting the most granular entry (the last one probably).
6011
+ input = view.opt('slotLabelFormat');
6012
+ if ($.isArray(input)) {
6013
+ input = input[input.length - 1];
6014
+ }
6015
+
6016
+ this.labelFormat =
6017
+ input ||
6018
+ view.opt('axisFormat') || // deprecated
6019
+ view.opt('smallTimeFormat'); // the computed default
6020
+
6021
+ input = view.opt('slotLabelInterval');
6022
+ this.labelInterval = input ?
6023
+ moment.duration(input) :
6024
+ this.computeLabelInterval(slotDuration);
6025
+ },
6026
+
6027
+
6028
+ // Computes an automatic value for slotLabelInterval
6029
+ computeLabelInterval: function(slotDuration) {
6030
+ var i;
6031
+ var labelInterval;
6032
+ var slotsPerLabel;
6033
+
6034
+ // find the smallest stock label interval that results in more than one slots-per-label
6035
+ for (i = AGENDA_STOCK_SUB_DURATIONS.length - 1; i >= 0; i--) {
6036
+ labelInterval = moment.duration(AGENDA_STOCK_SUB_DURATIONS[i]);
6037
+ slotsPerLabel = divideDurationByDuration(labelInterval, slotDuration);
6038
+ if (isInt(slotsPerLabel) && slotsPerLabel > 1) {
6039
+ return labelInterval;
6040
+ }
6041
+ }
6042
+
6043
+ return moment.duration(slotDuration); // fall back. clone
5793
6044
  },
5794
6045
 
5795
6046
 
@@ -6209,7 +6460,7 @@ TimeGrid.mixin({
6209
6460
 
6210
6461
  for (col = 0; col < segCols.length; col++) { // iterate each column grouping
6211
6462
  colSegs = segCols[col];
6212
- placeSlotSegs(colSegs); // compute horizontal coordinates, z-index's, and reorder the array
6463
+ this.placeSlotSegs(colSegs); // compute horizontal coordinates, z-index's, and reorder the array
6213
6464
 
6214
6465
  containerEl = $('<div class="fc-event-container"/>');
6215
6466
 
@@ -6235,6 +6486,74 @@ TimeGrid.mixin({
6235
6486
  },
6236
6487
 
6237
6488
 
6489
+ // Given an array of segments that are all in the same column, sets the backwardCoord and forwardCoord on each.
6490
+ // NOTE: Also reorders the given array by date!
6491
+ placeSlotSegs: function(segs) {
6492
+ var levels;
6493
+ var level0;
6494
+ var i;
6495
+
6496
+ this.sortSegs(segs); // order by date
6497
+ levels = buildSlotSegLevels(segs);
6498
+ computeForwardSlotSegs(levels);
6499
+
6500
+ if ((level0 = levels[0])) {
6501
+
6502
+ for (i = 0; i < level0.length; i++) {
6503
+ computeSlotSegPressures(level0[i]);
6504
+ }
6505
+
6506
+ for (i = 0; i < level0.length; i++) {
6507
+ this.computeSlotSegCoords(level0[i], 0, 0);
6508
+ }
6509
+ }
6510
+ },
6511
+
6512
+
6513
+ // Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range
6514
+ // from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and
6515
+ // seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left.
6516
+ //
6517
+ // The segment might be part of a "series", which means consecutive segments with the same pressure
6518
+ // who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of
6519
+ // segments behind this one in the current series, and `seriesBackwardCoord` is the starting
6520
+ // coordinate of the first segment in the series.
6521
+ computeSlotSegCoords: function(seg, seriesBackwardPressure, seriesBackwardCoord) {
6522
+ var forwardSegs = seg.forwardSegs;
6523
+ var i;
6524
+
6525
+ if (seg.forwardCoord === undefined) { // not already computed
6526
+
6527
+ if (!forwardSegs.length) {
6528
+
6529
+ // if there are no forward segments, this segment should butt up against the edge
6530
+ seg.forwardCoord = 1;
6531
+ }
6532
+ else {
6533
+
6534
+ // sort highest pressure first
6535
+ this.sortForwardSlotSegs(forwardSegs);
6536
+
6537
+ // this segment's forwardCoord will be calculated from the backwardCoord of the
6538
+ // highest-pressure forward segment.
6539
+ this.computeSlotSegCoords(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord);
6540
+ seg.forwardCoord = forwardSegs[0].backwardCoord;
6541
+ }
6542
+
6543
+ // calculate the backwardCoord from the forwardCoord. consider the series
6544
+ seg.backwardCoord = seg.forwardCoord -
6545
+ (seg.forwardCoord - seriesBackwardCoord) / // available width for series
6546
+ (seriesBackwardPressure + 1); // # of segments in the series
6547
+
6548
+ // use this segment's coordinates to computed the coordinates of the less-pressurized
6549
+ // forward segments
6550
+ for (i=0; i<forwardSegs.length; i++) {
6551
+ this.computeSlotSegCoords(forwardSegs[i], 0, seg.forwardCoord);
6552
+ }
6553
+ }
6554
+ },
6555
+
6556
+
6238
6557
  // Refreshes the CSS top/bottom coordinates for each segment element. Probably after a window resize/zoom.
6239
6558
  // Repositions business hours segs too, so not just for events. Maybe shouldn't be here.
6240
6559
  updateSegVerticals: function() {
@@ -6396,33 +6715,25 @@ TimeGrid.mixin({
6396
6715
  }
6397
6716
 
6398
6717
  return segCols;
6399
- }
6400
-
6401
- });
6402
-
6403
-
6404
- // Given an array of segments that are all in the same column, sets the backwardCoord and forwardCoord on each.
6405
- // NOTE: Also reorders the given array by date!
6406
- function placeSlotSegs(segs) {
6407
- var levels;
6408
- var level0;
6409
- var i;
6718
+ },
6410
6719
 
6411
- segs.sort(compareSegs); // order by date
6412
- levels = buildSlotSegLevels(segs);
6413
- computeForwardSlotSegs(levels);
6414
6720
 
6415
- if ((level0 = levels[0])) {
6721
+ sortForwardSlotSegs: function(forwardSegs) {
6722
+ forwardSegs.sort(proxy(this, 'compareForwardSlotSegs'));
6723
+ },
6416
6724
 
6417
- for (i = 0; i < level0.length; i++) {
6418
- computeSlotSegPressures(level0[i]);
6419
- }
6420
6725
 
6421
- for (i = 0; i < level0.length; i++) {
6422
- computeSlotSegCoords(level0[i], 0, 0);
6423
- }
6726
+ // A cmp function for determining which forward segment to rely on more when computing coordinates.
6727
+ compareForwardSlotSegs: function(seg1, seg2) {
6728
+ // put higher-pressure first
6729
+ return seg2.forwardPressure - seg1.forwardPressure ||
6730
+ // put segments that are closer to initial edge first (and favor ones with no coords yet)
6731
+ (seg1.backwardCoord || 0) - (seg2.backwardCoord || 0) ||
6732
+ // do normal sorting...
6733
+ this.compareSegs(seg1, seg2);
6424
6734
  }
6425
- }
6735
+
6736
+ });
6426
6737
 
6427
6738
 
6428
6739
  // Builds an array of segments "levels". The first level will be the leftmost tier of segments if the calendar is
@@ -6501,50 +6812,6 @@ function computeSlotSegPressures(seg) {
6501
6812
  }
6502
6813
 
6503
6814
 
6504
- // Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range
6505
- // from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and
6506
- // seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left.
6507
- //
6508
- // The segment might be part of a "series", which means consecutive segments with the same pressure
6509
- // who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of
6510
- // segments behind this one in the current series, and `seriesBackwardCoord` is the starting
6511
- // coordinate of the first segment in the series.
6512
- function computeSlotSegCoords(seg, seriesBackwardPressure, seriesBackwardCoord) {
6513
- var forwardSegs = seg.forwardSegs;
6514
- var i;
6515
-
6516
- if (seg.forwardCoord === undefined) { // not already computed
6517
-
6518
- if (!forwardSegs.length) {
6519
-
6520
- // if there are no forward segments, this segment should butt up against the edge
6521
- seg.forwardCoord = 1;
6522
- }
6523
- else {
6524
-
6525
- // sort highest pressure first
6526
- forwardSegs.sort(compareForwardSlotSegs);
6527
-
6528
- // this segment's forwardCoord will be calculated from the backwardCoord of the
6529
- // highest-pressure forward segment.
6530
- computeSlotSegCoords(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord);
6531
- seg.forwardCoord = forwardSegs[0].backwardCoord;
6532
- }
6533
-
6534
- // calculate the backwardCoord from the forwardCoord. consider the series
6535
- seg.backwardCoord = seg.forwardCoord -
6536
- (seg.forwardCoord - seriesBackwardCoord) / // available width for series
6537
- (seriesBackwardPressure + 1); // # of segments in the series
6538
-
6539
- // use this segment's coordinates to computed the coordinates of the less-pressurized
6540
- // forward segments
6541
- for (i=0; i<forwardSegs.length; i++) {
6542
- computeSlotSegCoords(forwardSegs[i], 0, seg.forwardCoord);
6543
- }
6544
- }
6545
- }
6546
-
6547
-
6548
6815
  // Find all the segments in `otherSegs` that vertically collide with `seg`.
6549
6816
  // Append into an optionally-supplied `results` array and return.
6550
6817
  function computeSlotSegCollisions(seg, otherSegs, results) {
@@ -6565,17 +6832,6 @@ function isSlotSegCollision(seg1, seg2) {
6565
6832
  return seg1.bottom > seg2.top && seg1.top < seg2.bottom;
6566
6833
  }
6567
6834
 
6568
-
6569
- // A cmp function for determining which forward segment to rely on more when computing coordinates.
6570
- function compareForwardSlotSegs(seg1, seg2) {
6571
- // put higher-pressure first
6572
- return seg2.forwardPressure - seg1.forwardPressure ||
6573
- // put segments that are closer to initial edge first (and favor ones with no coords yet)
6574
- (seg1.backwardCoord || 0) - (seg2.backwardCoord || 0) ||
6575
- // do normal sorting...
6576
- compareSegs(seg1, seg2);
6577
- }
6578
-
6579
6835
  ;;
6580
6836
 
6581
6837
  /* An abstract class from which other views inherit from
@@ -6610,6 +6866,8 @@ var View = fc.View = Class.extend({
6610
6866
  isRTL: false,
6611
6867
  isSelected: false, // boolean whether a range of time is user-selected or not
6612
6868
 
6869
+ eventOrderSpecs: null, // criteria for ordering events when they have same date/time
6870
+
6613
6871
  // subclasses can optionally use a scroll container
6614
6872
  scrollerEl: null, // the element that will most likely scroll when content is too tall
6615
6873
  scrollTop: null, // cached vertical scroll value
@@ -6639,6 +6897,8 @@ var View = fc.View = Class.extend({
6639
6897
  this.initHiddenDays();
6640
6898
  this.isRTL = this.opt('isRTL');
6641
6899
 
6900
+ this.eventOrderSpecs = parseFieldSpecs(this.opt('eventOrder'));
6901
+
6642
6902
  this.documentMousedownProxy = proxy(this, 'documentMousedown');
6643
6903
 
6644
6904
  this.initialize();
@@ -7776,6 +8036,9 @@ var Calendar = fc.Calendar = Class.extend({
7776
8036
  });
7777
8037
 
7778
8038
 
8039
+ Calendar.mixin(Emitter);
8040
+
8041
+
7779
8042
  function Calendar_constructor(element, overrides) {
7780
8043
  var t = this;
7781
8044
 
@@ -8409,12 +8672,14 @@ function Calendar_constructor(element, overrides) {
8409
8672
  }
8410
8673
 
8411
8674
 
8412
- function trigger(name, thisObj) {
8675
+ function trigger(name, thisObj) { // overrides the Emitter's trigger method :(
8676
+ var args = Array.prototype.slice.call(arguments, 2);
8677
+
8678
+ thisObj = thisObj || _element;
8679
+ this.triggerWith(name, thisObj, args); // Emitter's method
8680
+
8413
8681
  if (options[name]) {
8414
- return options[name].apply(
8415
- thisObj || _element,
8416
- Array.prototype.slice.call(arguments, 2)
8417
- );
8682
+ return options[name].apply(thisObj, args);
8418
8683
  }
8419
8684
  }
8420
8685
 
@@ -8501,6 +8766,8 @@ Calendar.defaults = {
8501
8766
 
8502
8767
  dropAccept: '*',
8503
8768
 
8769
+ eventOrder: 'title',
8770
+
8504
8771
  eventLimit: false,
8505
8772
  eventLimitText: 'more',
8506
8773
  eventLimitClick: 'popover',
@@ -8796,6 +9063,7 @@ function Header(calendar, options) {
8796
9063
  var groupEl;
8797
9064
 
8798
9065
  $.each(this.split(','), function(j, buttonName) {
9066
+ var customButtonProps;
8799
9067
  var viewSpec;
8800
9068
  var buttonClick;
8801
9069
  var overrideText; // text explicitly set by calendar's constructor options. overcomes icons
@@ -8804,16 +9072,23 @@ function Header(calendar, options) {
8804
9072
  var normalIcon;
8805
9073
  var innerHtml;
8806
9074
  var classes;
8807
- var button;
9075
+ var button; // the element
8808
9076
 
8809
9077
  if (buttonName == 'title') {
8810
9078
  groupChildren = groupChildren.add($('<h2>&nbsp;</h2>')); // we always want it to take up height
8811
9079
  isOnlyButtons = false;
8812
9080
  }
8813
9081
  else {
8814
- viewSpec = calendar.getViewSpec(buttonName);
8815
-
8816
- if (viewSpec) {
9082
+ if ((customButtonProps = (calendar.options.customButtons || {})[buttonName])) {
9083
+ buttonClick = function(ev) {
9084
+ if (customButtonProps.click) {
9085
+ customButtonProps.click.call(button[0], ev);
9086
+ }
9087
+ };
9088
+ overrideText = ''; // icons will override text
9089
+ defaultText = customButtonProps.text;
9090
+ }
9091
+ else if ((viewSpec = calendar.getViewSpec(buttonName))) {
8817
9092
  buttonClick = function() {
8818
9093
  calendar.changeView(buttonName);
8819
9094
  };
@@ -8831,8 +9106,15 @@ function Header(calendar, options) {
8831
9106
 
8832
9107
  if (buttonClick) {
8833
9108
 
8834
- themeIcon = options.themeButtonIcons[buttonName];
8835
- normalIcon = options.buttonIcons[buttonName];
9109
+ themeIcon =
9110
+ customButtonProps ?
9111
+ customButtonProps.themeIcon :
9112
+ options.themeButtonIcons[buttonName];
9113
+
9114
+ normalIcon =
9115
+ customButtonProps ?
9116
+ customButtonProps.icon :
9117
+ options.buttonIcons[buttonName];
8836
9118
 
8837
9119
  if (overrideText) {
8838
9120
  innerHtml = htmlEscape(overrideText);
@@ -8858,11 +9140,11 @@ function Header(calendar, options) {
8858
9140
  innerHtml +
8859
9141
  '</button>'
8860
9142
  )
8861
- .click(function() {
9143
+ .click(function(ev) {
8862
9144
  // don't process clicks for disabled buttons
8863
9145
  if (!button.hasClass(tm + '-state-disabled')) {
8864
9146
 
8865
- buttonClick();
9147
+ buttonClick(ev);
8866
9148
 
8867
9149
  // after the click action, if the button becomes the "active" tab, or disabled,
8868
9150
  // it should never have a hover class, so remove it now.
@@ -10851,6 +11133,16 @@ var AgendaView = View.extend({
10851
11133
 
10852
11134
  var AGENDA_ALL_DAY_EVENT_LIMIT = 5;
10853
11135
 
11136
+ // potential nice values for the slot-duration and interval-duration
11137
+ // from largest to smallest
11138
+ var AGENDA_STOCK_SUB_DURATIONS = [
11139
+ { hours: 1 },
11140
+ { minutes: 30 },
11141
+ { minutes: 15 },
11142
+ { seconds: 30 },
11143
+ { seconds: 15 }
11144
+ ];
11145
+
10854
11146
  fcViews.agenda = {
10855
11147
  'class': AgendaView,
10856
11148
  defaults: {
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * FullCalendar v2.3.2 Google Calendar Plugin
2
+ * FullCalendar v2.4.0 Google Calendar Plugin
3
3
  * Docs & License: http://fullcalendar.io/
4
4
  * (c) 2015 Adam Shaw
5
5
  */
@@ -80,17 +80,13 @@ function transformOptions(sourceOptions, start, end, timezone, calendar) {
80
80
 
81
81
  function reportError(message, apiErrorObjs) {
82
82
  var errorObjs = apiErrorObjs || [ { message: message } ]; // to be passed into error handlers
83
- var consoleObj = window.console;
84
- var consoleWarnFunc = consoleObj ? (consoleObj.warn || consoleObj.log) : null;
85
83
 
86
84
  // call error handlers
87
85
  (sourceOptions.googleCalendarError || $.noop).apply(calendar, errorObjs);
88
86
  (calendar.options.googleCalendarError || $.noop).apply(calendar, errorObjs);
89
87
 
90
88
  // print error to debug console
91
- if (consoleWarnFunc) {
92
- consoleWarnFunc.apply(consoleObj, [ message ].concat(apiErrorObjs || []));
93
- }
89
+ fc.warn.apply(null, [ message ].concat(apiErrorObjs || []));
94
90
  }
95
91
 
96
92
  if (!apiKey) {
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * FullCalendar v2.3.2 Stylesheet
2
+ * FullCalendar v2.4.0 Stylesheet
3
3
  * Docs & License: http://fullcalendar.io/
4
4
  * (c) 2015 Adam Shaw
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * FullCalendar v2.3.2 Print Stylesheet
2
+ * FullCalendar v2.4.0 Print Stylesheet
3
3
  * Docs & License: http://fullcalendar.io/
4
4
  * (c) 2015 Adam Shaw
5
5
  */
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fullcalendar.io-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.2
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - dbackowski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-15 00:00:00.000000000 Z
11
+ date: 2015-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jquery-rails