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 +4 -4
- data/lib/fullcalendar.io/rails/version.rb +1 -1
- data/vendor/assets/javascripts/fullcalendar.js +408 -116
- data/vendor/assets/javascripts/fullcalendar/gcal.js +2 -6
- data/vendor/assets/stylesheets/fullcalendar.css +1 -1
- data/vendor/assets/stylesheets/fullcalendar.print.css +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e95fa760c253b1bcbbdaacc80fd045d1126a39c
|
4
|
+
data.tar.gz: 44c65ae292b3c364da1454c5a7838185105f2a69
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0aae9e839f7247dac108bb1b750543e22dc486f377ca34b70026670f2b7e103da8e57639158cab448d6ae6ddc9bfceccc469d43e07a6da7ee4b235fa1d2f2299
|
7
|
+
data.tar.gz: 28ae98115d58895d0f313f312194b4f9e293ba4e0ce6fab912d6df267ec9b7ab476b8dfffdf71ad44794a87dd9013b7787267dfcd829090812ad3ca07d5e6132
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
* FullCalendar v2.
|
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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
5746
|
-
|
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
|
-
(
|
5966
|
+
(isLabeled ?
|
5751
5967
|
'<span>' + // for matchCellWidths
|
5752
|
-
htmlEscape(slotDate.format(this.
|
5968
|
+
htmlEscape(slotDate.format(this.labelFormat)) +
|
5753
5969
|
'</span>' :
|
5754
5970
|
''
|
5755
5971
|
) +
|
5756
5972
|
'</td>';
|
5757
5973
|
|
5758
5974
|
html +=
|
5759
|
-
'<tr ' + (
|
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
|
-
|
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
|
-
|
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
|
-
|
6422
|
-
|
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> </h2>')); // we always want it to take up height
|
8811
9079
|
isOnlyButtons = false;
|
8812
9080
|
}
|
8813
9081
|
else {
|
8814
|
-
|
8815
|
-
|
8816
|
-
|
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 =
|
8835
|
-
|
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.
|
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
|
-
|
92
|
-
consoleWarnFunc.apply(consoleObj, [ message ].concat(apiErrorObjs || []));
|
93
|
-
}
|
89
|
+
fc.warn.apply(null, [ message ].concat(apiErrorObjs || []));
|
94
90
|
}
|
95
91
|
|
96
92
|
if (!apiKey) {
|
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.
|
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-
|
11
|
+
date: 2015-08-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jquery-rails
|