fullcalendar.io-rails 3.0.1 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/fullcalendar.io-rails.gemspec +1 -1
- data/lib/fullcalendar.io/rails/version.rb +1 -1
- data/vendor/assets/javascripts/fullcalendar.js +1670 -975
- data/vendor/assets/javascripts/fullcalendar/gcal.js +1 -1
- data/vendor/assets/javascripts/fullcalendar/locale-all.js +5 -5
- data/vendor/assets/javascripts/fullcalendar/locale/af.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/ar-dz.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/ar-ly.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/ar-sa.js +1 -1
- data/vendor/assets/javascripts/fullcalendar/locale/ca.js +1 -1
- data/vendor/assets/javascripts/fullcalendar/locale/gl.js +1 -1
- data/vendor/assets/javascripts/fullcalendar/locale/hr.js +1 -1
- data/vendor/assets/javascripts/fullcalendar/locale/hu.js +1 -1
- data/vendor/assets/javascripts/fullcalendar/locale/kk.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/lt.js +1 -1
- data/vendor/assets/javascripts/fullcalendar/locale/nl-be.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/nl.js +1 -1
- data/vendor/assets/javascripts/fullcalendar/locale/pl.js +1 -1
- data/vendor/assets/javascripts/fullcalendar/locale/sl.js +1 -1
- data/vendor/assets/javascripts/fullcalendar/locale/sr-cyrl.js +1 -1
- data/vendor/assets/javascripts/fullcalendar/locale/sr.js +1 -1
- data/vendor/assets/javascripts/fullcalendar/locale/th.js +1 -1
- data/vendor/assets/stylesheets/fullcalendar.css +9 -2
- data/vendor/assets/stylesheets/fullcalendar.print.css +1 -1
- metadata +79 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 360b2048acb86aa79d0aac78fc0ca49be99591bd
|
|
4
|
+
data.tar.gz: b511e90f3ace317e3ef591ebe25f32c1e12ebcc8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 533d93407cd7579f11255710338b4e80e45278cb690a826cac9eb311b98e250883bfc610f48df0936831daf4df8747967324bb293a4c3e0e6ef282875ce186e6
|
|
7
|
+
data.tar.gz: eba2626f57e3e8f9132d29956fc97175c6d953595ac9c802aa263715ca0da7e96764937b68703ad5bfc356f006f9c35904dc85fe5d8e1b3a93a04ca0a2e7c843
|
|
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
|
20
20
|
spec.test_files = Dir["spec/**/*"]
|
|
21
21
|
|
|
22
22
|
spec.add_runtime_dependency 'jquery-rails', '>= 3.1.0', '< 5.0'
|
|
23
|
-
spec.add_runtime_dependency 'momentjs-rails', '~> 2.
|
|
23
|
+
spec.add_runtime_dependency 'momentjs-rails', '~> 2.15'
|
|
24
24
|
spec.add_development_dependency "bundler", "~> 1.7"
|
|
25
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
|
26
26
|
spec.add_development_dependency 'rails', '4.2.5'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* FullCalendar v3.0
|
|
2
|
+
* FullCalendar v3.1.0
|
|
3
3
|
* Docs & License: http://fullcalendar.io/
|
|
4
4
|
* (c) 2016 Adam Shaw
|
|
5
5
|
*/
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
;;
|
|
20
20
|
|
|
21
21
|
var FC = $.fullCalendar = {
|
|
22
|
-
version: "3.0
|
|
23
|
-
internalApiVersion:
|
|
22
|
+
version: "3.1.0",
|
|
23
|
+
internalApiVersion: 7
|
|
24
24
|
};
|
|
25
25
|
var fcViews = FC.views = {};
|
|
26
26
|
|
|
@@ -53,13 +53,14 @@ $.fn.fullCalendar = function(options) {
|
|
|
53
53
|
calendar.render();
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
return res;
|
|
58
58
|
};
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
var complexOptions = [ // names of options that are objects whose properties should be combined
|
|
62
62
|
'header',
|
|
63
|
+
'footer',
|
|
63
64
|
'buttonText',
|
|
64
65
|
'buttonIcons',
|
|
65
66
|
'themeButtonIcons'
|
|
@@ -848,6 +849,7 @@ function createObject(proto) {
|
|
|
848
849
|
f.prototype = proto;
|
|
849
850
|
return new f();
|
|
850
851
|
}
|
|
852
|
+
FC.createObject = createObject;
|
|
851
853
|
|
|
852
854
|
|
|
853
855
|
function copyOwnProps(src, dest) {
|
|
@@ -1004,20 +1006,6 @@ function debounce(func, wait, immediate) {
|
|
|
1004
1006
|
};
|
|
1005
1007
|
}
|
|
1006
1008
|
|
|
1007
|
-
|
|
1008
|
-
// HACK around jQuery's now A+ promises: execute callback synchronously if already resolved.
|
|
1009
|
-
// thenFunc shouldn't accept args.
|
|
1010
|
-
// similar to whenResources in Scheduler plugin.
|
|
1011
|
-
function syncThen(promise, thenFunc) {
|
|
1012
|
-
// not a promise, or an already-resolved promise?
|
|
1013
|
-
if (!promise || !promise.then || promise.state() === 'resolved') {
|
|
1014
|
-
return $.when(thenFunc()); // resolve immediately
|
|
1015
|
-
}
|
|
1016
|
-
else if (thenFunc) {
|
|
1017
|
-
return promise.then(thenFunc);
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
1009
|
;;
|
|
1022
1010
|
|
|
1023
1011
|
/*
|
|
@@ -1681,6 +1669,201 @@ function mixIntoClass(theClass, members) {
|
|
|
1681
1669
|
}
|
|
1682
1670
|
;;
|
|
1683
1671
|
|
|
1672
|
+
/*
|
|
1673
|
+
Wrap jQuery's Deferred Promise object to be slightly more Promise/A+ compliant.
|
|
1674
|
+
With the added non-standard feature of synchronously executing handlers on resolved promises,
|
|
1675
|
+
which doesn't always happen otherwise (esp with nested .then handlers!?),
|
|
1676
|
+
so, this makes things a lot easier, esp because jQuery 3 changed the synchronicity for Deferred objects.
|
|
1677
|
+
|
|
1678
|
+
TODO: write tests and more comments
|
|
1679
|
+
*/
|
|
1680
|
+
|
|
1681
|
+
function Promise(executor) {
|
|
1682
|
+
var deferred = $.Deferred();
|
|
1683
|
+
var promise = deferred.promise();
|
|
1684
|
+
|
|
1685
|
+
if (typeof executor === 'function') {
|
|
1686
|
+
executor(
|
|
1687
|
+
function(value) { // resolve
|
|
1688
|
+
if (Promise.immediate) {
|
|
1689
|
+
promise._value = value;
|
|
1690
|
+
}
|
|
1691
|
+
deferred.resolve(value);
|
|
1692
|
+
},
|
|
1693
|
+
function() { // reject
|
|
1694
|
+
deferred.reject();
|
|
1695
|
+
}
|
|
1696
|
+
);
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
if (Promise.immediate) {
|
|
1700
|
+
var origThen = promise.then;
|
|
1701
|
+
|
|
1702
|
+
promise.then = function(onFulfilled, onRejected) {
|
|
1703
|
+
var state = promise.state();
|
|
1704
|
+
|
|
1705
|
+
if (state === 'resolved') {
|
|
1706
|
+
if (typeof onFulfilled === 'function') {
|
|
1707
|
+
return Promise.resolve(onFulfilled(promise._value));
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
else if (state === 'rejected') {
|
|
1711
|
+
if (typeof onRejected === 'function') {
|
|
1712
|
+
onRejected();
|
|
1713
|
+
return promise; // already rejected
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
return origThen.call(promise, onFulfilled, onRejected);
|
|
1718
|
+
};
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
return promise; // instanceof Promise will break :( TODO: make Promise a real class
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
FC.Promise = Promise;
|
|
1725
|
+
|
|
1726
|
+
Promise.immediate = true;
|
|
1727
|
+
|
|
1728
|
+
|
|
1729
|
+
Promise.resolve = function(value) {
|
|
1730
|
+
if (value && typeof value.resolve === 'function') {
|
|
1731
|
+
return value.promise();
|
|
1732
|
+
}
|
|
1733
|
+
if (value && typeof value.then === 'function') {
|
|
1734
|
+
return value;
|
|
1735
|
+
}
|
|
1736
|
+
else {
|
|
1737
|
+
var deferred = $.Deferred().resolve(value);
|
|
1738
|
+
var promise = deferred.promise();
|
|
1739
|
+
|
|
1740
|
+
if (Promise.immediate) {
|
|
1741
|
+
var origThen = promise.then;
|
|
1742
|
+
|
|
1743
|
+
promise._value = value;
|
|
1744
|
+
|
|
1745
|
+
promise.then = function(onFulfilled, onRejected) {
|
|
1746
|
+
if (typeof onFulfilled === 'function') {
|
|
1747
|
+
return Promise.resolve(onFulfilled(value));
|
|
1748
|
+
}
|
|
1749
|
+
return origThen.call(promise, onFulfilled, onRejected);
|
|
1750
|
+
};
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
return promise;
|
|
1754
|
+
}
|
|
1755
|
+
};
|
|
1756
|
+
|
|
1757
|
+
|
|
1758
|
+
Promise.reject = function() {
|
|
1759
|
+
return $.Deferred().reject().promise();
|
|
1760
|
+
};
|
|
1761
|
+
|
|
1762
|
+
|
|
1763
|
+
Promise.all = function(inputs) {
|
|
1764
|
+
var hasAllValues = false;
|
|
1765
|
+
var values;
|
|
1766
|
+
var i, input;
|
|
1767
|
+
|
|
1768
|
+
if (Promise.immediate) {
|
|
1769
|
+
hasAllValues = true;
|
|
1770
|
+
values = [];
|
|
1771
|
+
|
|
1772
|
+
for (i = 0; i < inputs.length; i++) {
|
|
1773
|
+
input = inputs[i];
|
|
1774
|
+
|
|
1775
|
+
if (input && typeof input.state === 'function' && input.state() === 'resolved' && ('_value' in input)) {
|
|
1776
|
+
values.push(input._value);
|
|
1777
|
+
}
|
|
1778
|
+
else if (input && typeof input.then === 'function') {
|
|
1779
|
+
hasAllValues = false;
|
|
1780
|
+
break;
|
|
1781
|
+
}
|
|
1782
|
+
else {
|
|
1783
|
+
values.push(input);
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
if (hasAllValues) {
|
|
1789
|
+
return Promise.resolve(values);
|
|
1790
|
+
}
|
|
1791
|
+
else {
|
|
1792
|
+
return $.when.apply($.when, inputs).then(function() {
|
|
1793
|
+
return $.when($.makeArray(arguments));
|
|
1794
|
+
});
|
|
1795
|
+
}
|
|
1796
|
+
};
|
|
1797
|
+
|
|
1798
|
+
;;
|
|
1799
|
+
|
|
1800
|
+
// TODO: write tests and clean up code
|
|
1801
|
+
|
|
1802
|
+
function TaskQueue(debounceWait) {
|
|
1803
|
+
var q = []; // array of runFuncs
|
|
1804
|
+
|
|
1805
|
+
function addTask(taskFunc) {
|
|
1806
|
+
return new Promise(function(resolve) {
|
|
1807
|
+
|
|
1808
|
+
// should run this function when it's taskFunc's turn to run.
|
|
1809
|
+
// responsible for popping itself off the queue.
|
|
1810
|
+
var runFunc = function() {
|
|
1811
|
+
Promise.resolve(taskFunc()) // result might be async, coerce to promise
|
|
1812
|
+
.then(resolve) // resolve TaskQueue::push's promise, for the caller. will receive result of taskFunc.
|
|
1813
|
+
.then(function() {
|
|
1814
|
+
q.shift(); // pop itself off
|
|
1815
|
+
|
|
1816
|
+
// run the next task, if any
|
|
1817
|
+
if (q.length) {
|
|
1818
|
+
q[0]();
|
|
1819
|
+
}
|
|
1820
|
+
});
|
|
1821
|
+
};
|
|
1822
|
+
|
|
1823
|
+
// always put the task at the end of the queue, BEFORE running the task
|
|
1824
|
+
q.push(runFunc);
|
|
1825
|
+
|
|
1826
|
+
// if it's the only task in the queue, run immediately
|
|
1827
|
+
if (q.length === 1) {
|
|
1828
|
+
runFunc();
|
|
1829
|
+
}
|
|
1830
|
+
});
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
this.add = // potentially debounce, for the public method
|
|
1834
|
+
typeof debounceWait === 'number' ?
|
|
1835
|
+
debounce(addTask, debounceWait) :
|
|
1836
|
+
addTask; // if not a number (null/undefined/false), no debounce at all
|
|
1837
|
+
|
|
1838
|
+
this.addQuickly = addTask; // guaranteed no debounce
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
FC.TaskQueue = TaskQueue;
|
|
1842
|
+
|
|
1843
|
+
/*
|
|
1844
|
+
q = new TaskQueue();
|
|
1845
|
+
|
|
1846
|
+
function work(i) {
|
|
1847
|
+
return q.push(function() {
|
|
1848
|
+
trigger();
|
|
1849
|
+
console.log('work' + i);
|
|
1850
|
+
});
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
var cnt = 0;
|
|
1854
|
+
|
|
1855
|
+
function trigger() {
|
|
1856
|
+
if (cnt < 5) {
|
|
1857
|
+
cnt++;
|
|
1858
|
+
work(cnt);
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
work(9);
|
|
1863
|
+
*/
|
|
1864
|
+
|
|
1865
|
+
;;
|
|
1866
|
+
|
|
1684
1867
|
var EmitterMixin = FC.EmitterMixin = {
|
|
1685
1868
|
|
|
1686
1869
|
// jQuery-ification via $(this) allows a non-DOM object to have
|
|
@@ -1688,7 +1871,18 @@ var EmitterMixin = FC.EmitterMixin = {
|
|
|
1688
1871
|
|
|
1689
1872
|
|
|
1690
1873
|
on: function(types, handler) {
|
|
1874
|
+
$(this).on(types, this._prepareIntercept(handler));
|
|
1875
|
+
return this; // for chaining
|
|
1876
|
+
},
|
|
1877
|
+
|
|
1878
|
+
|
|
1879
|
+
one: function(types, handler) {
|
|
1880
|
+
$(this).one(types, this._prepareIntercept(handler));
|
|
1881
|
+
return this; // for chaining
|
|
1882
|
+
},
|
|
1691
1883
|
|
|
1884
|
+
|
|
1885
|
+
_prepareIntercept: function(handler) {
|
|
1692
1886
|
// handlers are always called with an "event" object as their first param.
|
|
1693
1887
|
// sneak the `this` context and arguments into the extra parameter object
|
|
1694
1888
|
// and forward them on to the original handler.
|
|
@@ -1708,9 +1902,7 @@ var EmitterMixin = FC.EmitterMixin = {
|
|
|
1708
1902
|
}
|
|
1709
1903
|
intercept.guid = handler.guid;
|
|
1710
1904
|
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
return this; // for chaining
|
|
1905
|
+
return intercept;
|
|
1714
1906
|
},
|
|
1715
1907
|
|
|
1716
1908
|
|
|
@@ -2039,9 +2231,15 @@ var CoordCache = FC.CoordCache = Class.extend({
|
|
|
2039
2231
|
// Queries the els for coordinates and stores them.
|
|
2040
2232
|
// Call this method before using and of the get* methods below.
|
|
2041
2233
|
build: function() {
|
|
2042
|
-
var offsetParentEl = this.forcedOffsetParentEl
|
|
2234
|
+
var offsetParentEl = this.forcedOffsetParentEl;
|
|
2235
|
+
if (!offsetParentEl && this.els.length > 0) {
|
|
2236
|
+
offsetParentEl = this.els.eq(0).offsetParent();
|
|
2237
|
+
}
|
|
2238
|
+
|
|
2239
|
+
this.origin = offsetParentEl ?
|
|
2240
|
+
offsetParentEl.offset() :
|
|
2241
|
+
null;
|
|
2043
2242
|
|
|
2044
|
-
this.origin = offsetParentEl.offset();
|
|
2045
2243
|
this.boundingRect = this.queryBoundingRect();
|
|
2046
2244
|
|
|
2047
2245
|
if (this.isHorizontal) {
|
|
@@ -2224,12 +2422,19 @@ var CoordCache = FC.CoordCache = Class.extend({
|
|
|
2224
2422
|
|
|
2225
2423
|
// Compute and return what the elements' bounding rectangle is, from the user's perspective.
|
|
2226
2424
|
// Right now, only returns a rectangle if constrained by an overflow:scroll element.
|
|
2425
|
+
// Returns null if there are no elements
|
|
2227
2426
|
queryBoundingRect: function() {
|
|
2228
|
-
var scrollParentEl
|
|
2427
|
+
var scrollParentEl;
|
|
2428
|
+
|
|
2429
|
+
if (this.els.length > 0) {
|
|
2430
|
+
scrollParentEl = getScrollParent(this.els.eq(0));
|
|
2229
2431
|
|
|
2230
|
-
|
|
2231
|
-
|
|
2432
|
+
if (!scrollParentEl.is(document)) {
|
|
2433
|
+
return getClientRect(scrollParentEl);
|
|
2434
|
+
}
|
|
2232
2435
|
}
|
|
2436
|
+
|
|
2437
|
+
return null;
|
|
2233
2438
|
},
|
|
2234
2439
|
|
|
2235
2440
|
isPointInBounds: function(leftOffset, topOffset) {
|
|
@@ -3448,6 +3653,7 @@ var Grid = FC.Grid = Class.extend(ListenerMixin, MouseIgnorerMixin, {
|
|
|
3448
3653
|
|
|
3449
3654
|
dayTouchStart: function(ev) {
|
|
3450
3655
|
var view = this.view;
|
|
3656
|
+
var selectLongPressDelay = view.opt('selectLongPressDelay');
|
|
3451
3657
|
|
|
3452
3658
|
// HACK to prevent a user's clickaway for unselecting a range or an event
|
|
3453
3659
|
// from causing a dayClick.
|
|
@@ -3455,8 +3661,12 @@ var Grid = FC.Grid = Class.extend(ListenerMixin, MouseIgnorerMixin, {
|
|
|
3455
3661
|
this.tempIgnoreMouse();
|
|
3456
3662
|
}
|
|
3457
3663
|
|
|
3664
|
+
if (selectLongPressDelay == null) {
|
|
3665
|
+
selectLongPressDelay = view.opt('longPressDelay'); // fallback
|
|
3666
|
+
}
|
|
3667
|
+
|
|
3458
3668
|
this.dayDragListener.startInteraction(ev, {
|
|
3459
|
-
delay:
|
|
3669
|
+
delay: selectLongPressDelay
|
|
3460
3670
|
});
|
|
3461
3671
|
},
|
|
3462
3672
|
|
|
@@ -3793,7 +4003,7 @@ var Grid = FC.Grid = Class.extend(ListenerMixin, MouseIgnorerMixin, {
|
|
|
3793
4003
|
|
|
3794
4004
|
|
|
3795
4005
|
// Computes HTML classNames for a single-day element
|
|
3796
|
-
getDayClasses: function(date) {
|
|
4006
|
+
getDayClasses: function(date, noThemeHighlight) {
|
|
3797
4007
|
var view = this.view;
|
|
3798
4008
|
var today = view.calendar.getNow();
|
|
3799
4009
|
var classes = [ 'fc-' + dayIDs[date.day()] ];
|
|
@@ -3806,10 +4016,11 @@ var Grid = FC.Grid = Class.extend(ListenerMixin, MouseIgnorerMixin, {
|
|
|
3806
4016
|
}
|
|
3807
4017
|
|
|
3808
4018
|
if (date.isSame(today, 'day')) {
|
|
3809
|
-
classes.push(
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
4019
|
+
classes.push('fc-today');
|
|
4020
|
+
|
|
4021
|
+
if (noThemeHighlight !== true) {
|
|
4022
|
+
classes.push(view.highlightStateClass);
|
|
4023
|
+
}
|
|
3813
4024
|
}
|
|
3814
4025
|
else if (date < today) {
|
|
3815
4026
|
classes.push('fc-past');
|
|
@@ -4005,16 +4216,33 @@ Grid.mixin({
|
|
|
4005
4216
|
|
|
4006
4217
|
// Compute business hour segs for the grid's current date range.
|
|
4007
4218
|
// Caller must ask if whole-day business hours are needed.
|
|
4008
|
-
|
|
4009
|
-
|
|
4219
|
+
// If no `businessHours` configuration value is specified, assumes the calendar default.
|
|
4220
|
+
buildBusinessHourSegs: function(wholeDay, businessHours) {
|
|
4221
|
+
return this.eventsToSegs(
|
|
4222
|
+
this.buildBusinessHourEvents(wholeDay, businessHours)
|
|
4223
|
+
);
|
|
4224
|
+
},
|
|
4225
|
+
|
|
4226
|
+
|
|
4227
|
+
// Compute business hour *events* for the grid's current date range.
|
|
4228
|
+
// Caller must ask if whole-day business hours are needed.
|
|
4229
|
+
// If no `businessHours` configuration value is specified, assumes the calendar default.
|
|
4230
|
+
buildBusinessHourEvents: function(wholeDay, businessHours) {
|
|
4231
|
+
var calendar = this.view.calendar;
|
|
4232
|
+
var events;
|
|
4233
|
+
|
|
4234
|
+
if (businessHours == null) {
|
|
4235
|
+
// fallback
|
|
4236
|
+
// access from calendawr. don't access from view. doesn't update with dynamic options.
|
|
4237
|
+
businessHours = calendar.options.businessHours;
|
|
4238
|
+
}
|
|
4239
|
+
|
|
4240
|
+
events = calendar.computeBusinessHourEvents(wholeDay, businessHours);
|
|
4010
4241
|
|
|
4011
4242
|
// HACK. Eventually refactor business hours "events" system.
|
|
4012
4243
|
// If no events are given, but businessHours is activated, this means the entire visible range should be
|
|
4013
4244
|
// marked as *not* business-hours, via inverse-background rendering.
|
|
4014
|
-
if (
|
|
4015
|
-
!events.length &&
|
|
4016
|
-
this.view.calendar.options.businessHours // don't access view option. doesn't update with dynamic options
|
|
4017
|
-
) {
|
|
4245
|
+
if (!events.length && businessHours) {
|
|
4018
4246
|
events = [
|
|
4019
4247
|
$.extend({}, BUSINESS_HOUR_EVENT_DEFAULTS, {
|
|
4020
4248
|
start: this.view.end, // guaranteed out-of-range
|
|
@@ -4024,7 +4252,7 @@ Grid.mixin({
|
|
|
4024
4252
|
];
|
|
4025
4253
|
}
|
|
4026
4254
|
|
|
4027
|
-
return
|
|
4255
|
+
return events;
|
|
4028
4256
|
},
|
|
4029
4257
|
|
|
4030
4258
|
|
|
@@ -4066,7 +4294,7 @@ Grid.mixin({
|
|
|
4066
4294
|
|
|
4067
4295
|
|
|
4068
4296
|
handleSegClick: function(seg, ev) {
|
|
4069
|
-
var res = this.view.
|
|
4297
|
+
var res = this.view.publiclyTrigger('eventClick', seg.el[0], seg.event, ev); // can return `false` to cancel
|
|
4070
4298
|
if (res === false) {
|
|
4071
4299
|
ev.preventDefault();
|
|
4072
4300
|
}
|
|
@@ -4083,7 +4311,7 @@ Grid.mixin({
|
|
|
4083
4311
|
if (this.view.isEventResizable(seg.event)) {
|
|
4084
4312
|
seg.el.addClass('fc-allow-mouse-resize');
|
|
4085
4313
|
}
|
|
4086
|
-
this.view.
|
|
4314
|
+
this.view.publiclyTrigger('eventMouseover', seg.el[0], seg.event, ev);
|
|
4087
4315
|
}
|
|
4088
4316
|
},
|
|
4089
4317
|
|
|
@@ -4099,7 +4327,7 @@ Grid.mixin({
|
|
|
4099
4327
|
if (this.view.isEventResizable(seg.event)) {
|
|
4100
4328
|
seg.el.removeClass('fc-allow-mouse-resize');
|
|
4101
4329
|
}
|
|
4102
|
-
this.view.
|
|
4330
|
+
this.view.publiclyTrigger('eventMouseout', seg.el[0], seg.event, ev);
|
|
4103
4331
|
}
|
|
4104
4332
|
},
|
|
4105
4333
|
|
|
@@ -4124,6 +4352,7 @@ Grid.mixin({
|
|
|
4124
4352
|
var isResizable = view.isEventResizable(event);
|
|
4125
4353
|
var isResizing = false;
|
|
4126
4354
|
var dragListener;
|
|
4355
|
+
var eventLongPressDelay;
|
|
4127
4356
|
|
|
4128
4357
|
if (isSelected && isResizable) {
|
|
4129
4358
|
// only allow resizing of the event is selected
|
|
@@ -4132,12 +4361,17 @@ Grid.mixin({
|
|
|
4132
4361
|
|
|
4133
4362
|
if (!isResizing && (isDraggable || isResizable)) { // allowed to be selected?
|
|
4134
4363
|
|
|
4364
|
+
eventLongPressDelay = view.opt('eventLongPressDelay');
|
|
4365
|
+
if (eventLongPressDelay == null) {
|
|
4366
|
+
eventLongPressDelay = view.opt('longPressDelay'); // fallback
|
|
4367
|
+
}
|
|
4368
|
+
|
|
4135
4369
|
dragListener = isDraggable ?
|
|
4136
4370
|
this.buildSegDragListener(seg) :
|
|
4137
4371
|
this.buildSegSelectListener(seg); // seg isn't draggable, but still needs to be selected
|
|
4138
4372
|
|
|
4139
4373
|
dragListener.startInteraction(ev, { // won't start if already started
|
|
4140
|
-
delay: isSelected ? 0 :
|
|
4374
|
+
delay: isSelected ? 0 : eventLongPressDelay // do delay if not already selected
|
|
4141
4375
|
});
|
|
4142
4376
|
}
|
|
4143
4377
|
|
|
@@ -4270,11 +4504,15 @@ Grid.mixin({
|
|
|
4270
4504
|
mouseFollower.stop(!dropLocation, function() {
|
|
4271
4505
|
if (isDragging) {
|
|
4272
4506
|
view.unrenderDrag();
|
|
4273
|
-
view.showEvent(event);
|
|
4274
4507
|
_this.segDragStop(seg, ev);
|
|
4275
4508
|
}
|
|
4509
|
+
|
|
4276
4510
|
if (dropLocation) {
|
|
4277
|
-
|
|
4511
|
+
// no need to re-show original, will rerender all anyways. esp important if eventRenderWait
|
|
4512
|
+
view.reportEventDrop(event, dropLocation, _this.largeUnit, el, ev);
|
|
4513
|
+
}
|
|
4514
|
+
else {
|
|
4515
|
+
view.showEvent(event);
|
|
4278
4516
|
}
|
|
4279
4517
|
});
|
|
4280
4518
|
_this.segDragListener = null;
|
|
@@ -4316,14 +4554,14 @@ Grid.mixin({
|
|
|
4316
4554
|
// Called before event segment dragging starts
|
|
4317
4555
|
segDragStart: function(seg, ev) {
|
|
4318
4556
|
this.isDraggingSeg = true;
|
|
4319
|
-
this.view.
|
|
4557
|
+
this.view.publiclyTrigger('eventDragStart', seg.el[0], seg.event, ev, {}); // last argument is jqui dummy
|
|
4320
4558
|
},
|
|
4321
4559
|
|
|
4322
4560
|
|
|
4323
4561
|
// Called after event segment dragging stops
|
|
4324
4562
|
segDragStop: function(seg, ev) {
|
|
4325
4563
|
this.isDraggingSeg = false;
|
|
4326
|
-
this.view.
|
|
4564
|
+
this.view.publiclyTrigger('eventDragStop', seg.el[0], seg.event, ev, {}); // last argument is jqui dummy
|
|
4327
4565
|
},
|
|
4328
4566
|
|
|
4329
4567
|
|
|
@@ -4561,18 +4799,23 @@ Grid.mixin({
|
|
|
4561
4799
|
},
|
|
4562
4800
|
hitOut: function() { // called before mouse moves to a different hit OR moved out of all hits
|
|
4563
4801
|
resizeLocation = null;
|
|
4802
|
+
view.showEvent(event); // for when out-of-bounds. show original
|
|
4564
4803
|
},
|
|
4565
4804
|
hitDone: function() { // resets the rendering to show the original event
|
|
4566
4805
|
_this.unrenderEventResize();
|
|
4567
|
-
view.showEvent(event);
|
|
4568
4806
|
enableCursor();
|
|
4569
4807
|
},
|
|
4570
4808
|
interactionEnd: function(ev) {
|
|
4571
4809
|
if (isDragging) {
|
|
4572
4810
|
_this.segResizeStop(seg, ev);
|
|
4573
4811
|
}
|
|
4812
|
+
|
|
4574
4813
|
if (resizeLocation) { // valid date to resize to?
|
|
4575
|
-
|
|
4814
|
+
// no need to re-show original, will rerender all anyways. esp important if eventRenderWait
|
|
4815
|
+
view.reportEventResize(event, resizeLocation, _this.largeUnit, el, ev);
|
|
4816
|
+
}
|
|
4817
|
+
else {
|
|
4818
|
+
view.showEvent(event);
|
|
4576
4819
|
}
|
|
4577
4820
|
_this.segResizeListener = null;
|
|
4578
4821
|
}
|
|
@@ -4585,14 +4828,14 @@ Grid.mixin({
|
|
|
4585
4828
|
// Called before event segment resizing starts
|
|
4586
4829
|
segResizeStart: function(seg, ev) {
|
|
4587
4830
|
this.isResizingSeg = true;
|
|
4588
|
-
this.view.
|
|
4831
|
+
this.view.publiclyTrigger('eventResizeStart', seg.el[0], seg.event, ev, {}); // last argument is jqui dummy
|
|
4589
4832
|
},
|
|
4590
4833
|
|
|
4591
4834
|
|
|
4592
4835
|
// Called after event segment resizing stops
|
|
4593
4836
|
segResizeStop: function(seg, ev) {
|
|
4594
4837
|
this.isResizingSeg = false;
|
|
4595
|
-
this.view.
|
|
4838
|
+
this.view.publiclyTrigger('eventResizeStop', seg.el[0], seg.event, ev, {}); // last argument is jqui dummy
|
|
4596
4839
|
},
|
|
4597
4840
|
|
|
4598
4841
|
|
|
@@ -5143,7 +5386,7 @@ var DayTableMixin = FC.DayTableMixin = {
|
|
|
5143
5386
|
this.dayIndices = dayIndices;
|
|
5144
5387
|
this.daysPerRow = daysPerRow;
|
|
5145
5388
|
this.rowCnt = rowCnt;
|
|
5146
|
-
|
|
5389
|
+
|
|
5147
5390
|
this.updateDayTableCols();
|
|
5148
5391
|
},
|
|
5149
5392
|
|
|
@@ -5381,9 +5624,25 @@ var DayTableMixin = FC.DayTableMixin = {
|
|
|
5381
5624
|
// (colspan should be no different)
|
|
5382
5625
|
renderHeadDateCellHtml: function(date, colspan, otherAttrs) {
|
|
5383
5626
|
var view = this.view;
|
|
5627
|
+
var classNames = [
|
|
5628
|
+
'fc-day-header',
|
|
5629
|
+
view.widgetHeaderClass
|
|
5630
|
+
];
|
|
5631
|
+
|
|
5632
|
+
// if only one row of days, the classNames on the header can represent the specific days beneath
|
|
5633
|
+
if (this.rowCnt === 1) {
|
|
5634
|
+
classNames = classNames.concat(
|
|
5635
|
+
// includes the day-of-week class
|
|
5636
|
+
// noThemeHighlight=true (don't highlight the header)
|
|
5637
|
+
this.getDayClasses(date, true)
|
|
5638
|
+
);
|
|
5639
|
+
}
|
|
5640
|
+
else {
|
|
5641
|
+
classNames.push('fc-' + dayIDs[date.day()]); // only add the day-of-week class
|
|
5642
|
+
}
|
|
5384
5643
|
|
|
5385
5644
|
return '' +
|
|
5386
|
-
|
|
5645
|
+
'<th class="' + classNames.join(' ') + '"' +
|
|
5387
5646
|
(this.rowCnt === 1 ?
|
|
5388
5647
|
' data-date="' + date.format('YYYY-MM-DD') + '"' :
|
|
5389
5648
|
'') +
|
|
@@ -5534,7 +5793,7 @@ var DayGrid = FC.DayGrid = Grid.extend(DayTableMixin, {
|
|
|
5534
5793
|
// trigger dayRender with each cell's element
|
|
5535
5794
|
for (row = 0; row < rowCnt; row++) {
|
|
5536
5795
|
for (col = 0; col < colCnt; col++) {
|
|
5537
|
-
view.
|
|
5796
|
+
view.publiclyTrigger(
|
|
5538
5797
|
'dayRender',
|
|
5539
5798
|
null,
|
|
5540
5799
|
this.getCellDate(row, col),
|
|
@@ -6469,7 +6728,7 @@ DayGrid.mixin({
|
|
|
6469
6728
|
|
|
6470
6729
|
if (typeof clickOption === 'function') {
|
|
6471
6730
|
// the returned value can be an atomic option
|
|
6472
|
-
clickOption = view.
|
|
6731
|
+
clickOption = view.publiclyTrigger('eventLimitClick', null, {
|
|
6473
6732
|
date: date,
|
|
6474
6733
|
dayEl: dayEl,
|
|
6475
6734
|
moreEl: moreEl,
|
|
@@ -6512,6 +6771,14 @@ DayGrid.mixin({
|
|
|
6512
6771
|
viewportConstrain: view.opt('popoverViewportConstrain'),
|
|
6513
6772
|
hide: function() {
|
|
6514
6773
|
// kill everything when the popover is hidden
|
|
6774
|
+
// notify events to be removed
|
|
6775
|
+
if (_this.popoverSegs) {
|
|
6776
|
+
var seg;
|
|
6777
|
+
for (var i = 0; i < _this.popoverSegs.length; ++i) {
|
|
6778
|
+
seg = _this.popoverSegs[i];
|
|
6779
|
+
view.publiclyTrigger('eventDestroy', seg.event, seg.event, seg.el);
|
|
6780
|
+
}
|
|
6781
|
+
}
|
|
6515
6782
|
_this.segPopover.removeElement();
|
|
6516
6783
|
_this.segPopover = null;
|
|
6517
6784
|
_this.popoverSegs = null;
|
|
@@ -7789,9 +8056,14 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
7789
8056
|
options: null, // hash containing all options. already merged with view-specific-options
|
|
7790
8057
|
el: null, // the view's containing element. set by Calendar
|
|
7791
8058
|
|
|
7792
|
-
|
|
7793
|
-
|
|
8059
|
+
isDateSet: false,
|
|
8060
|
+
isDateRendered: false,
|
|
8061
|
+
dateRenderQueue: null,
|
|
8062
|
+
|
|
8063
|
+
isEventsBound: false,
|
|
8064
|
+
isEventsSet: false,
|
|
7794
8065
|
isEventsRendered: false,
|
|
8066
|
+
eventRenderQueue: null,
|
|
7795
8067
|
|
|
7796
8068
|
// range the view is actually displaying (moments)
|
|
7797
8069
|
start: null,
|
|
@@ -7841,6 +8113,9 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
7841
8113
|
|
|
7842
8114
|
this.eventOrderSpecs = parseFieldSpecs(this.opt('eventOrder'));
|
|
7843
8115
|
|
|
8116
|
+
this.dateRenderQueue = new TaskQueue();
|
|
8117
|
+
this.eventRenderQueue = new TaskQueue(this.opt('eventRenderWait'));
|
|
8118
|
+
|
|
7844
8119
|
this.initialize();
|
|
7845
8120
|
},
|
|
7846
8121
|
|
|
@@ -7858,10 +8133,10 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
7858
8133
|
|
|
7859
8134
|
|
|
7860
8135
|
// Triggers handlers that are view-related. Modifies args before passing to calendar.
|
|
7861
|
-
|
|
8136
|
+
publiclyTrigger: function(name, thisObj) { // arguments beyond thisObj are passed along
|
|
7862
8137
|
var calendar = this.calendar;
|
|
7863
8138
|
|
|
7864
|
-
return calendar.
|
|
8139
|
+
return calendar.publiclyTrigger.apply(
|
|
7865
8140
|
calendar,
|
|
7866
8141
|
[name, thisObj || this].concat(
|
|
7867
8142
|
Array.prototype.slice.call(arguments, 2), // arguments beyond thisObj
|
|
@@ -7871,16 +8146,33 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
7871
8146
|
},
|
|
7872
8147
|
|
|
7873
8148
|
|
|
7874
|
-
|
|
7875
|
-
|
|
8149
|
+
// Returns a proxy of the given promise that will be rejected if the given event fires
|
|
8150
|
+
// before the promise resolves.
|
|
8151
|
+
rejectOn: function(eventName, promise) {
|
|
8152
|
+
var _this = this;
|
|
7876
8153
|
|
|
8154
|
+
return new Promise(function(resolve, reject) {
|
|
8155
|
+
_this.one(eventName, reject);
|
|
7877
8156
|
|
|
7878
|
-
|
|
7879
|
-
|
|
7880
|
-
|
|
8157
|
+
function cleanup() {
|
|
8158
|
+
_this.off(eventName, reject);
|
|
8159
|
+
}
|
|
8160
|
+
|
|
8161
|
+
promise.then(function(res) { // success
|
|
8162
|
+
cleanup();
|
|
8163
|
+
resolve(res);
|
|
8164
|
+
}, function() { // failure
|
|
8165
|
+
cleanup();
|
|
8166
|
+
reject();
|
|
8167
|
+
});
|
|
8168
|
+
});
|
|
7881
8169
|
},
|
|
7882
8170
|
|
|
7883
8171
|
|
|
8172
|
+
/* Date Computation
|
|
8173
|
+
------------------------------------------------------------------------------------------------------------------*/
|
|
8174
|
+
|
|
8175
|
+
|
|
7884
8176
|
// Updates all internal dates for displaying the given unzoned range.
|
|
7885
8177
|
setRange: function(range) {
|
|
7886
8178
|
$.extend(this, range); // assigns every property to this object's member variables
|
|
@@ -7963,6 +8255,7 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
7963
8255
|
// Sets the view's title property to the most updated computed value
|
|
7964
8256
|
updateTitle: function() {
|
|
7965
8257
|
this.title = this.computeTitle();
|
|
8258
|
+
this.calendar.setToolbarsTitle(this.title);
|
|
7966
8259
|
},
|
|
7967
8260
|
|
|
7968
8261
|
|
|
@@ -8068,164 +8361,219 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
8068
8361
|
},
|
|
8069
8362
|
|
|
8070
8363
|
|
|
8071
|
-
|
|
8072
|
-
|
|
8364
|
+
// Rendering Non-date-related Content
|
|
8365
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
8073
8366
|
|
|
8074
8367
|
|
|
8075
|
-
// Sets the container element that the view should render inside of
|
|
8076
|
-
//
|
|
8368
|
+
// Sets the container element that the view should render inside of, does global DOM-related initializations,
|
|
8369
|
+
// and renders all the non-date-related content inside.
|
|
8077
8370
|
setElement: function(el) {
|
|
8078
8371
|
this.el = el;
|
|
8079
8372
|
this.bindGlobalHandlers();
|
|
8373
|
+
this.renderSkeleton();
|
|
8080
8374
|
},
|
|
8081
8375
|
|
|
8082
8376
|
|
|
8083
8377
|
// Removes the view's container element from the DOM, clearing any content beforehand.
|
|
8084
8378
|
// Undoes any other DOM-related attachments.
|
|
8085
8379
|
removeElement: function() {
|
|
8086
|
-
this.
|
|
8087
|
-
|
|
8088
|
-
// clean up the skeleton
|
|
8089
|
-
if (this.isSkeletonRendered) {
|
|
8090
|
-
this.unrenderSkeleton();
|
|
8091
|
-
this.isSkeletonRendered = false;
|
|
8092
|
-
}
|
|
8380
|
+
this.unsetDate();
|
|
8381
|
+
this.unrenderSkeleton();
|
|
8093
8382
|
|
|
8094
8383
|
this.unbindGlobalHandlers();
|
|
8095
8384
|
|
|
8096
8385
|
this.el.remove();
|
|
8097
|
-
|
|
8098
8386
|
// NOTE: don't null-out this.el in case the View was destroyed within an API callback.
|
|
8099
8387
|
// We don't null-out the View's other jQuery element references upon destroy,
|
|
8100
8388
|
// so we shouldn't kill this.el either.
|
|
8101
8389
|
},
|
|
8102
8390
|
|
|
8103
8391
|
|
|
8104
|
-
//
|
|
8105
|
-
|
|
8106
|
-
|
|
8107
|
-
|
|
8108
|
-
|
|
8109
|
-
|
|
8392
|
+
// Renders the basic structure of the view before any content is rendered
|
|
8393
|
+
renderSkeleton: function() {
|
|
8394
|
+
// subclasses should implement
|
|
8395
|
+
},
|
|
8396
|
+
|
|
8397
|
+
|
|
8398
|
+
// Unrenders the basic structure of the view
|
|
8399
|
+
unrenderSkeleton: function() {
|
|
8400
|
+
// subclasses should implement
|
|
8401
|
+
},
|
|
8402
|
+
|
|
8403
|
+
|
|
8404
|
+
// Date Setting/Unsetting
|
|
8405
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
8406
|
+
|
|
8407
|
+
|
|
8408
|
+
setDate: function(date) {
|
|
8409
|
+
var isReset = this.isDateSet;
|
|
8410
|
+
|
|
8411
|
+
this.isDateSet = true;
|
|
8412
|
+
this.handleDate(date, isReset);
|
|
8413
|
+
this.trigger(isReset ? 'dateReset' : 'dateSet', date);
|
|
8414
|
+
},
|
|
8415
|
+
|
|
8110
8416
|
|
|
8111
|
-
|
|
8112
|
-
|
|
8417
|
+
unsetDate: function() {
|
|
8418
|
+
if (this.isDateSet) {
|
|
8419
|
+
this.isDateSet = false;
|
|
8420
|
+
this.handleDateUnset();
|
|
8421
|
+
this.trigger('dateUnset');
|
|
8113
8422
|
}
|
|
8423
|
+
},
|
|
8114
8424
|
|
|
8115
|
-
this.calendar.freezeContentHeight();
|
|
8116
8425
|
|
|
8117
|
-
|
|
8118
|
-
|
|
8119
|
-
_this.displaying =
|
|
8120
|
-
syncThen(_this.displayView(date), function() { // displayView might return a promise
|
|
8426
|
+
// Date Handling
|
|
8427
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
8121
8428
|
|
|
8122
|
-
// caller of display() wants a specific scroll state?
|
|
8123
|
-
if (explicitScrollState != null) {
|
|
8124
|
-
// we make an assumption that this is NOT the initial render,
|
|
8125
|
-
// and thus don't need forceScroll (is inconveniently asynchronous)
|
|
8126
|
-
_this.setScroll(explicitScrollState);
|
|
8127
|
-
}
|
|
8128
|
-
else {
|
|
8129
|
-
_this.forceScroll(_this.computeInitialScroll(prevScrollState));
|
|
8130
|
-
}
|
|
8131
8429
|
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8430
|
+
handleDate: function(date, isReset) {
|
|
8431
|
+
var _this = this;
|
|
8432
|
+
|
|
8433
|
+
this.unbindEvents(); // will do nothing if not already bound
|
|
8434
|
+
this.requestDateRender(date).then(function() {
|
|
8435
|
+
// wish we could start earlier, but setRange/computeRange needs to execute first
|
|
8436
|
+
_this.bindEvents(); // will request events
|
|
8136
8437
|
});
|
|
8137
8438
|
},
|
|
8138
8439
|
|
|
8139
8440
|
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
8143
|
-
|
|
8441
|
+
handleDateUnset: function() {
|
|
8442
|
+
this.unbindEvents();
|
|
8443
|
+
this.requestDateUnrender();
|
|
8444
|
+
},
|
|
8445
|
+
|
|
8446
|
+
|
|
8447
|
+
// Date Render Queuing
|
|
8448
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
8449
|
+
|
|
8450
|
+
|
|
8451
|
+
// if date not specified, uses current
|
|
8452
|
+
requestDateRender: function(date) {
|
|
8144
8453
|
var _this = this;
|
|
8145
|
-
var displaying = this.displaying;
|
|
8146
8454
|
|
|
8147
|
-
|
|
8148
|
-
return
|
|
8149
|
-
|
|
8150
|
-
_this.clearEvents();
|
|
8151
|
-
return _this.clearView(); // might return a promise. chain it
|
|
8152
|
-
});
|
|
8153
|
-
}
|
|
8154
|
-
else {
|
|
8155
|
-
return $.when(); // an immediately-resolved promise
|
|
8156
|
-
}
|
|
8455
|
+
return this.dateRenderQueue.add(function() {
|
|
8456
|
+
return _this.executeDateRender(date);
|
|
8457
|
+
});
|
|
8157
8458
|
},
|
|
8158
8459
|
|
|
8159
8460
|
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
|
|
8163
|
-
|
|
8164
|
-
|
|
8165
|
-
|
|
8166
|
-
|
|
8167
|
-
|
|
8461
|
+
requestDateUnrender: function() {
|
|
8462
|
+
var _this = this;
|
|
8463
|
+
|
|
8464
|
+
return this.dateRenderQueue.add(function() {
|
|
8465
|
+
return _this.executeDateUnrender();
|
|
8466
|
+
});
|
|
8467
|
+
},
|
|
8468
|
+
|
|
8469
|
+
|
|
8470
|
+
// Date High-level Rendering
|
|
8471
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
8472
|
+
|
|
8473
|
+
|
|
8474
|
+
// if date not specified, uses current
|
|
8475
|
+
executeDateRender: function(date) {
|
|
8476
|
+
var _this = this;
|
|
8477
|
+
|
|
8478
|
+
// if rendering a new date, reset scroll to initial state (scrollTime)
|
|
8168
8479
|
if (date) {
|
|
8169
|
-
this.
|
|
8480
|
+
this.captureInitialScroll();
|
|
8170
8481
|
}
|
|
8171
|
-
|
|
8172
|
-
this.
|
|
8482
|
+
else {
|
|
8483
|
+
this.captureScroll(); // a rerender of the current date
|
|
8173
8484
|
}
|
|
8174
|
-
|
|
8175
|
-
this.
|
|
8176
|
-
|
|
8177
|
-
this.
|
|
8485
|
+
|
|
8486
|
+
this.freezeHeight();
|
|
8487
|
+
|
|
8488
|
+
return this.executeDateUnrender().then(function() {
|
|
8489
|
+
|
|
8490
|
+
if (date) {
|
|
8491
|
+
_this.setRange(_this.computeRange(date));
|
|
8492
|
+
}
|
|
8493
|
+
|
|
8494
|
+
if (_this.render) {
|
|
8495
|
+
_this.render(); // TODO: deprecate
|
|
8496
|
+
}
|
|
8497
|
+
|
|
8498
|
+
_this.renderDates();
|
|
8499
|
+
_this.updateSize();
|
|
8500
|
+
_this.renderBusinessHours(); // might need coordinates, so should go after updateSize()
|
|
8501
|
+
_this.startNowIndicator();
|
|
8502
|
+
|
|
8503
|
+
_this.thawHeight();
|
|
8504
|
+
_this.releaseScroll();
|
|
8505
|
+
|
|
8506
|
+
_this.isDateRendered = true;
|
|
8507
|
+
_this.onDateRender();
|
|
8508
|
+
_this.trigger('dateRender');
|
|
8509
|
+
});
|
|
8178
8510
|
},
|
|
8179
8511
|
|
|
8180
8512
|
|
|
8181
|
-
|
|
8182
|
-
|
|
8183
|
-
|
|
8184
|
-
|
|
8185
|
-
|
|
8186
|
-
|
|
8187
|
-
|
|
8188
|
-
|
|
8189
|
-
|
|
8190
|
-
|
|
8513
|
+
executeDateUnrender: function() {
|
|
8514
|
+
var _this = this;
|
|
8515
|
+
|
|
8516
|
+
if (_this.isDateRendered) {
|
|
8517
|
+
return this.requestEventsUnrender().then(function() {
|
|
8518
|
+
|
|
8519
|
+
_this.unselect();
|
|
8520
|
+
_this.stopNowIndicator();
|
|
8521
|
+
_this.triggerUnrender();
|
|
8522
|
+
_this.unrenderBusinessHours();
|
|
8523
|
+
_this.unrenderDates();
|
|
8524
|
+
|
|
8525
|
+
if (_this.destroy) {
|
|
8526
|
+
_this.destroy(); // TODO: deprecate
|
|
8527
|
+
}
|
|
8528
|
+
|
|
8529
|
+
_this.isDateRendered = false;
|
|
8530
|
+
_this.trigger('dateUnrender');
|
|
8531
|
+
});
|
|
8532
|
+
}
|
|
8533
|
+
else {
|
|
8534
|
+
return Promise.resolve();
|
|
8191
8535
|
}
|
|
8192
8536
|
},
|
|
8193
8537
|
|
|
8194
8538
|
|
|
8195
|
-
//
|
|
8196
|
-
|
|
8197
|
-
// subclasses should implement
|
|
8198
|
-
},
|
|
8539
|
+
// Date Rendering Triggers
|
|
8540
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
8199
8541
|
|
|
8200
8542
|
|
|
8201
|
-
|
|
8202
|
-
|
|
8203
|
-
// subclasses should implement
|
|
8543
|
+
onDateRender: function() {
|
|
8544
|
+
this.triggerRender();
|
|
8204
8545
|
},
|
|
8205
8546
|
|
|
8206
8547
|
|
|
8207
|
-
//
|
|
8208
|
-
//
|
|
8548
|
+
// Date Low-level Rendering
|
|
8549
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
8550
|
+
|
|
8551
|
+
|
|
8552
|
+
// date-cell content only
|
|
8209
8553
|
renderDates: function() {
|
|
8210
8554
|
// subclasses should implement
|
|
8211
8555
|
},
|
|
8212
8556
|
|
|
8213
8557
|
|
|
8214
|
-
//
|
|
8558
|
+
// date-cell content only
|
|
8215
8559
|
unrenderDates: function() {
|
|
8216
8560
|
// subclasses should override
|
|
8217
8561
|
},
|
|
8218
8562
|
|
|
8219
8563
|
|
|
8564
|
+
// Misc view rendering utils
|
|
8565
|
+
// -------------------------
|
|
8566
|
+
|
|
8567
|
+
|
|
8220
8568
|
// Signals that the view's content has been rendered
|
|
8221
8569
|
triggerRender: function() {
|
|
8222
|
-
this.
|
|
8570
|
+
this.publiclyTrigger('viewRender', this, this, this.el);
|
|
8223
8571
|
},
|
|
8224
8572
|
|
|
8225
8573
|
|
|
8226
8574
|
// Signals that the view's content is about to be unrendered
|
|
8227
8575
|
triggerUnrender: function() {
|
|
8228
|
-
this.
|
|
8576
|
+
this.publiclyTrigger('viewDestroy', this, this, this.el);
|
|
8229
8577
|
},
|
|
8230
8578
|
|
|
8231
8579
|
|
|
@@ -8362,10 +8710,9 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
8362
8710
|
|
|
8363
8711
|
// Refreshes anything dependant upon sizing of the container element of the grid
|
|
8364
8712
|
updateSize: function(isResize) {
|
|
8365
|
-
var scrollState;
|
|
8366
8713
|
|
|
8367
8714
|
if (isResize) {
|
|
8368
|
-
|
|
8715
|
+
this.captureScroll();
|
|
8369
8716
|
}
|
|
8370
8717
|
|
|
8371
8718
|
this.updateHeight(isResize);
|
|
@@ -8373,7 +8720,7 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
8373
8720
|
this.updateNowIndicator();
|
|
8374
8721
|
|
|
8375
8722
|
if (isResize) {
|
|
8376
|
-
this.
|
|
8723
|
+
this.releaseScroll();
|
|
8377
8724
|
}
|
|
8378
8725
|
},
|
|
8379
8726
|
|
|
@@ -8406,72 +8753,294 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
8406
8753
|
------------------------------------------------------------------------------------------------------------------*/
|
|
8407
8754
|
|
|
8408
8755
|
|
|
8409
|
-
|
|
8410
|
-
|
|
8411
|
-
|
|
8412
|
-
|
|
8756
|
+
capturedScroll: null,
|
|
8757
|
+
capturedScrollDepth: 0,
|
|
8758
|
+
|
|
8759
|
+
|
|
8760
|
+
captureScroll: function() {
|
|
8761
|
+
if (!(this.capturedScrollDepth++)) {
|
|
8762
|
+
this.capturedScroll = this.isDateRendered ? this.queryScroll() : {}; // require a render first
|
|
8763
|
+
return true; // root?
|
|
8764
|
+
}
|
|
8765
|
+
return false;
|
|
8413
8766
|
},
|
|
8414
8767
|
|
|
8415
8768
|
|
|
8416
|
-
|
|
8417
|
-
|
|
8418
|
-
|
|
8769
|
+
captureInitialScroll: function(forcedScroll) {
|
|
8770
|
+
if (this.captureScroll()) { // root?
|
|
8771
|
+
this.capturedScroll.isInitial = true;
|
|
8772
|
+
|
|
8773
|
+
if (forcedScroll) {
|
|
8774
|
+
$.extend(this.capturedScroll, forcedScroll);
|
|
8775
|
+
}
|
|
8776
|
+
else {
|
|
8777
|
+
this.capturedScroll.isComputed = true;
|
|
8778
|
+
}
|
|
8779
|
+
}
|
|
8419
8780
|
},
|
|
8420
8781
|
|
|
8421
8782
|
|
|
8422
|
-
|
|
8423
|
-
|
|
8424
|
-
|
|
8783
|
+
releaseScroll: function() {
|
|
8784
|
+
var scroll = this.capturedScroll;
|
|
8785
|
+
var isRoot = this.discardScroll();
|
|
8786
|
+
|
|
8787
|
+
if (scroll.isComputed) {
|
|
8788
|
+
if (isRoot) {
|
|
8789
|
+
// only compute initial scroll if it will actually be used (is the root capture)
|
|
8790
|
+
$.extend(scroll, this.computeInitialScroll());
|
|
8791
|
+
}
|
|
8792
|
+
else {
|
|
8793
|
+
scroll = null; // scroll couldn't be computed. don't apply it to the DOM
|
|
8794
|
+
}
|
|
8795
|
+
}
|
|
8796
|
+
|
|
8797
|
+
if (scroll) {
|
|
8798
|
+
// we act immediately on a releaseScroll operation, as opposed to captureScroll.
|
|
8799
|
+
// if capture/release wraps a render operation that screws up the scroll,
|
|
8800
|
+
// we still want to restore it a good state after, regardless of depth.
|
|
8801
|
+
|
|
8802
|
+
if (scroll.isInitial) {
|
|
8803
|
+
this.hardSetScroll(scroll); // outsmart how browsers set scroll on initial DOM
|
|
8804
|
+
}
|
|
8805
|
+
else {
|
|
8806
|
+
this.setScroll(scroll);
|
|
8807
|
+
}
|
|
8808
|
+
}
|
|
8809
|
+
},
|
|
8810
|
+
|
|
8811
|
+
|
|
8812
|
+
discardScroll: function() {
|
|
8813
|
+
if (!(--this.capturedScrollDepth)) {
|
|
8814
|
+
this.capturedScroll = null;
|
|
8815
|
+
return true; // root?
|
|
8816
|
+
}
|
|
8817
|
+
return false;
|
|
8818
|
+
},
|
|
8819
|
+
|
|
8820
|
+
|
|
8821
|
+
computeInitialScroll: function() {
|
|
8822
|
+
return {};
|
|
8425
8823
|
},
|
|
8426
8824
|
|
|
8427
8825
|
|
|
8428
|
-
|
|
8429
|
-
|
|
8826
|
+
queryScroll: function() {
|
|
8827
|
+
return {};
|
|
8828
|
+
},
|
|
8829
|
+
|
|
8830
|
+
|
|
8831
|
+
hardSetScroll: function(scroll) {
|
|
8430
8832
|
var _this = this;
|
|
8833
|
+
var exec = function() { _this.setScroll(scroll); };
|
|
8834
|
+
exec();
|
|
8835
|
+
setTimeout(exec, 0); // to surely clear the browser's initial scroll for the DOM
|
|
8836
|
+
},
|
|
8431
8837
|
|
|
8432
|
-
|
|
8433
|
-
|
|
8434
|
-
_this.setScroll(scrollState);
|
|
8435
|
-
}, 0);
|
|
8838
|
+
|
|
8839
|
+
setScroll: function(scroll) {
|
|
8436
8840
|
},
|
|
8437
8841
|
|
|
8438
8842
|
|
|
8439
|
-
/*
|
|
8843
|
+
/* Height Freezing
|
|
8440
8844
|
------------------------------------------------------------------------------------------------------------------*/
|
|
8441
8845
|
|
|
8442
8846
|
|
|
8443
|
-
|
|
8444
|
-
|
|
8445
|
-
|
|
8847
|
+
freezeHeight: function() {
|
|
8848
|
+
this.calendar.freezeContentHeight();
|
|
8849
|
+
},
|
|
8850
|
+
|
|
8851
|
+
|
|
8852
|
+
thawHeight: function() {
|
|
8853
|
+
this.calendar.thawContentHeight();
|
|
8854
|
+
},
|
|
8855
|
+
|
|
8856
|
+
|
|
8857
|
+
// Event Binding/Unbinding
|
|
8858
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
8859
|
+
|
|
8860
|
+
|
|
8861
|
+
bindEvents: function() {
|
|
8862
|
+
var _this = this;
|
|
8863
|
+
|
|
8864
|
+
if (!this.isEventsBound) {
|
|
8865
|
+
this.isEventsBound = true;
|
|
8866
|
+
this.rejectOn('eventsUnbind', this.requestEvents()).then(function(events) { // TODO: test rejection
|
|
8867
|
+
_this.listenTo(_this.calendar, 'eventsReset', _this.setEvents);
|
|
8868
|
+
_this.setEvents(events);
|
|
8869
|
+
});
|
|
8870
|
+
}
|
|
8871
|
+
},
|
|
8872
|
+
|
|
8873
|
+
|
|
8874
|
+
unbindEvents: function() {
|
|
8875
|
+
if (this.isEventsBound) {
|
|
8876
|
+
this.isEventsBound = false;
|
|
8877
|
+
this.stopListeningTo(this.calendar, 'eventsReset');
|
|
8878
|
+
this.unsetEvents();
|
|
8879
|
+
this.trigger('eventsUnbind');
|
|
8880
|
+
}
|
|
8881
|
+
},
|
|
8882
|
+
|
|
8883
|
+
|
|
8884
|
+
// Event Setting/Unsetting
|
|
8885
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
8886
|
+
|
|
8887
|
+
|
|
8888
|
+
setEvents: function(events) {
|
|
8889
|
+
var isReset = this.isEventSet;
|
|
8890
|
+
|
|
8891
|
+
this.isEventsSet = true;
|
|
8892
|
+
this.handleEvents(events, isReset);
|
|
8893
|
+
this.trigger(isReset ? 'eventsReset' : 'eventsSet', events);
|
|
8894
|
+
},
|
|
8895
|
+
|
|
8896
|
+
|
|
8897
|
+
unsetEvents: function() {
|
|
8898
|
+
if (this.isEventsSet) {
|
|
8899
|
+
this.isEventsSet = false;
|
|
8900
|
+
this.handleEventsUnset();
|
|
8901
|
+
this.trigger('eventsUnset');
|
|
8902
|
+
}
|
|
8903
|
+
},
|
|
8904
|
+
|
|
8905
|
+
|
|
8906
|
+
whenEventsSet: function() {
|
|
8907
|
+
var _this = this;
|
|
8908
|
+
|
|
8909
|
+
if (this.isEventsSet) {
|
|
8910
|
+
return Promise.resolve(this.getCurrentEvents());
|
|
8911
|
+
}
|
|
8912
|
+
else {
|
|
8913
|
+
return new Promise(function(resolve) {
|
|
8914
|
+
_this.one('eventsSet', resolve);
|
|
8915
|
+
});
|
|
8916
|
+
}
|
|
8917
|
+
},
|
|
8918
|
+
|
|
8919
|
+
|
|
8920
|
+
// Event Handling
|
|
8921
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
8922
|
+
|
|
8923
|
+
|
|
8924
|
+
handleEvents: function(events, isReset) {
|
|
8925
|
+
this.requestEventsRender(events);
|
|
8926
|
+
},
|
|
8927
|
+
|
|
8928
|
+
|
|
8929
|
+
handleEventsUnset: function() {
|
|
8930
|
+
this.requestEventsUnrender();
|
|
8931
|
+
},
|
|
8932
|
+
|
|
8933
|
+
|
|
8934
|
+
// Event Render Queuing
|
|
8935
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
8936
|
+
|
|
8937
|
+
|
|
8938
|
+
// assumes any previous event renders have been cleared already
|
|
8939
|
+
requestEventsRender: function(events) {
|
|
8940
|
+
var _this = this;
|
|
8941
|
+
|
|
8942
|
+
return this.eventRenderQueue.add(function() { // might not return a promise if debounced!? bad
|
|
8943
|
+
return _this.executeEventsRender(events);
|
|
8944
|
+
});
|
|
8945
|
+
},
|
|
8446
8946
|
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
this.
|
|
8947
|
+
|
|
8948
|
+
requestEventsUnrender: function() {
|
|
8949
|
+
var _this = this;
|
|
8950
|
+
|
|
8951
|
+
if (this.isEventsRendered) {
|
|
8952
|
+
return this.eventRenderQueue.addQuickly(function() {
|
|
8953
|
+
return _this.executeEventsUnrender();
|
|
8954
|
+
});
|
|
8955
|
+
}
|
|
8956
|
+
else {
|
|
8957
|
+
return Promise.resolve();
|
|
8958
|
+
}
|
|
8452
8959
|
},
|
|
8453
8960
|
|
|
8454
8961
|
|
|
8455
|
-
|
|
8456
|
-
|
|
8457
|
-
|
|
8962
|
+
requestCurrentEventsRender: function() {
|
|
8963
|
+
if (this.isEventsSet) {
|
|
8964
|
+
this.requestEventsRender(this.getCurrentEvents());
|
|
8965
|
+
}
|
|
8966
|
+
else {
|
|
8967
|
+
return Promise.reject();
|
|
8968
|
+
}
|
|
8969
|
+
},
|
|
8970
|
+
|
|
8971
|
+
|
|
8972
|
+
// Event High-level Rendering
|
|
8973
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
8974
|
+
|
|
8975
|
+
|
|
8976
|
+
executeEventsRender: function(events) {
|
|
8977
|
+
var _this = this;
|
|
8978
|
+
|
|
8979
|
+
this.captureScroll();
|
|
8980
|
+
this.freezeHeight();
|
|
8981
|
+
|
|
8982
|
+
return this.executeEventsUnrender().then(function() {
|
|
8983
|
+
_this.renderEvents(events);
|
|
8984
|
+
|
|
8985
|
+
_this.thawHeight();
|
|
8986
|
+
_this.releaseScroll();
|
|
8987
|
+
|
|
8988
|
+
_this.isEventsRendered = true;
|
|
8989
|
+
_this.onEventsRender();
|
|
8990
|
+
_this.trigger('eventsRender');
|
|
8991
|
+
});
|
|
8992
|
+
},
|
|
8993
|
+
|
|
8458
8994
|
|
|
8995
|
+
executeEventsUnrender: function() {
|
|
8459
8996
|
if (this.isEventsRendered) {
|
|
8997
|
+
this.onBeforeEventsUnrender();
|
|
8460
8998
|
|
|
8461
|
-
|
|
8462
|
-
|
|
8999
|
+
this.captureScroll();
|
|
9000
|
+
this.freezeHeight();
|
|
8463
9001
|
|
|
8464
|
-
this.triggerEventUnrender();
|
|
8465
9002
|
if (this.destroyEvents) {
|
|
8466
9003
|
this.destroyEvents(); // TODO: deprecate
|
|
8467
9004
|
}
|
|
9005
|
+
|
|
8468
9006
|
this.unrenderEvents();
|
|
8469
|
-
|
|
9007
|
+
|
|
9008
|
+
this.thawHeight();
|
|
9009
|
+
this.releaseScroll();
|
|
9010
|
+
|
|
8470
9011
|
this.isEventsRendered = false;
|
|
9012
|
+
this.trigger('eventsUnrender');
|
|
8471
9013
|
}
|
|
9014
|
+
|
|
9015
|
+
return Promise.resolve(); // always synchronous
|
|
9016
|
+
},
|
|
9017
|
+
|
|
9018
|
+
|
|
9019
|
+
// Event Rendering Triggers
|
|
9020
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
9021
|
+
|
|
9022
|
+
|
|
9023
|
+
// Signals that all events have been rendered
|
|
9024
|
+
onEventsRender: function() {
|
|
9025
|
+
this.renderedEventSegEach(function(seg) {
|
|
9026
|
+
this.publiclyTrigger('eventAfterRender', seg.event, seg.event, seg.el);
|
|
9027
|
+
});
|
|
9028
|
+
this.publiclyTrigger('eventAfterAllRender');
|
|
9029
|
+
},
|
|
9030
|
+
|
|
9031
|
+
|
|
9032
|
+
// Signals that all event elements are about to be removed
|
|
9033
|
+
onBeforeEventsUnrender: function() {
|
|
9034
|
+
this.renderedEventSegEach(function(seg) {
|
|
9035
|
+
this.publiclyTrigger('eventDestroy', seg.event, seg.event, seg.el);
|
|
9036
|
+
});
|
|
8472
9037
|
},
|
|
8473
9038
|
|
|
8474
9039
|
|
|
9040
|
+
// Event Low-level Rendering
|
|
9041
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
9042
|
+
|
|
9043
|
+
|
|
8475
9044
|
// Renders the events onto the view.
|
|
8476
9045
|
renderEvents: function(events) {
|
|
8477
9046
|
// subclasses should implement
|
|
@@ -8484,27 +9053,28 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
8484
9053
|
},
|
|
8485
9054
|
|
|
8486
9055
|
|
|
8487
|
-
//
|
|
8488
|
-
|
|
8489
|
-
|
|
8490
|
-
|
|
8491
|
-
|
|
8492
|
-
this.
|
|
9056
|
+
// Event Data Access
|
|
9057
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
9058
|
+
|
|
9059
|
+
|
|
9060
|
+
requestEvents: function() {
|
|
9061
|
+
return this.calendar.requestEvents(this.start, this.end);
|
|
8493
9062
|
},
|
|
8494
9063
|
|
|
8495
9064
|
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
this.renderedEventSegEach(function(seg) {
|
|
8499
|
-
this.trigger('eventDestroy', seg.event, seg.event, seg.el);
|
|
8500
|
-
});
|
|
9065
|
+
getCurrentEvents: function() {
|
|
9066
|
+
return this.calendar.getPrunedEventCache();
|
|
8501
9067
|
},
|
|
8502
9068
|
|
|
8503
9069
|
|
|
9070
|
+
// Event Rendering Utils
|
|
9071
|
+
// -----------------------------------------------------------------------------------------------------------------
|
|
9072
|
+
|
|
9073
|
+
|
|
8504
9074
|
// Given an event and the default element used for rendering, returns the element that should actually be used.
|
|
8505
9075
|
// Basically runs events and elements through the eventRender hook.
|
|
8506
9076
|
resolveEventEl: function(event, el) {
|
|
8507
|
-
var custom = this.
|
|
9077
|
+
var custom = this.publiclyTrigger('eventRender', event, event, el);
|
|
8508
9078
|
|
|
8509
9079
|
if (custom === false) { // means don't render at all
|
|
8510
9080
|
el = null;
|
|
@@ -8603,7 +9173,7 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
8603
9173
|
|
|
8604
9174
|
// Triggers event-drop handlers that have subscribed via the API
|
|
8605
9175
|
triggerEventDrop: function(event, dateDelta, undoFunc, el, ev) {
|
|
8606
|
-
this.
|
|
9176
|
+
this.publiclyTrigger('eventDrop', el[0], event, dateDelta, undoFunc, ev, {}); // {} = jqui dummy
|
|
8607
9177
|
},
|
|
8608
9178
|
|
|
8609
9179
|
|
|
@@ -8633,10 +9203,10 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
8633
9203
|
triggerExternalDrop: function(event, dropLocation, el, ev, ui) {
|
|
8634
9204
|
|
|
8635
9205
|
// trigger 'drop' regardless of whether element represents an event
|
|
8636
|
-
this.
|
|
9206
|
+
this.publiclyTrigger('drop', el[0], dropLocation.start, ev, ui);
|
|
8637
9207
|
|
|
8638
9208
|
if (event) {
|
|
8639
|
-
this.
|
|
9209
|
+
this.publiclyTrigger('eventReceive', null, event); // signal an external event landed
|
|
8640
9210
|
}
|
|
8641
9211
|
},
|
|
8642
9212
|
|
|
@@ -8706,7 +9276,7 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
8706
9276
|
|
|
8707
9277
|
// Triggers event-resize handlers that have subscribed via the API
|
|
8708
9278
|
triggerEventResize: function(event, durationDelta, undoFunc, el, ev) {
|
|
8709
|
-
this.
|
|
9279
|
+
this.publiclyTrigger('eventResize', el[0], event, durationDelta, undoFunc, ev, {}); // {} = jqui dummy
|
|
8710
9280
|
},
|
|
8711
9281
|
|
|
8712
9282
|
|
|
@@ -8738,7 +9308,7 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
8738
9308
|
|
|
8739
9309
|
// Triggers handlers to 'select'
|
|
8740
9310
|
triggerSelect: function(span, ev) {
|
|
8741
|
-
this.
|
|
9311
|
+
this.publiclyTrigger(
|
|
8742
9312
|
'select',
|
|
8743
9313
|
null,
|
|
8744
9314
|
this.calendar.applyTimezone(span.start), // convert to calendar's tz for external API
|
|
@@ -8757,7 +9327,7 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
8757
9327
|
this.destroySelection(); // TODO: deprecate
|
|
8758
9328
|
}
|
|
8759
9329
|
this.unrenderSelection();
|
|
8760
|
-
this.
|
|
9330
|
+
this.publiclyTrigger('unselect', null, ev);
|
|
8761
9331
|
}
|
|
8762
9332
|
},
|
|
8763
9333
|
|
|
@@ -8849,7 +9419,7 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
8849
9419
|
// Triggers handlers to 'dayClick'
|
|
8850
9420
|
// Span has start/end of the clicked area. Only the start is useful.
|
|
8851
9421
|
triggerDayClick: function(span, dayEl, ev) {
|
|
8852
|
-
this.
|
|
9422
|
+
this.publiclyTrigger(
|
|
8853
9423
|
'dayClick',
|
|
8854
9424
|
dayEl,
|
|
8855
9425
|
this.calendar.applyTimezone(span.start), // convert to calendar's timezone for external API
|
|
@@ -9076,208 +9646,498 @@ var Scroller = FC.Scroller = Class.extend({
|
|
|
9076
9646
|
});
|
|
9077
9647
|
|
|
9078
9648
|
;;
|
|
9649
|
+
function Iterator(items) {
|
|
9650
|
+
this.items = items || [];
|
|
9651
|
+
}
|
|
9079
9652
|
|
|
9080
|
-
var Calendar = FC.Calendar = Class.extend({
|
|
9081
9653
|
|
|
9082
|
-
|
|
9083
|
-
|
|
9084
|
-
|
|
9085
|
-
|
|
9086
|
-
options: null, // all defaults combined with overrides
|
|
9087
|
-
viewSpecCache: null, // cache of view definitions
|
|
9088
|
-
view: null, // current View object
|
|
9089
|
-
header: null,
|
|
9090
|
-
loadingLevel: 0, // number of simultaneous loading tasks
|
|
9654
|
+
/* Calls a method on every item passing the arguments through */
|
|
9655
|
+
Iterator.prototype.proxyCall = function(methodName) {
|
|
9656
|
+
var args = Array.prototype.slice.call(arguments, 1);
|
|
9657
|
+
var results = [];
|
|
9091
9658
|
|
|
9659
|
+
this.items.forEach(function(item) {
|
|
9660
|
+
results.push(item[methodName].apply(item, args));
|
|
9661
|
+
});
|
|
9092
9662
|
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
constructor: Calendar_constructor,
|
|
9663
|
+
return results;
|
|
9664
|
+
};
|
|
9096
9665
|
|
|
9666
|
+
;;
|
|
9097
9667
|
|
|
9098
|
-
|
|
9099
|
-
|
|
9100
|
-
},
|
|
9668
|
+
/* Toolbar with buttons and title
|
|
9669
|
+
----------------------------------------------------------------------------------------------------------------------*/
|
|
9101
9670
|
|
|
9671
|
+
function Toolbar(calendar, toolbarOptions) {
|
|
9672
|
+
var t = this;
|
|
9102
9673
|
|
|
9103
|
-
//
|
|
9104
|
-
|
|
9105
|
-
|
|
9106
|
-
|
|
9107
|
-
|
|
9674
|
+
// exports
|
|
9675
|
+
t.setToolbarOptions = setToolbarOptions;
|
|
9676
|
+
t.render = render;
|
|
9677
|
+
t.removeElement = removeElement;
|
|
9678
|
+
t.updateTitle = updateTitle;
|
|
9679
|
+
t.activateButton = activateButton;
|
|
9680
|
+
t.deactivateButton = deactivateButton;
|
|
9681
|
+
t.disableButton = disableButton;
|
|
9682
|
+
t.enableButton = enableButton;
|
|
9683
|
+
t.getViewsWithButtons = getViewsWithButtons;
|
|
9684
|
+
t.el = null; // mirrors local `el`
|
|
9108
9685
|
|
|
9109
|
-
|
|
9110
|
-
|
|
9111
|
-
|
|
9112
|
-
|
|
9113
|
-
localeDefaults = localeOptionHash[locale];
|
|
9114
|
-
if (!localeDefaults) { // explicit locale option not given or invalid?
|
|
9115
|
-
locale = Calendar.defaults.locale;
|
|
9116
|
-
localeDefaults = localeOptionHash[locale] || {};
|
|
9117
|
-
}
|
|
9686
|
+
// locals
|
|
9687
|
+
var el;
|
|
9688
|
+
var viewsWithButtons = [];
|
|
9689
|
+
var tm;
|
|
9118
9690
|
|
|
9119
|
-
|
|
9120
|
-
|
|
9121
|
-
|
|
9122
|
-
|
|
9123
|
-
Calendar.defaults.isRTL
|
|
9124
|
-
);
|
|
9125
|
-
dirDefaults = isRTL ? Calendar.rtlDefaults : {};
|
|
9691
|
+
// method to update toolbar-specific options, not calendar-wide options
|
|
9692
|
+
function setToolbarOptions(newToolbarOptions) {
|
|
9693
|
+
toolbarOptions = newToolbarOptions;
|
|
9694
|
+
}
|
|
9126
9695
|
|
|
9127
|
-
|
|
9128
|
-
|
|
9129
|
-
|
|
9130
|
-
Calendar.defaults, // global defaults
|
|
9131
|
-
dirDefaults,
|
|
9132
|
-
localeDefaults,
|
|
9133
|
-
this.overrides,
|
|
9134
|
-
this.dynamicOverrides
|
|
9135
|
-
]);
|
|
9136
|
-
populateInstanceComputableOptions(this.options); // fill in gaps with computed options
|
|
9137
|
-
},
|
|
9696
|
+
// can be called repeatedly and will rerender
|
|
9697
|
+
function render() {
|
|
9698
|
+
var sections = toolbarOptions.layout;
|
|
9138
9699
|
|
|
9700
|
+
tm = calendar.options.theme ? 'ui' : 'fc';
|
|
9139
9701
|
|
|
9140
|
-
|
|
9141
|
-
|
|
9142
|
-
|
|
9702
|
+
if (sections) {
|
|
9703
|
+
if (!el) {
|
|
9704
|
+
el = this.el = $("<div class='fc-toolbar "+ toolbarOptions.extraClasses + "'/>");
|
|
9705
|
+
}
|
|
9706
|
+
else {
|
|
9707
|
+
el.empty();
|
|
9708
|
+
}
|
|
9709
|
+
el.append(renderSection('left'))
|
|
9710
|
+
.append(renderSection('right'))
|
|
9711
|
+
.append(renderSection('center'))
|
|
9712
|
+
.append('<div class="fc-clear"/>');
|
|
9713
|
+
}
|
|
9714
|
+
else {
|
|
9715
|
+
removeElement();
|
|
9716
|
+
}
|
|
9717
|
+
}
|
|
9143
9718
|
|
|
9144
|
-
return cache[viewType] || (cache[viewType] = this.buildViewSpec(viewType));
|
|
9145
|
-
},
|
|
9146
9719
|
|
|
9720
|
+
function removeElement() {
|
|
9721
|
+
if (el) {
|
|
9722
|
+
el.remove();
|
|
9723
|
+
el = t.el = null;
|
|
9724
|
+
}
|
|
9725
|
+
}
|
|
9147
9726
|
|
|
9148
|
-
// Given a duration singular unit, like "week" or "day", finds a matching view spec.
|
|
9149
|
-
// Preference is given to views that have corresponding buttons.
|
|
9150
|
-
getUnitViewSpec: function(unit) {
|
|
9151
|
-
var viewTypes;
|
|
9152
|
-
var i;
|
|
9153
|
-
var spec;
|
|
9154
9727
|
|
|
9155
|
-
|
|
9728
|
+
function renderSection(position) {
|
|
9729
|
+
var sectionEl = $('<div class="fc-' + position + '"/>');
|
|
9730
|
+
var buttonStr = toolbarOptions.layout[position];
|
|
9156
9731
|
|
|
9157
|
-
|
|
9158
|
-
|
|
9159
|
-
|
|
9160
|
-
|
|
9161
|
-
|
|
9732
|
+
if (buttonStr) {
|
|
9733
|
+
$.each(buttonStr.split(' '), function(i) {
|
|
9734
|
+
var groupChildren = $();
|
|
9735
|
+
var isOnlyButtons = true;
|
|
9736
|
+
var groupEl;
|
|
9162
9737
|
|
|
9163
|
-
|
|
9164
|
-
|
|
9165
|
-
|
|
9166
|
-
|
|
9167
|
-
|
|
9738
|
+
$.each(this.split(','), function(j, buttonName) {
|
|
9739
|
+
var customButtonProps;
|
|
9740
|
+
var viewSpec;
|
|
9741
|
+
var buttonClick;
|
|
9742
|
+
var overrideText; // text explicitly set by calendar's constructor options. overcomes icons
|
|
9743
|
+
var defaultText;
|
|
9744
|
+
var themeIcon;
|
|
9745
|
+
var normalIcon;
|
|
9746
|
+
var innerHtml;
|
|
9747
|
+
var classes;
|
|
9748
|
+
var button; // the element
|
|
9749
|
+
|
|
9750
|
+
if (buttonName == 'title') {
|
|
9751
|
+
groupChildren = groupChildren.add($('<h2> </h2>')); // we always want it to take up height
|
|
9752
|
+
isOnlyButtons = false;
|
|
9168
9753
|
}
|
|
9169
|
-
|
|
9170
|
-
|
|
9171
|
-
|
|
9172
|
-
|
|
9754
|
+
else {
|
|
9755
|
+
if ((customButtonProps = (calendar.options.customButtons || {})[buttonName])) {
|
|
9756
|
+
buttonClick = function(ev) {
|
|
9757
|
+
if (customButtonProps.click) {
|
|
9758
|
+
customButtonProps.click.call(button[0], ev);
|
|
9759
|
+
}
|
|
9760
|
+
};
|
|
9761
|
+
overrideText = ''; // icons will override text
|
|
9762
|
+
defaultText = customButtonProps.text;
|
|
9763
|
+
}
|
|
9764
|
+
else if ((viewSpec = calendar.getViewSpec(buttonName))) {
|
|
9765
|
+
buttonClick = function() {
|
|
9766
|
+
calendar.changeView(buttonName);
|
|
9767
|
+
};
|
|
9768
|
+
viewsWithButtons.push(buttonName);
|
|
9769
|
+
overrideText = viewSpec.buttonTextOverride;
|
|
9770
|
+
defaultText = viewSpec.buttonTextDefault;
|
|
9771
|
+
}
|
|
9772
|
+
else if (calendar[buttonName]) { // a calendar method
|
|
9773
|
+
buttonClick = function() {
|
|
9774
|
+
calendar[buttonName]();
|
|
9775
|
+
};
|
|
9776
|
+
overrideText = (calendar.overrides.buttonText || {})[buttonName];
|
|
9777
|
+
defaultText = calendar.options.buttonText[buttonName]; // everything else is considered default
|
|
9778
|
+
}
|
|
9173
9779
|
|
|
9780
|
+
if (buttonClick) {
|
|
9174
9781
|
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
var defaultsChain = []; // for the view. lowest to highest priority
|
|
9180
|
-
var overridesChain = []; // for the view. lowest to highest priority
|
|
9181
|
-
var viewType = requestedViewType;
|
|
9182
|
-
var spec; // for the view
|
|
9183
|
-
var overrides; // for the view
|
|
9184
|
-
var duration;
|
|
9185
|
-
var unit;
|
|
9782
|
+
themeIcon =
|
|
9783
|
+
customButtonProps ?
|
|
9784
|
+
customButtonProps.themeIcon :
|
|
9785
|
+
calendar.options.themeButtonIcons[buttonName];
|
|
9186
9786
|
|
|
9187
|
-
|
|
9188
|
-
|
|
9189
|
-
|
|
9190
|
-
|
|
9191
|
-
viewType = null; // clear. might repopulate for another iteration
|
|
9787
|
+
normalIcon =
|
|
9788
|
+
customButtonProps ?
|
|
9789
|
+
customButtonProps.icon :
|
|
9790
|
+
calendar.options.buttonIcons[buttonName];
|
|
9192
9791
|
|
|
9193
|
-
|
|
9194
|
-
|
|
9195
|
-
|
|
9792
|
+
if (overrideText) {
|
|
9793
|
+
innerHtml = htmlEscape(overrideText);
|
|
9794
|
+
}
|
|
9795
|
+
else if (themeIcon && calendar.options.theme) {
|
|
9796
|
+
innerHtml = "<span class='ui-icon ui-icon-" + themeIcon + "'></span>";
|
|
9797
|
+
}
|
|
9798
|
+
else if (normalIcon && !calendar.options.theme) {
|
|
9799
|
+
innerHtml = "<span class='fc-icon fc-icon-" + normalIcon + "'></span>";
|
|
9800
|
+
}
|
|
9801
|
+
else {
|
|
9802
|
+
innerHtml = htmlEscape(defaultText);
|
|
9803
|
+
}
|
|
9196
9804
|
|
|
9197
|
-
|
|
9198
|
-
|
|
9199
|
-
|
|
9200
|
-
|
|
9201
|
-
|
|
9202
|
-
}
|
|
9805
|
+
classes = [
|
|
9806
|
+
'fc-' + buttonName + '-button',
|
|
9807
|
+
tm + '-button',
|
|
9808
|
+
tm + '-state-default'
|
|
9809
|
+
];
|
|
9203
9810
|
|
|
9204
|
-
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
|
|
9208
|
-
|
|
9209
|
-
|
|
9811
|
+
button = $( // type="button" so that it doesn't submit a form
|
|
9812
|
+
'<button type="button" class="' + classes.join(' ') + '">' +
|
|
9813
|
+
innerHtml +
|
|
9814
|
+
'</button>'
|
|
9815
|
+
)
|
|
9816
|
+
.click(function(ev) {
|
|
9817
|
+
// don't process clicks for disabled buttons
|
|
9818
|
+
if (!button.hasClass(tm + '-state-disabled')) {
|
|
9210
9819
|
|
|
9211
|
-
|
|
9212
|
-
spec.type = requestedViewType;
|
|
9213
|
-
if (!spec['class']) {
|
|
9214
|
-
return false;
|
|
9215
|
-
}
|
|
9820
|
+
buttonClick(ev);
|
|
9216
9821
|
|
|
9217
|
-
|
|
9218
|
-
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9822
|
+
// after the click action, if the button becomes the "active" tab, or disabled,
|
|
9823
|
+
// it should never have a hover class, so remove it now.
|
|
9824
|
+
if (
|
|
9825
|
+
button.hasClass(tm + '-state-active') ||
|
|
9826
|
+
button.hasClass(tm + '-state-disabled')
|
|
9827
|
+
) {
|
|
9828
|
+
button.removeClass(tm + '-state-hover');
|
|
9829
|
+
}
|
|
9830
|
+
}
|
|
9831
|
+
})
|
|
9832
|
+
.mousedown(function() {
|
|
9833
|
+
// the *down* effect (mouse pressed in).
|
|
9834
|
+
// only on buttons that are not the "active" tab, or disabled
|
|
9835
|
+
button
|
|
9836
|
+
.not('.' + tm + '-state-active')
|
|
9837
|
+
.not('.' + tm + '-state-disabled')
|
|
9838
|
+
.addClass(tm + '-state-down');
|
|
9839
|
+
})
|
|
9840
|
+
.mouseup(function() {
|
|
9841
|
+
// undo the *down* effect
|
|
9842
|
+
button.removeClass(tm + '-state-down');
|
|
9843
|
+
})
|
|
9844
|
+
.hover(
|
|
9845
|
+
function() {
|
|
9846
|
+
// the *hover* effect.
|
|
9847
|
+
// only on buttons that are not the "active" tab, or disabled
|
|
9848
|
+
button
|
|
9849
|
+
.not('.' + tm + '-state-active')
|
|
9850
|
+
.not('.' + tm + '-state-disabled')
|
|
9851
|
+
.addClass(tm + '-state-hover');
|
|
9852
|
+
},
|
|
9853
|
+
function() {
|
|
9854
|
+
// undo the *hover* effect
|
|
9855
|
+
button
|
|
9856
|
+
.removeClass(tm + '-state-hover')
|
|
9857
|
+
.removeClass(tm + '-state-down'); // if mouseleave happens before mouseup
|
|
9858
|
+
}
|
|
9859
|
+
);
|
|
9222
9860
|
|
|
9223
|
-
|
|
9224
|
-
|
|
9225
|
-
|
|
9226
|
-
|
|
9227
|
-
|
|
9861
|
+
groupChildren = groupChildren.add(button);
|
|
9862
|
+
}
|
|
9863
|
+
}
|
|
9864
|
+
});
|
|
9865
|
+
|
|
9866
|
+
if (isOnlyButtons) {
|
|
9867
|
+
groupChildren
|
|
9868
|
+
.first().addClass(tm + '-corner-left').end()
|
|
9869
|
+
.last().addClass(tm + '-corner-right').end();
|
|
9228
9870
|
}
|
|
9229
|
-
}
|
|
9230
|
-
}
|
|
9231
9871
|
|
|
9232
|
-
|
|
9233
|
-
|
|
9872
|
+
if (groupChildren.length > 1) {
|
|
9873
|
+
groupEl = $('<div/>');
|
|
9874
|
+
if (isOnlyButtons) {
|
|
9875
|
+
groupEl.addClass('fc-button-group');
|
|
9876
|
+
}
|
|
9877
|
+
groupEl.append(groupChildren);
|
|
9878
|
+
sectionEl.append(groupEl);
|
|
9879
|
+
}
|
|
9880
|
+
else {
|
|
9881
|
+
sectionEl.append(groupChildren); // 1 or 0 children
|
|
9882
|
+
}
|
|
9883
|
+
});
|
|
9884
|
+
}
|
|
9234
9885
|
|
|
9235
|
-
|
|
9236
|
-
|
|
9886
|
+
return sectionEl;
|
|
9887
|
+
}
|
|
9237
9888
|
|
|
9238
|
-
return spec;
|
|
9239
|
-
},
|
|
9240
9889
|
|
|
9890
|
+
function updateTitle(text) {
|
|
9891
|
+
if (el) {
|
|
9892
|
+
el.find('h2').text(text);
|
|
9893
|
+
}
|
|
9894
|
+
}
|
|
9241
9895
|
|
|
9242
|
-
// Builds and assigns a view spec's options object from its already-assigned defaults and overrides
|
|
9243
|
-
buildViewSpecOptions: function(spec) {
|
|
9244
|
-
spec.options = mergeOptions([ // lowest to highest priority
|
|
9245
|
-
Calendar.defaults, // global defaults
|
|
9246
|
-
spec.defaults, // view's defaults (from ViewSubclass.defaults)
|
|
9247
|
-
this.dirDefaults,
|
|
9248
|
-
this.localeDefaults, // locale and dir take precedence over view's defaults!
|
|
9249
|
-
this.overrides, // calendar's overrides (options given to constructor)
|
|
9250
|
-
spec.overrides, // view's overrides (view-specific options)
|
|
9251
|
-
this.dynamicOverrides // dynamically set via setter. highest precedence
|
|
9252
|
-
]);
|
|
9253
|
-
populateInstanceComputableOptions(spec.options);
|
|
9254
|
-
},
|
|
9255
9896
|
|
|
9897
|
+
function activateButton(buttonName) {
|
|
9898
|
+
if (el) {
|
|
9899
|
+
el.find('.fc-' + buttonName + '-button')
|
|
9900
|
+
.addClass(tm + '-state-active');
|
|
9901
|
+
}
|
|
9902
|
+
}
|
|
9256
9903
|
|
|
9257
|
-
// Computes and assigns a view spec's buttonText-related options
|
|
9258
|
-
buildViewSpecButtonText: function(spec, requestedViewType) {
|
|
9259
9904
|
|
|
9260
|
-
|
|
9261
|
-
|
|
9262
|
-
|
|
9263
|
-
|
|
9264
|
-
return buttonText[requestedViewType] ||
|
|
9265
|
-
// view can decide to look up a certain key
|
|
9266
|
-
(spec.buttonTextKey ? buttonText[spec.buttonTextKey] : null) ||
|
|
9267
|
-
// a key like "month"
|
|
9268
|
-
(spec.singleUnit ? buttonText[spec.singleUnit] : null);
|
|
9905
|
+
function deactivateButton(buttonName) {
|
|
9906
|
+
if (el) {
|
|
9907
|
+
el.find('.fc-' + buttonName + '-button')
|
|
9908
|
+
.removeClass(tm + '-state-active');
|
|
9269
9909
|
}
|
|
9910
|
+
}
|
|
9270
9911
|
|
|
9271
|
-
// highest to lowest priority
|
|
9272
|
-
spec.buttonTextOverride =
|
|
9273
|
-
queryButtonText(this.dynamicOverrides) ||
|
|
9274
|
-
queryButtonText(this.overrides) || // constructor-specified buttonText lookup hash takes precedence
|
|
9275
|
-
spec.overrides.buttonText; // `buttonText` for view-specific options is a string
|
|
9276
9912
|
|
|
9277
|
-
|
|
9278
|
-
|
|
9279
|
-
|
|
9280
|
-
|
|
9913
|
+
function disableButton(buttonName) {
|
|
9914
|
+
if (el) {
|
|
9915
|
+
el.find('.fc-' + buttonName + '-button')
|
|
9916
|
+
.prop('disabled', true)
|
|
9917
|
+
.addClass(tm + '-state-disabled');
|
|
9918
|
+
}
|
|
9919
|
+
}
|
|
9920
|
+
|
|
9921
|
+
|
|
9922
|
+
function enableButton(buttonName) {
|
|
9923
|
+
if (el) {
|
|
9924
|
+
el.find('.fc-' + buttonName + '-button')
|
|
9925
|
+
.prop('disabled', false)
|
|
9926
|
+
.removeClass(tm + '-state-disabled');
|
|
9927
|
+
}
|
|
9928
|
+
}
|
|
9929
|
+
|
|
9930
|
+
|
|
9931
|
+
function getViewsWithButtons() {
|
|
9932
|
+
return viewsWithButtons;
|
|
9933
|
+
}
|
|
9934
|
+
|
|
9935
|
+
}
|
|
9936
|
+
|
|
9937
|
+
;;
|
|
9938
|
+
|
|
9939
|
+
var Calendar = FC.Calendar = Class.extend({
|
|
9940
|
+
|
|
9941
|
+
dirDefaults: null, // option defaults related to LTR or RTL
|
|
9942
|
+
localeDefaults: null, // option defaults related to current locale
|
|
9943
|
+
overrides: null, // option overrides given to the fullCalendar constructor
|
|
9944
|
+
dynamicOverrides: null, // options set with dynamic setter method. higher precedence than view overrides.
|
|
9945
|
+
options: null, // all defaults combined with overrides
|
|
9946
|
+
viewSpecCache: null, // cache of view definitions
|
|
9947
|
+
view: null, // current View object
|
|
9948
|
+
header: null,
|
|
9949
|
+
footer: null,
|
|
9950
|
+
loadingLevel: 0, // number of simultaneous loading tasks
|
|
9951
|
+
|
|
9952
|
+
|
|
9953
|
+
// a lot of this class' OOP logic is scoped within this constructor function,
|
|
9954
|
+
// but in the future, write individual methods on the prototype.
|
|
9955
|
+
constructor: Calendar_constructor,
|
|
9956
|
+
|
|
9957
|
+
|
|
9958
|
+
// Subclasses can override this for initialization logic after the constructor has been called
|
|
9959
|
+
initialize: function() {
|
|
9960
|
+
},
|
|
9961
|
+
|
|
9962
|
+
|
|
9963
|
+
// Computes the flattened options hash for the calendar and assigns to `this.options`.
|
|
9964
|
+
// Assumes this.overrides and this.dynamicOverrides have already been initialized.
|
|
9965
|
+
populateOptionsHash: function() {
|
|
9966
|
+
var locale, localeDefaults;
|
|
9967
|
+
var isRTL, dirDefaults;
|
|
9968
|
+
|
|
9969
|
+
locale = firstDefined( // explicit locale option given?
|
|
9970
|
+
this.dynamicOverrides.locale,
|
|
9971
|
+
this.overrides.locale
|
|
9972
|
+
);
|
|
9973
|
+
localeDefaults = localeOptionHash[locale];
|
|
9974
|
+
if (!localeDefaults) { // explicit locale option not given or invalid?
|
|
9975
|
+
locale = Calendar.defaults.locale;
|
|
9976
|
+
localeDefaults = localeOptionHash[locale] || {};
|
|
9977
|
+
}
|
|
9978
|
+
|
|
9979
|
+
isRTL = firstDefined( // based on options computed so far, is direction RTL?
|
|
9980
|
+
this.dynamicOverrides.isRTL,
|
|
9981
|
+
this.overrides.isRTL,
|
|
9982
|
+
localeDefaults.isRTL,
|
|
9983
|
+
Calendar.defaults.isRTL
|
|
9984
|
+
);
|
|
9985
|
+
dirDefaults = isRTL ? Calendar.rtlDefaults : {};
|
|
9986
|
+
|
|
9987
|
+
this.dirDefaults = dirDefaults;
|
|
9988
|
+
this.localeDefaults = localeDefaults;
|
|
9989
|
+
this.options = mergeOptions([ // merge defaults and overrides. lowest to highest precedence
|
|
9990
|
+
Calendar.defaults, // global defaults
|
|
9991
|
+
dirDefaults,
|
|
9992
|
+
localeDefaults,
|
|
9993
|
+
this.overrides,
|
|
9994
|
+
this.dynamicOverrides
|
|
9995
|
+
]);
|
|
9996
|
+
populateInstanceComputableOptions(this.options); // fill in gaps with computed options
|
|
9997
|
+
},
|
|
9998
|
+
|
|
9999
|
+
|
|
10000
|
+
// Gets information about how to create a view. Will use a cache.
|
|
10001
|
+
getViewSpec: function(viewType) {
|
|
10002
|
+
var cache = this.viewSpecCache;
|
|
10003
|
+
|
|
10004
|
+
return cache[viewType] || (cache[viewType] = this.buildViewSpec(viewType));
|
|
10005
|
+
},
|
|
10006
|
+
|
|
10007
|
+
|
|
10008
|
+
// Given a duration singular unit, like "week" or "day", finds a matching view spec.
|
|
10009
|
+
// Preference is given to views that have corresponding buttons.
|
|
10010
|
+
getUnitViewSpec: function(unit) {
|
|
10011
|
+
var viewTypes;
|
|
10012
|
+
var i;
|
|
10013
|
+
var spec;
|
|
10014
|
+
|
|
10015
|
+
if ($.inArray(unit, intervalUnits) != -1) {
|
|
10016
|
+
|
|
10017
|
+
// put views that have buttons first. there will be duplicates, but oh well
|
|
10018
|
+
viewTypes = this.header.getViewsWithButtons(); // TODO: include footer as well?
|
|
10019
|
+
$.each(FC.views, function(viewType) { // all views
|
|
10020
|
+
viewTypes.push(viewType);
|
|
10021
|
+
});
|
|
10022
|
+
|
|
10023
|
+
for (i = 0; i < viewTypes.length; i++) {
|
|
10024
|
+
spec = this.getViewSpec(viewTypes[i]);
|
|
10025
|
+
if (spec) {
|
|
10026
|
+
if (spec.singleUnit == unit) {
|
|
10027
|
+
return spec;
|
|
10028
|
+
}
|
|
10029
|
+
}
|
|
10030
|
+
}
|
|
10031
|
+
}
|
|
10032
|
+
},
|
|
10033
|
+
|
|
10034
|
+
|
|
10035
|
+
// Builds an object with information on how to create a given view
|
|
10036
|
+
buildViewSpec: function(requestedViewType) {
|
|
10037
|
+
var viewOverrides = this.overrides.views || {};
|
|
10038
|
+
var specChain = []; // for the view. lowest to highest priority
|
|
10039
|
+
var defaultsChain = []; // for the view. lowest to highest priority
|
|
10040
|
+
var overridesChain = []; // for the view. lowest to highest priority
|
|
10041
|
+
var viewType = requestedViewType;
|
|
10042
|
+
var spec; // for the view
|
|
10043
|
+
var overrides; // for the view
|
|
10044
|
+
var duration;
|
|
10045
|
+
var unit;
|
|
10046
|
+
|
|
10047
|
+
// iterate from the specific view definition to a more general one until we hit an actual View class
|
|
10048
|
+
while (viewType) {
|
|
10049
|
+
spec = fcViews[viewType];
|
|
10050
|
+
overrides = viewOverrides[viewType];
|
|
10051
|
+
viewType = null; // clear. might repopulate for another iteration
|
|
10052
|
+
|
|
10053
|
+
if (typeof spec === 'function') { // TODO: deprecate
|
|
10054
|
+
spec = { 'class': spec };
|
|
10055
|
+
}
|
|
10056
|
+
|
|
10057
|
+
if (spec) {
|
|
10058
|
+
specChain.unshift(spec);
|
|
10059
|
+
defaultsChain.unshift(spec.defaults || {});
|
|
10060
|
+
duration = duration || spec.duration;
|
|
10061
|
+
viewType = viewType || spec.type;
|
|
10062
|
+
}
|
|
10063
|
+
|
|
10064
|
+
if (overrides) {
|
|
10065
|
+
overridesChain.unshift(overrides); // view-specific option hashes have options at zero-level
|
|
10066
|
+
duration = duration || overrides.duration;
|
|
10067
|
+
viewType = viewType || overrides.type;
|
|
10068
|
+
}
|
|
10069
|
+
}
|
|
10070
|
+
|
|
10071
|
+
spec = mergeProps(specChain);
|
|
10072
|
+
spec.type = requestedViewType;
|
|
10073
|
+
if (!spec['class']) {
|
|
10074
|
+
return false;
|
|
10075
|
+
}
|
|
10076
|
+
|
|
10077
|
+
if (duration) {
|
|
10078
|
+
duration = moment.duration(duration);
|
|
10079
|
+
if (duration.valueOf()) { // valid?
|
|
10080
|
+
spec.duration = duration;
|
|
10081
|
+
unit = computeIntervalUnit(duration);
|
|
10082
|
+
|
|
10083
|
+
// view is a single-unit duration, like "week" or "day"
|
|
10084
|
+
// incorporate options for this. lowest priority
|
|
10085
|
+
if (duration.as(unit) === 1) {
|
|
10086
|
+
spec.singleUnit = unit;
|
|
10087
|
+
overridesChain.unshift(viewOverrides[unit] || {});
|
|
10088
|
+
}
|
|
10089
|
+
}
|
|
10090
|
+
}
|
|
10091
|
+
|
|
10092
|
+
spec.defaults = mergeOptions(defaultsChain);
|
|
10093
|
+
spec.overrides = mergeOptions(overridesChain);
|
|
10094
|
+
|
|
10095
|
+
this.buildViewSpecOptions(spec);
|
|
10096
|
+
this.buildViewSpecButtonText(spec, requestedViewType);
|
|
10097
|
+
|
|
10098
|
+
return spec;
|
|
10099
|
+
},
|
|
10100
|
+
|
|
10101
|
+
|
|
10102
|
+
// Builds and assigns a view spec's options object from its already-assigned defaults and overrides
|
|
10103
|
+
buildViewSpecOptions: function(spec) {
|
|
10104
|
+
spec.options = mergeOptions([ // lowest to highest priority
|
|
10105
|
+
Calendar.defaults, // global defaults
|
|
10106
|
+
spec.defaults, // view's defaults (from ViewSubclass.defaults)
|
|
10107
|
+
this.dirDefaults,
|
|
10108
|
+
this.localeDefaults, // locale and dir take precedence over view's defaults!
|
|
10109
|
+
this.overrides, // calendar's overrides (options given to constructor)
|
|
10110
|
+
spec.overrides, // view's overrides (view-specific options)
|
|
10111
|
+
this.dynamicOverrides // dynamically set via setter. highest precedence
|
|
10112
|
+
]);
|
|
10113
|
+
populateInstanceComputableOptions(spec.options);
|
|
10114
|
+
},
|
|
10115
|
+
|
|
10116
|
+
|
|
10117
|
+
// Computes and assigns a view spec's buttonText-related options
|
|
10118
|
+
buildViewSpecButtonText: function(spec, requestedViewType) {
|
|
10119
|
+
|
|
10120
|
+
// given an options object with a possible `buttonText` hash, lookup the buttonText for the
|
|
10121
|
+
// requested view, falling back to a generic unit entry like "week" or "day"
|
|
10122
|
+
function queryButtonText(options) {
|
|
10123
|
+
var buttonText = options.buttonText || {};
|
|
10124
|
+
return buttonText[requestedViewType] ||
|
|
10125
|
+
// view can decide to look up a certain key
|
|
10126
|
+
(spec.buttonTextKey ? buttonText[spec.buttonTextKey] : null) ||
|
|
10127
|
+
// a key like "month"
|
|
10128
|
+
(spec.singleUnit ? buttonText[spec.singleUnit] : null);
|
|
10129
|
+
}
|
|
10130
|
+
|
|
10131
|
+
// highest to lowest priority
|
|
10132
|
+
spec.buttonTextOverride =
|
|
10133
|
+
queryButtonText(this.dynamicOverrides) ||
|
|
10134
|
+
queryButtonText(this.overrides) || // constructor-specified buttonText lookup hash takes precedence
|
|
10135
|
+
spec.overrides.buttonText; // `buttonText` for view-specific options is a string
|
|
10136
|
+
|
|
10137
|
+
// highest to lowest priority. mirrors buildViewSpecOptions
|
|
10138
|
+
spec.buttonTextDefault =
|
|
10139
|
+
queryButtonText(this.localeDefaults) ||
|
|
10140
|
+
queryButtonText(this.dirDefaults) ||
|
|
9281
10141
|
spec.defaults.buttonText || // a single string. from ViewSubclass.defaults
|
|
9282
10142
|
queryButtonText(Calendar.defaults) ||
|
|
9283
10143
|
(spec.duration ? this.humanizeDuration(spec.duration) : null) || // like "3 days"
|
|
@@ -9302,7 +10162,7 @@ var Calendar = FC.Calendar = Class.extend({
|
|
|
9302
10162
|
// Should be called when any type of async data fetching begins
|
|
9303
10163
|
pushLoading: function() {
|
|
9304
10164
|
if (!(this.loadingLevel++)) {
|
|
9305
|
-
this.
|
|
10165
|
+
this.publiclyTrigger('loading', null, true, this.view);
|
|
9306
10166
|
}
|
|
9307
10167
|
},
|
|
9308
10168
|
|
|
@@ -9310,7 +10170,7 @@ var Calendar = FC.Calendar = Class.extend({
|
|
|
9310
10170
|
// Should be called when any type of async data fetching completes
|
|
9311
10171
|
popLoading: function() {
|
|
9312
10172
|
if (!(--this.loadingLevel)) {
|
|
9313
|
-
this.
|
|
10173
|
+
this.publiclyTrigger('loading', null, false, this.view);
|
|
9314
10174
|
}
|
|
9315
10175
|
},
|
|
9316
10176
|
|
|
@@ -9348,11 +10208,7 @@ function Calendar_constructor(element, overrides) {
|
|
|
9348
10208
|
|
|
9349
10209
|
t.render = render;
|
|
9350
10210
|
t.destroy = destroy;
|
|
9351
|
-
t.
|
|
9352
|
-
t.refetchEventSources = refetchEventSources;
|
|
9353
|
-
t.reportEvents = reportEvents;
|
|
9354
|
-
t.reportEventChange = reportEventChange;
|
|
9355
|
-
t.rerenderEvents = renderEvents; // `renderEvents` serves as a rerender. an API method
|
|
10211
|
+
t.rerenderEvents = rerenderEvents;
|
|
9356
10212
|
t.changeView = renderView; // `renderView` will switch to another view
|
|
9357
10213
|
t.select = select;
|
|
9358
10214
|
t.unselect = unselect;
|
|
@@ -9368,7 +10224,7 @@ function Calendar_constructor(element, overrides) {
|
|
|
9368
10224
|
t.getCalendar = getCalendar;
|
|
9369
10225
|
t.getView = getView;
|
|
9370
10226
|
t.option = option; // getter/setter method
|
|
9371
|
-
t.
|
|
10227
|
+
t.publiclyTrigger = publiclyTrigger;
|
|
9372
10228
|
|
|
9373
10229
|
|
|
9374
10230
|
// Options
|
|
@@ -9561,15 +10417,12 @@ function Calendar_constructor(element, overrides) {
|
|
|
9561
10417
|
};
|
|
9562
10418
|
|
|
9563
10419
|
|
|
9564
|
-
|
|
10420
|
+
|
|
9565
10421
|
// Imports
|
|
9566
10422
|
// -----------------------------------------------------------------------------------
|
|
9567
10423
|
|
|
9568
10424
|
|
|
9569
10425
|
EventManager.call(t);
|
|
9570
|
-
var isFetchNeeded = t.isFetchNeeded;
|
|
9571
|
-
var fetchEvents = t.fetchEvents;
|
|
9572
|
-
var fetchEventSources = t.fetchEventSources;
|
|
9573
10426
|
|
|
9574
10427
|
|
|
9575
10428
|
|
|
@@ -9578,7 +10431,9 @@ function Calendar_constructor(element, overrides) {
|
|
|
9578
10431
|
|
|
9579
10432
|
|
|
9580
10433
|
var _element = element[0];
|
|
10434
|
+
var toolbarsManager;
|
|
9581
10435
|
var header;
|
|
10436
|
+
var footer;
|
|
9582
10437
|
var content;
|
|
9583
10438
|
var tm; // for making theme classes
|
|
9584
10439
|
var currentView; // NOTE: keep this in sync with this.view
|
|
@@ -9586,11 +10441,10 @@ function Calendar_constructor(element, overrides) {
|
|
|
9586
10441
|
var suggestedViewHeight;
|
|
9587
10442
|
var windowResizeProxy; // wraps the windowResize function
|
|
9588
10443
|
var ignoreWindowResize = 0;
|
|
9589
|
-
var events = [];
|
|
9590
10444
|
var date; // unzoned
|
|
9591
|
-
|
|
9592
|
-
|
|
9593
|
-
|
|
10445
|
+
|
|
10446
|
+
|
|
10447
|
+
|
|
9594
10448
|
// Main Rendering
|
|
9595
10449
|
// -----------------------------------------------------------------------------------
|
|
9596
10450
|
|
|
@@ -9602,8 +10456,8 @@ function Calendar_constructor(element, overrides) {
|
|
|
9602
10456
|
else {
|
|
9603
10457
|
date = t.getNow(); // getNow already returns unzoned
|
|
9604
10458
|
}
|
|
9605
|
-
|
|
9606
|
-
|
|
10459
|
+
|
|
10460
|
+
|
|
9607
10461
|
function render() {
|
|
9608
10462
|
if (!content) {
|
|
9609
10463
|
initialRender();
|
|
@@ -9614,8 +10468,8 @@ function Calendar_constructor(element, overrides) {
|
|
|
9614
10468
|
renderView();
|
|
9615
10469
|
}
|
|
9616
10470
|
}
|
|
9617
|
-
|
|
9618
|
-
|
|
10471
|
+
|
|
10472
|
+
|
|
9619
10473
|
function initialRender() {
|
|
9620
10474
|
element.addClass('fc');
|
|
9621
10475
|
|
|
@@ -9656,9 +10510,14 @@ function Calendar_constructor(element, overrides) {
|
|
|
9656
10510
|
|
|
9657
10511
|
content = $("<div class='fc-view-container'/>").prependTo(element);
|
|
9658
10512
|
|
|
9659
|
-
|
|
9660
|
-
|
|
10513
|
+
var toolbars = buildToolbars();
|
|
10514
|
+
toolbarsManager = new Iterator(toolbars);
|
|
10515
|
+
|
|
10516
|
+
header = t.header = toolbars[0];
|
|
10517
|
+
footer = t.footer = toolbars[1];
|
|
9661
10518
|
|
|
10519
|
+
renderHeader();
|
|
10520
|
+
renderFooter();
|
|
9662
10521
|
renderView(t.options.defaultView);
|
|
9663
10522
|
|
|
9664
10523
|
if (t.options.handleWindowResize) {
|
|
@@ -9668,15 +10527,6 @@ function Calendar_constructor(element, overrides) {
|
|
|
9668
10527
|
}
|
|
9669
10528
|
|
|
9670
10529
|
|
|
9671
|
-
// can be called repeatedly and Header will rerender
|
|
9672
|
-
function renderHeader() {
|
|
9673
|
-
header.render();
|
|
9674
|
-
if (header.el) {
|
|
9675
|
-
element.prepend(header.el);
|
|
9676
|
-
}
|
|
9677
|
-
}
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
10530
|
function destroy() {
|
|
9681
10531
|
|
|
9682
10532
|
if (currentView) {
|
|
@@ -9686,7 +10536,7 @@ function Calendar_constructor(element, overrides) {
|
|
|
9686
10536
|
// It is still the "current" view, just not rendered.
|
|
9687
10537
|
}
|
|
9688
10538
|
|
|
9689
|
-
|
|
10539
|
+
toolbarsManager.proxyCall('removeElement');
|
|
9690
10540
|
content.remove();
|
|
9691
10541
|
element.removeClass('fc fc-ltr fc-rtl fc-unthemed ui-widget');
|
|
9692
10542
|
|
|
@@ -9696,13 +10546,13 @@ function Calendar_constructor(element, overrides) {
|
|
|
9696
10546
|
$(window).unbind('resize', windowResizeProxy);
|
|
9697
10547
|
}
|
|
9698
10548
|
}
|
|
9699
|
-
|
|
9700
|
-
|
|
10549
|
+
|
|
10550
|
+
|
|
9701
10551
|
function elementVisible() {
|
|
9702
10552
|
return element.is(':visible');
|
|
9703
10553
|
}
|
|
9704
|
-
|
|
9705
|
-
|
|
10554
|
+
|
|
10555
|
+
|
|
9706
10556
|
|
|
9707
10557
|
// View Rendering
|
|
9708
10558
|
// -----------------------------------------------------------------------------------
|
|
@@ -9711,11 +10561,13 @@ function Calendar_constructor(element, overrides) {
|
|
|
9711
10561
|
// Renders a view because of a date change, view-type change, or for the first time.
|
|
9712
10562
|
// If not given a viewType, keep the current view but render different dates.
|
|
9713
10563
|
// Accepts an optional scroll state to restore to.
|
|
9714
|
-
function renderView(viewType,
|
|
10564
|
+
function renderView(viewType, forcedScroll) {
|
|
9715
10565
|
ignoreWindowResize++;
|
|
9716
10566
|
|
|
10567
|
+
var needsClearView = currentView && viewType && currentView.type !== viewType;
|
|
10568
|
+
|
|
9717
10569
|
// if viewType is changing, remove the old view's rendering
|
|
9718
|
-
if (
|
|
10570
|
+
if (needsClearView) {
|
|
9719
10571
|
freezeContentHeight(); // prevent a scroll jump when view element is removed
|
|
9720
10572
|
clearView();
|
|
9721
10573
|
}
|
|
@@ -9729,7 +10581,7 @@ function Calendar_constructor(element, overrides) {
|
|
|
9729
10581
|
currentView.setElement(
|
|
9730
10582
|
$("<div class='fc-view fc-" + viewType + "-view' />").appendTo(content)
|
|
9731
10583
|
);
|
|
9732
|
-
|
|
10584
|
+
toolbarsManager.proxyCall('activateButton', viewType);
|
|
9733
10585
|
}
|
|
9734
10586
|
|
|
9735
10587
|
if (currentView) {
|
|
@@ -9739,7 +10591,7 @@ function Calendar_constructor(element, overrides) {
|
|
|
9739
10591
|
|
|
9740
10592
|
// render or rerender the view
|
|
9741
10593
|
if (
|
|
9742
|
-
!currentView.
|
|
10594
|
+
!currentView.isDateSet ||
|
|
9743
10595
|
!( // NOT within interval range signals an implicit date window change
|
|
9744
10596
|
date >= currentView.intervalStart &&
|
|
9745
10597
|
date < currentView.intervalEnd
|
|
@@ -9747,19 +10599,27 @@ function Calendar_constructor(element, overrides) {
|
|
|
9747
10599
|
) {
|
|
9748
10600
|
if (elementVisible()) {
|
|
9749
10601
|
|
|
9750
|
-
|
|
9751
|
-
|
|
10602
|
+
if (forcedScroll) {
|
|
10603
|
+
currentView.captureInitialScroll(forcedScroll);
|
|
10604
|
+
}
|
|
10605
|
+
|
|
10606
|
+
currentView.setDate(date, forcedScroll);
|
|
9752
10607
|
|
|
9753
|
-
|
|
9754
|
-
|
|
9755
|
-
|
|
10608
|
+
if (forcedScroll) {
|
|
10609
|
+
currentView.releaseScroll();
|
|
10610
|
+
}
|
|
9756
10611
|
|
|
9757
|
-
|
|
10612
|
+
// need to do this after View::render, so dates are calculated
|
|
10613
|
+
// NOTE: view updates title text proactively
|
|
10614
|
+
updateToolbarsTodayButton();
|
|
9758
10615
|
}
|
|
9759
10616
|
}
|
|
9760
10617
|
}
|
|
9761
10618
|
|
|
9762
|
-
|
|
10619
|
+
if (needsClearView) {
|
|
10620
|
+
thawContentHeight();
|
|
10621
|
+
}
|
|
10622
|
+
|
|
9763
10623
|
ignoreWindowResize--;
|
|
9764
10624
|
}
|
|
9765
10625
|
|
|
@@ -9767,7 +10627,7 @@ function Calendar_constructor(element, overrides) {
|
|
|
9767
10627
|
// Unrenders the current view and reflects this change in the Header.
|
|
9768
10628
|
// Unregsiters the `currentView`, but does not remove from viewByType hash.
|
|
9769
10629
|
function clearView() {
|
|
9770
|
-
|
|
10630
|
+
toolbarsManager.proxyCall('deactivateButton', currentView.type);
|
|
9771
10631
|
currentView.removeElement();
|
|
9772
10632
|
currentView = t.view = null;
|
|
9773
10633
|
}
|
|
@@ -9783,13 +10643,14 @@ function Calendar_constructor(element, overrides) {
|
|
|
9783
10643
|
var viewType = currentView.type;
|
|
9784
10644
|
var scrollState = currentView.queryScroll();
|
|
9785
10645
|
clearView();
|
|
10646
|
+
calcSize();
|
|
9786
10647
|
renderView(viewType, scrollState);
|
|
9787
10648
|
|
|
9788
|
-
|
|
10649
|
+
thawContentHeight();
|
|
9789
10650
|
ignoreWindowResize--;
|
|
9790
10651
|
}
|
|
9791
10652
|
|
|
9792
|
-
|
|
10653
|
+
|
|
9793
10654
|
|
|
9794
10655
|
// Resizing
|
|
9795
10656
|
// -----------------------------------------------------------------------------------
|
|
@@ -9806,8 +10667,8 @@ function Calendar_constructor(element, overrides) {
|
|
|
9806
10667
|
t.isHeightAuto = function() {
|
|
9807
10668
|
return t.options.contentHeight === 'auto' || t.options.height === 'auto';
|
|
9808
10669
|
};
|
|
9809
|
-
|
|
9810
|
-
|
|
10670
|
+
|
|
10671
|
+
|
|
9811
10672
|
function updateSize(shouldRecalc) {
|
|
9812
10673
|
if (elementVisible()) {
|
|
9813
10674
|
|
|
@@ -9829,8 +10690,8 @@ function Calendar_constructor(element, overrides) {
|
|
|
9829
10690
|
_calcSize();
|
|
9830
10691
|
}
|
|
9831
10692
|
}
|
|
9832
|
-
|
|
9833
|
-
|
|
10693
|
+
|
|
10694
|
+
|
|
9834
10695
|
function _calcSize() { // assumes elementVisible
|
|
9835
10696
|
var contentHeightInput = t.options.contentHeight;
|
|
9836
10697
|
var heightInput = t.options.height;
|
|
@@ -9842,13 +10703,13 @@ function Calendar_constructor(element, overrides) {
|
|
|
9842
10703
|
suggestedViewHeight = contentHeightInput();
|
|
9843
10704
|
}
|
|
9844
10705
|
else if (typeof heightInput === 'number') { // exists and not 'auto'
|
|
9845
|
-
suggestedViewHeight = heightInput -
|
|
10706
|
+
suggestedViewHeight = heightInput - queryToolbarsHeight();
|
|
9846
10707
|
}
|
|
9847
10708
|
else if (typeof heightInput === 'function') { // exists and is a function
|
|
9848
|
-
suggestedViewHeight = heightInput() -
|
|
10709
|
+
suggestedViewHeight = heightInput() - queryToolbarsHeight();
|
|
9849
10710
|
}
|
|
9850
10711
|
else if (heightInput === 'parent') { // set to height of parent element
|
|
9851
|
-
suggestedViewHeight = element.parent().height() -
|
|
10712
|
+
suggestedViewHeight = element.parent().height() - queryToolbarsHeight();
|
|
9852
10713
|
}
|
|
9853
10714
|
else {
|
|
9854
10715
|
suggestedViewHeight = Math.round(content.width() / Math.max(t.options.aspectRatio, .5));
|
|
@@ -9856,11 +10717,14 @@ function Calendar_constructor(element, overrides) {
|
|
|
9856
10717
|
}
|
|
9857
10718
|
|
|
9858
10719
|
|
|
9859
|
-
function
|
|
9860
|
-
return
|
|
10720
|
+
function queryToolbarsHeight() {
|
|
10721
|
+
return toolbarsManager.items.reduce(function(accumulator, toolbar) {
|
|
10722
|
+
var toolbarHeight = toolbar.el ? toolbar.el.outerHeight(true) : 0; // includes margin
|
|
10723
|
+
return accumulator + toolbarHeight;
|
|
10724
|
+
}, 0);
|
|
9861
10725
|
}
|
|
9862
|
-
|
|
9863
|
-
|
|
10726
|
+
|
|
10727
|
+
|
|
9864
10728
|
function windowResize(ev) {
|
|
9865
10729
|
if (
|
|
9866
10730
|
!ignoreWindowResize &&
|
|
@@ -9868,94 +10732,93 @@ function Calendar_constructor(element, overrides) {
|
|
|
9868
10732
|
currentView.start // view has already been rendered
|
|
9869
10733
|
) {
|
|
9870
10734
|
if (updateSize(true)) {
|
|
9871
|
-
currentView.
|
|
10735
|
+
currentView.publiclyTrigger('windowResize', _element);
|
|
9872
10736
|
}
|
|
9873
10737
|
}
|
|
9874
10738
|
}
|
|
9875
|
-
|
|
9876
|
-
|
|
9877
|
-
|
|
9878
|
-
/* Event Fetching/Rendering
|
|
9879
|
-
-----------------------------------------------------------------------------*/
|
|
9880
|
-
// TODO: going forward, most of this stuff should be directly handled by the view
|
|
9881
10739
|
|
|
9882
10740
|
|
|
9883
|
-
function refetchEvents() { // can be called as an API method
|
|
9884
|
-
fetchAndRenderEvents();
|
|
9885
|
-
}
|
|
9886
|
-
|
|
9887
10741
|
|
|
9888
|
-
|
|
9889
|
-
|
|
9890
|
-
fetchEventSources(t.getEventSourcesByMatchArray(matchInputs));
|
|
9891
|
-
}
|
|
10742
|
+
/* Event Rendering
|
|
10743
|
+
-----------------------------------------------------------------------------*/
|
|
9892
10744
|
|
|
9893
10745
|
|
|
9894
|
-
function
|
|
10746
|
+
function rerenderEvents() { // API method. destroys old events if previously rendered.
|
|
9895
10747
|
if (elementVisible()) {
|
|
9896
|
-
|
|
9897
|
-
currentView.displayEvents(events);
|
|
9898
|
-
unfreezeContentHeight();
|
|
10748
|
+
t.reportEventChange(); // will re-trasmit events to the view, causing a rerender
|
|
9899
10749
|
}
|
|
9900
10750
|
}
|
|
9901
|
-
|
|
9902
10751
|
|
|
9903
|
-
function getAndRenderEvents() {
|
|
9904
|
-
if (!t.options.lazyFetching || isFetchNeeded(currentView.start, currentView.end)) {
|
|
9905
|
-
fetchAndRenderEvents();
|
|
9906
|
-
}
|
|
9907
|
-
else {
|
|
9908
|
-
renderEvents();
|
|
9909
|
-
}
|
|
9910
|
-
}
|
|
9911
10752
|
|
|
9912
10753
|
|
|
9913
|
-
|
|
9914
|
-
|
|
9915
|
-
// ... will call reportEvents
|
|
9916
|
-
// ... which will call renderEvents
|
|
9917
|
-
}
|
|
10754
|
+
/* Toolbars
|
|
10755
|
+
-----------------------------------------------------------------------------*/
|
|
9918
10756
|
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
|
|
9923
|
-
|
|
10757
|
+
|
|
10758
|
+
function buildToolbars() {
|
|
10759
|
+
return [
|
|
10760
|
+
new Toolbar(t, computeHeaderOptions()),
|
|
10761
|
+
new Toolbar(t, computeFooterOptions())
|
|
10762
|
+
];
|
|
9924
10763
|
}
|
|
9925
10764
|
|
|
9926
10765
|
|
|
9927
|
-
|
|
9928
|
-
|
|
9929
|
-
|
|
10766
|
+
function computeHeaderOptions() {
|
|
10767
|
+
return {
|
|
10768
|
+
extraClasses: 'fc-header-toolbar',
|
|
10769
|
+
layout: t.options.header
|
|
10770
|
+
};
|
|
9930
10771
|
}
|
|
9931
10772
|
|
|
9932
10773
|
|
|
10774
|
+
function computeFooterOptions() {
|
|
10775
|
+
return {
|
|
10776
|
+
extraClasses: 'fc-footer-toolbar',
|
|
10777
|
+
layout: t.options.footer
|
|
10778
|
+
};
|
|
10779
|
+
}
|
|
9933
10780
|
|
|
9934
|
-
|
|
9935
|
-
|
|
10781
|
+
|
|
10782
|
+
// can be called repeatedly and Header will rerender
|
|
10783
|
+
function renderHeader() {
|
|
10784
|
+
header.setToolbarOptions(computeHeaderOptions());
|
|
10785
|
+
header.render();
|
|
10786
|
+
if (header.el) {
|
|
10787
|
+
element.prepend(header.el);
|
|
10788
|
+
}
|
|
10789
|
+
}
|
|
9936
10790
|
|
|
9937
10791
|
|
|
9938
|
-
|
|
9939
|
-
|
|
10792
|
+
// can be called repeatedly and Footer will rerender
|
|
10793
|
+
function renderFooter() {
|
|
10794
|
+
footer.setToolbarOptions(computeFooterOptions());
|
|
10795
|
+
footer.render();
|
|
10796
|
+
if (footer.el) {
|
|
10797
|
+
element.append(footer.el);
|
|
10798
|
+
}
|
|
9940
10799
|
}
|
|
9941
10800
|
|
|
9942
10801
|
|
|
9943
|
-
function
|
|
9944
|
-
|
|
10802
|
+
t.setToolbarsTitle = function(title) {
|
|
10803
|
+
toolbarsManager.proxyCall('updateTitle', title);
|
|
10804
|
+
};
|
|
9945
10805
|
|
|
10806
|
+
|
|
10807
|
+
function updateToolbarsTodayButton() {
|
|
10808
|
+
var now = t.getNow();
|
|
9946
10809
|
if (now >= currentView.intervalStart && now < currentView.intervalEnd) {
|
|
9947
|
-
|
|
10810
|
+
toolbarsManager.proxyCall('disableButton', 'today');
|
|
9948
10811
|
}
|
|
9949
10812
|
else {
|
|
9950
|
-
|
|
10813
|
+
toolbarsManager.proxyCall('enableButton', 'today');
|
|
9951
10814
|
}
|
|
9952
10815
|
}
|
|
9953
|
-
|
|
10816
|
+
|
|
9954
10817
|
|
|
9955
10818
|
|
|
9956
10819
|
/* Selection
|
|
9957
10820
|
-----------------------------------------------------------------------------*/
|
|
9958
|
-
|
|
10821
|
+
|
|
9959
10822
|
|
|
9960
10823
|
// this public method receives start/end dates in any format, with any timezone
|
|
9961
10824
|
function select(zonedStartInput, zonedEndInput) {
|
|
@@ -9963,56 +10826,56 @@ function Calendar_constructor(element, overrides) {
|
|
|
9963
10826
|
t.buildSelectSpan.apply(t, arguments)
|
|
9964
10827
|
);
|
|
9965
10828
|
}
|
|
9966
|
-
|
|
10829
|
+
|
|
9967
10830
|
|
|
9968
10831
|
function unselect() { // safe to be called before renderView
|
|
9969
10832
|
if (currentView) {
|
|
9970
10833
|
currentView.unselect();
|
|
9971
10834
|
}
|
|
9972
10835
|
}
|
|
9973
|
-
|
|
9974
|
-
|
|
9975
|
-
|
|
10836
|
+
|
|
10837
|
+
|
|
10838
|
+
|
|
9976
10839
|
/* Date
|
|
9977
10840
|
-----------------------------------------------------------------------------*/
|
|
9978
|
-
|
|
9979
|
-
|
|
10841
|
+
|
|
10842
|
+
|
|
9980
10843
|
function prev() {
|
|
9981
10844
|
date = currentView.computePrevDate(date);
|
|
9982
10845
|
renderView();
|
|
9983
10846
|
}
|
|
9984
|
-
|
|
9985
|
-
|
|
10847
|
+
|
|
10848
|
+
|
|
9986
10849
|
function next() {
|
|
9987
10850
|
date = currentView.computeNextDate(date);
|
|
9988
10851
|
renderView();
|
|
9989
10852
|
}
|
|
9990
|
-
|
|
9991
|
-
|
|
10853
|
+
|
|
10854
|
+
|
|
9992
10855
|
function prevYear() {
|
|
9993
10856
|
date.add(-1, 'years');
|
|
9994
10857
|
renderView();
|
|
9995
10858
|
}
|
|
9996
|
-
|
|
9997
|
-
|
|
10859
|
+
|
|
10860
|
+
|
|
9998
10861
|
function nextYear() {
|
|
9999
10862
|
date.add(1, 'years');
|
|
10000
10863
|
renderView();
|
|
10001
10864
|
}
|
|
10002
|
-
|
|
10003
|
-
|
|
10865
|
+
|
|
10866
|
+
|
|
10004
10867
|
function today() {
|
|
10005
10868
|
date = t.getNow();
|
|
10006
10869
|
renderView();
|
|
10007
10870
|
}
|
|
10008
|
-
|
|
10009
|
-
|
|
10871
|
+
|
|
10872
|
+
|
|
10010
10873
|
function gotoDate(zonedDateInput) {
|
|
10011
10874
|
date = t.moment(zonedDateInput).stripZone();
|
|
10012
10875
|
renderView();
|
|
10013
10876
|
}
|
|
10014
|
-
|
|
10015
|
-
|
|
10877
|
+
|
|
10878
|
+
|
|
10016
10879
|
function incrementDate(delta) {
|
|
10017
10880
|
date.add(moment.duration(delta));
|
|
10018
10881
|
renderView();
|
|
@@ -10030,8 +10893,8 @@ function Calendar_constructor(element, overrides) {
|
|
|
10030
10893
|
date = newDate.clone();
|
|
10031
10894
|
renderView(spec ? spec.type : null);
|
|
10032
10895
|
}
|
|
10033
|
-
|
|
10034
|
-
|
|
10896
|
+
|
|
10897
|
+
|
|
10035
10898
|
// for external API
|
|
10036
10899
|
function getDate() {
|
|
10037
10900
|
return t.applyTimezone(date); // infuse the calendar's timezone
|
|
@@ -10041,45 +10904,51 @@ function Calendar_constructor(element, overrides) {
|
|
|
10041
10904
|
|
|
10042
10905
|
/* Height "Freezing"
|
|
10043
10906
|
-----------------------------------------------------------------------------*/
|
|
10044
|
-
|
|
10907
|
+
|
|
10045
10908
|
|
|
10046
10909
|
t.freezeContentHeight = freezeContentHeight;
|
|
10047
|
-
t.
|
|
10910
|
+
t.thawContentHeight = thawContentHeight;
|
|
10911
|
+
|
|
10912
|
+
var freezeContentHeightDepth = 0;
|
|
10048
10913
|
|
|
10049
10914
|
|
|
10050
10915
|
function freezeContentHeight() {
|
|
10051
|
-
|
|
10052
|
-
|
|
10053
|
-
|
|
10054
|
-
|
|
10055
|
-
|
|
10916
|
+
if (!(freezeContentHeightDepth++)) {
|
|
10917
|
+
content.css({
|
|
10918
|
+
width: '100%',
|
|
10919
|
+
height: content.height(),
|
|
10920
|
+
overflow: 'hidden'
|
|
10921
|
+
});
|
|
10922
|
+
}
|
|
10056
10923
|
}
|
|
10057
10924
|
|
|
10058
10925
|
|
|
10059
|
-
function
|
|
10060
|
-
|
|
10061
|
-
|
|
10062
|
-
|
|
10063
|
-
|
|
10064
|
-
|
|
10926
|
+
function thawContentHeight() {
|
|
10927
|
+
if (!(--freezeContentHeightDepth)) {
|
|
10928
|
+
content.css({
|
|
10929
|
+
width: '',
|
|
10930
|
+
height: '',
|
|
10931
|
+
overflow: ''
|
|
10932
|
+
});
|
|
10933
|
+
}
|
|
10065
10934
|
}
|
|
10066
|
-
|
|
10067
|
-
|
|
10068
|
-
|
|
10935
|
+
|
|
10936
|
+
|
|
10937
|
+
|
|
10069
10938
|
/* Misc
|
|
10070
10939
|
-----------------------------------------------------------------------------*/
|
|
10071
|
-
|
|
10940
|
+
|
|
10072
10941
|
|
|
10073
10942
|
function getCalendar() {
|
|
10074
10943
|
return t;
|
|
10075
10944
|
}
|
|
10076
10945
|
|
|
10077
|
-
|
|
10946
|
+
|
|
10078
10947
|
function getView() {
|
|
10079
10948
|
return currentView;
|
|
10080
10949
|
}
|
|
10081
|
-
|
|
10082
|
-
|
|
10950
|
+
|
|
10951
|
+
|
|
10083
10952
|
function option(name, value) {
|
|
10084
10953
|
var newOptionHash;
|
|
10085
10954
|
|
|
@@ -10135,19 +11004,20 @@ function Calendar_constructor(element, overrides) {
|
|
|
10135
11004
|
}
|
|
10136
11005
|
else if (optionName === 'timezone') {
|
|
10137
11006
|
t.rezoneArrayEventSources();
|
|
10138
|
-
refetchEvents();
|
|
11007
|
+
t.refetchEvents();
|
|
10139
11008
|
return;
|
|
10140
11009
|
}
|
|
10141
11010
|
}
|
|
10142
11011
|
|
|
10143
|
-
// catch-all. rerender the header and rebuild/rerender the current view
|
|
11012
|
+
// catch-all. rerender the header and footer and rebuild/rerender the current view
|
|
10144
11013
|
renderHeader();
|
|
11014
|
+
renderFooter();
|
|
10145
11015
|
viewsByType = {}; // even non-current views will be affected by this option change. do before rerender
|
|
10146
11016
|
reinitView();
|
|
10147
11017
|
}
|
|
10148
|
-
|
|
10149
|
-
|
|
10150
|
-
function
|
|
11018
|
+
|
|
11019
|
+
|
|
11020
|
+
function publiclyTrigger(name, thisObj) {
|
|
10151
11021
|
var args = Array.prototype.slice.call(arguments, 2);
|
|
10152
11022
|
|
|
10153
11023
|
thisObj = thisObj || _element;
|
|
@@ -10310,6 +11180,7 @@ Calendar.defaults = {
|
|
|
10310
11180
|
dropAccept: '*',
|
|
10311
11181
|
|
|
10312
11182
|
eventOrder: 'title',
|
|
11183
|
+
//eventRenderWait: null,
|
|
10313
11184
|
|
|
10314
11185
|
eventLimit: false,
|
|
10315
11186
|
eventLimitText: 'more',
|
|
@@ -10430,392 +11301,123 @@ var dpComputableOptions = {
|
|
|
10430
11301
|
// the translations sometimes wrongly contain HTML entities
|
|
10431
11302
|
prev: stripHtmlEntities(dpOptions.prevText),
|
|
10432
11303
|
next: stripHtmlEntities(dpOptions.nextText),
|
|
10433
|
-
today: stripHtmlEntities(dpOptions.currentText)
|
|
10434
|
-
};
|
|
10435
|
-
},
|
|
10436
|
-
|
|
10437
|
-
// Produces format strings like "MMMM YYYY" -> "September 2014"
|
|
10438
|
-
monthYearFormat: function(dpOptions) {
|
|
10439
|
-
return dpOptions.showMonthAfterYear ?
|
|
10440
|
-
'YYYY[' + dpOptions.yearSuffix + '] MMMM' :
|
|
10441
|
-
'MMMM YYYY[' + dpOptions.yearSuffix + ']';
|
|
10442
|
-
}
|
|
10443
|
-
|
|
10444
|
-
};
|
|
10445
|
-
|
|
10446
|
-
var momComputableOptions = {
|
|
10447
|
-
|
|
10448
|
-
// Produces format strings like "ddd M/D" -> "Fri 9/15"
|
|
10449
|
-
dayOfMonthFormat: function(momOptions, fcOptions) {
|
|
10450
|
-
var format = momOptions.longDateFormat('l'); // for the format like "M/D/YYYY"
|
|
10451
|
-
|
|
10452
|
-
// strip the year off the edge, as well as other misc non-whitespace chars
|
|
10453
|
-
format = format.replace(/^Y+[^\w\s]*|[^\w\s]*Y+$/g, '');
|
|
10454
|
-
|
|
10455
|
-
if (fcOptions.isRTL) {
|
|
10456
|
-
format += ' ddd'; // for RTL, add day-of-week to end
|
|
10457
|
-
}
|
|
10458
|
-
else {
|
|
10459
|
-
format = 'ddd ' + format; // for LTR, add day-of-week to beginning
|
|
10460
|
-
}
|
|
10461
|
-
return format;
|
|
10462
|
-
},
|
|
10463
|
-
|
|
10464
|
-
// Produces format strings like "h:mma" -> "6:00pm"
|
|
10465
|
-
mediumTimeFormat: function(momOptions) { // can't be called `timeFormat` because collides with option
|
|
10466
|
-
return momOptions.longDateFormat('LT')
|
|
10467
|
-
.replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand
|
|
10468
|
-
},
|
|
10469
|
-
|
|
10470
|
-
// Produces format strings like "h(:mm)a" -> "6pm" / "6:30pm"
|
|
10471
|
-
smallTimeFormat: function(momOptions) {
|
|
10472
|
-
return momOptions.longDateFormat('LT')
|
|
10473
|
-
.replace(':mm', '(:mm)')
|
|
10474
|
-
.replace(/(\Wmm)$/, '($1)') // like above, but for foreign locales
|
|
10475
|
-
.replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand
|
|
10476
|
-
},
|
|
10477
|
-
|
|
10478
|
-
// Produces format strings like "h(:mm)t" -> "6p" / "6:30p"
|
|
10479
|
-
extraSmallTimeFormat: function(momOptions) {
|
|
10480
|
-
return momOptions.longDateFormat('LT')
|
|
10481
|
-
.replace(':mm', '(:mm)')
|
|
10482
|
-
.replace(/(\Wmm)$/, '($1)') // like above, but for foreign locales
|
|
10483
|
-
.replace(/\s*a$/i, 't'); // convert to AM/PM/am/pm to lowercase one-letter. remove any spaces beforehand
|
|
10484
|
-
},
|
|
10485
|
-
|
|
10486
|
-
// Produces format strings like "ha" / "H" -> "6pm" / "18"
|
|
10487
|
-
hourFormat: function(momOptions) {
|
|
10488
|
-
return momOptions.longDateFormat('LT')
|
|
10489
|
-
.replace(':mm', '')
|
|
10490
|
-
.replace(/(\Wmm)$/, '') // like above, but for foreign locales
|
|
10491
|
-
.replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand
|
|
10492
|
-
},
|
|
10493
|
-
|
|
10494
|
-
// Produces format strings like "h:mm" -> "6:30" (with no AM/PM)
|
|
10495
|
-
noMeridiemTimeFormat: function(momOptions) {
|
|
10496
|
-
return momOptions.longDateFormat('LT')
|
|
10497
|
-
.replace(/\s*a$/i, ''); // remove trailing AM/PM
|
|
10498
|
-
}
|
|
10499
|
-
|
|
10500
|
-
};
|
|
10501
|
-
|
|
10502
|
-
|
|
10503
|
-
// options that should be computed off live calendar options (considers override options)
|
|
10504
|
-
// TODO: best place for this? related to locale?
|
|
10505
|
-
// TODO: flipping text based on isRTL is a bad idea because the CSS `direction` might want to handle it
|
|
10506
|
-
var instanceComputableOptions = {
|
|
10507
|
-
|
|
10508
|
-
// Produces format strings for results like "Mo 16"
|
|
10509
|
-
smallDayDateFormat: function(options) {
|
|
10510
|
-
return options.isRTL ?
|
|
10511
|
-
'D dd' :
|
|
10512
|
-
'dd D';
|
|
10513
|
-
},
|
|
10514
|
-
|
|
10515
|
-
// Produces format strings for results like "Wk 5"
|
|
10516
|
-
weekFormat: function(options) {
|
|
10517
|
-
return options.isRTL ?
|
|
10518
|
-
'w[ ' + options.weekNumberTitle + ']' :
|
|
10519
|
-
'[' + options.weekNumberTitle + ' ]w';
|
|
10520
|
-
},
|
|
10521
|
-
|
|
10522
|
-
// Produces format strings for results like "Wk5"
|
|
10523
|
-
smallWeekFormat: function(options) {
|
|
10524
|
-
return options.isRTL ?
|
|
10525
|
-
'w[' + options.weekNumberTitle + ']' :
|
|
10526
|
-
'[' + options.weekNumberTitle + ']w';
|
|
10527
|
-
}
|
|
10528
|
-
|
|
10529
|
-
};
|
|
10530
|
-
|
|
10531
|
-
function populateInstanceComputableOptions(options) {
|
|
10532
|
-
$.each(instanceComputableOptions, function(name, func) {
|
|
10533
|
-
if (options[name] == null) {
|
|
10534
|
-
options[name] = func(options);
|
|
10535
|
-
}
|
|
10536
|
-
});
|
|
10537
|
-
}
|
|
10538
|
-
|
|
10539
|
-
|
|
10540
|
-
// Returns moment's internal locale data. If doesn't exist, returns English.
|
|
10541
|
-
function getMomentLocaleData(localeCode) {
|
|
10542
|
-
return moment.localeData(localeCode) || moment.localeData('en');
|
|
10543
|
-
}
|
|
10544
|
-
|
|
10545
|
-
|
|
10546
|
-
// Initialize English by forcing computation of moment-derived options.
|
|
10547
|
-
// Also, sets it as the default.
|
|
10548
|
-
FC.locale('en', Calendar.englishDefaults);
|
|
10549
|
-
|
|
10550
|
-
;;
|
|
10551
|
-
|
|
10552
|
-
/* Top toolbar area with buttons and title
|
|
10553
|
-
----------------------------------------------------------------------------------------------------------------------*/
|
|
10554
|
-
// TODO: rename all header-related things to "toolbar"
|
|
10555
|
-
|
|
10556
|
-
function Header(calendar) {
|
|
10557
|
-
var t = this;
|
|
10558
|
-
|
|
10559
|
-
// exports
|
|
10560
|
-
t.render = render;
|
|
10561
|
-
t.removeElement = removeElement;
|
|
10562
|
-
t.updateTitle = updateTitle;
|
|
10563
|
-
t.activateButton = activateButton;
|
|
10564
|
-
t.deactivateButton = deactivateButton;
|
|
10565
|
-
t.disableButton = disableButton;
|
|
10566
|
-
t.enableButton = enableButton;
|
|
10567
|
-
t.getViewsWithButtons = getViewsWithButtons;
|
|
10568
|
-
t.el = null; // mirrors local `el`
|
|
10569
|
-
|
|
10570
|
-
// locals
|
|
10571
|
-
var el;
|
|
10572
|
-
var viewsWithButtons = [];
|
|
10573
|
-
var tm;
|
|
10574
|
-
|
|
10575
|
-
|
|
10576
|
-
// can be called repeatedly and will rerender
|
|
10577
|
-
function render() {
|
|
10578
|
-
var options = calendar.options;
|
|
10579
|
-
var sections = options.header;
|
|
10580
|
-
|
|
10581
|
-
tm = options.theme ? 'ui' : 'fc';
|
|
10582
|
-
|
|
10583
|
-
if (sections) {
|
|
10584
|
-
if (!el) {
|
|
10585
|
-
el = this.el = $("<div class='fc-toolbar'/>");
|
|
10586
|
-
}
|
|
10587
|
-
else {
|
|
10588
|
-
el.empty();
|
|
10589
|
-
}
|
|
10590
|
-
el.append(renderSection('left'))
|
|
10591
|
-
.append(renderSection('right'))
|
|
10592
|
-
.append(renderSection('center'))
|
|
10593
|
-
.append('<div class="fc-clear"/>');
|
|
10594
|
-
}
|
|
10595
|
-
else {
|
|
10596
|
-
removeElement();
|
|
10597
|
-
}
|
|
10598
|
-
}
|
|
10599
|
-
|
|
10600
|
-
|
|
10601
|
-
function removeElement() {
|
|
10602
|
-
if (el) {
|
|
10603
|
-
el.remove();
|
|
10604
|
-
el = t.el = null;
|
|
10605
|
-
}
|
|
10606
|
-
}
|
|
10607
|
-
|
|
10608
|
-
|
|
10609
|
-
function renderSection(position) {
|
|
10610
|
-
var sectionEl = $('<div class="fc-' + position + '"/>');
|
|
10611
|
-
var options = calendar.options;
|
|
10612
|
-
var buttonStr = options.header[position];
|
|
10613
|
-
|
|
10614
|
-
if (buttonStr) {
|
|
10615
|
-
$.each(buttonStr.split(' '), function(i) {
|
|
10616
|
-
var groupChildren = $();
|
|
10617
|
-
var isOnlyButtons = true;
|
|
10618
|
-
var groupEl;
|
|
10619
|
-
|
|
10620
|
-
$.each(this.split(','), function(j, buttonName) {
|
|
10621
|
-
var customButtonProps;
|
|
10622
|
-
var viewSpec;
|
|
10623
|
-
var buttonClick;
|
|
10624
|
-
var overrideText; // text explicitly set by calendar's constructor options. overcomes icons
|
|
10625
|
-
var defaultText;
|
|
10626
|
-
var themeIcon;
|
|
10627
|
-
var normalIcon;
|
|
10628
|
-
var innerHtml;
|
|
10629
|
-
var classes;
|
|
10630
|
-
var button; // the element
|
|
10631
|
-
|
|
10632
|
-
if (buttonName == 'title') {
|
|
10633
|
-
groupChildren = groupChildren.add($('<h2> </h2>')); // we always want it to take up height
|
|
10634
|
-
isOnlyButtons = false;
|
|
10635
|
-
}
|
|
10636
|
-
else {
|
|
10637
|
-
if ((customButtonProps = (options.customButtons || {})[buttonName])) {
|
|
10638
|
-
buttonClick = function(ev) {
|
|
10639
|
-
if (customButtonProps.click) {
|
|
10640
|
-
customButtonProps.click.call(button[0], ev);
|
|
10641
|
-
}
|
|
10642
|
-
};
|
|
10643
|
-
overrideText = ''; // icons will override text
|
|
10644
|
-
defaultText = customButtonProps.text;
|
|
10645
|
-
}
|
|
10646
|
-
else if ((viewSpec = calendar.getViewSpec(buttonName))) {
|
|
10647
|
-
buttonClick = function() {
|
|
10648
|
-
calendar.changeView(buttonName);
|
|
10649
|
-
};
|
|
10650
|
-
viewsWithButtons.push(buttonName);
|
|
10651
|
-
overrideText = viewSpec.buttonTextOverride;
|
|
10652
|
-
defaultText = viewSpec.buttonTextDefault;
|
|
10653
|
-
}
|
|
10654
|
-
else if (calendar[buttonName]) { // a calendar method
|
|
10655
|
-
buttonClick = function() {
|
|
10656
|
-
calendar[buttonName]();
|
|
10657
|
-
};
|
|
10658
|
-
overrideText = (calendar.overrides.buttonText || {})[buttonName];
|
|
10659
|
-
defaultText = options.buttonText[buttonName]; // everything else is considered default
|
|
10660
|
-
}
|
|
10661
|
-
|
|
10662
|
-
if (buttonClick) {
|
|
10663
|
-
|
|
10664
|
-
themeIcon =
|
|
10665
|
-
customButtonProps ?
|
|
10666
|
-
customButtonProps.themeIcon :
|
|
10667
|
-
options.themeButtonIcons[buttonName];
|
|
10668
|
-
|
|
10669
|
-
normalIcon =
|
|
10670
|
-
customButtonProps ?
|
|
10671
|
-
customButtonProps.icon :
|
|
10672
|
-
options.buttonIcons[buttonName];
|
|
10673
|
-
|
|
10674
|
-
if (overrideText) {
|
|
10675
|
-
innerHtml = htmlEscape(overrideText);
|
|
10676
|
-
}
|
|
10677
|
-
else if (themeIcon && options.theme) {
|
|
10678
|
-
innerHtml = "<span class='ui-icon ui-icon-" + themeIcon + "'></span>";
|
|
10679
|
-
}
|
|
10680
|
-
else if (normalIcon && !options.theme) {
|
|
10681
|
-
innerHtml = "<span class='fc-icon fc-icon-" + normalIcon + "'></span>";
|
|
10682
|
-
}
|
|
10683
|
-
else {
|
|
10684
|
-
innerHtml = htmlEscape(defaultText);
|
|
10685
|
-
}
|
|
10686
|
-
|
|
10687
|
-
classes = [
|
|
10688
|
-
'fc-' + buttonName + '-button',
|
|
10689
|
-
tm + '-button',
|
|
10690
|
-
tm + '-state-default'
|
|
10691
|
-
];
|
|
10692
|
-
|
|
10693
|
-
button = $( // type="button" so that it doesn't submit a form
|
|
10694
|
-
'<button type="button" class="' + classes.join(' ') + '">' +
|
|
10695
|
-
innerHtml +
|
|
10696
|
-
'</button>'
|
|
10697
|
-
)
|
|
10698
|
-
.click(function(ev) {
|
|
10699
|
-
// don't process clicks for disabled buttons
|
|
10700
|
-
if (!button.hasClass(tm + '-state-disabled')) {
|
|
10701
|
-
|
|
10702
|
-
buttonClick(ev);
|
|
10703
|
-
|
|
10704
|
-
// after the click action, if the button becomes the "active" tab, or disabled,
|
|
10705
|
-
// it should never have a hover class, so remove it now.
|
|
10706
|
-
if (
|
|
10707
|
-
button.hasClass(tm + '-state-active') ||
|
|
10708
|
-
button.hasClass(tm + '-state-disabled')
|
|
10709
|
-
) {
|
|
10710
|
-
button.removeClass(tm + '-state-hover');
|
|
10711
|
-
}
|
|
10712
|
-
}
|
|
10713
|
-
})
|
|
10714
|
-
.mousedown(function() {
|
|
10715
|
-
// the *down* effect (mouse pressed in).
|
|
10716
|
-
// only on buttons that are not the "active" tab, or disabled
|
|
10717
|
-
button
|
|
10718
|
-
.not('.' + tm + '-state-active')
|
|
10719
|
-
.not('.' + tm + '-state-disabled')
|
|
10720
|
-
.addClass(tm + '-state-down');
|
|
10721
|
-
})
|
|
10722
|
-
.mouseup(function() {
|
|
10723
|
-
// undo the *down* effect
|
|
10724
|
-
button.removeClass(tm + '-state-down');
|
|
10725
|
-
})
|
|
10726
|
-
.hover(
|
|
10727
|
-
function() {
|
|
10728
|
-
// the *hover* effect.
|
|
10729
|
-
// only on buttons that are not the "active" tab, or disabled
|
|
10730
|
-
button
|
|
10731
|
-
.not('.' + tm + '-state-active')
|
|
10732
|
-
.not('.' + tm + '-state-disabled')
|
|
10733
|
-
.addClass(tm + '-state-hover');
|
|
10734
|
-
},
|
|
10735
|
-
function() {
|
|
10736
|
-
// undo the *hover* effect
|
|
10737
|
-
button
|
|
10738
|
-
.removeClass(tm + '-state-hover')
|
|
10739
|
-
.removeClass(tm + '-state-down'); // if mouseleave happens before mouseup
|
|
10740
|
-
}
|
|
10741
|
-
);
|
|
10742
|
-
|
|
10743
|
-
groupChildren = groupChildren.add(button);
|
|
10744
|
-
}
|
|
10745
|
-
}
|
|
10746
|
-
});
|
|
10747
|
-
|
|
10748
|
-
if (isOnlyButtons) {
|
|
10749
|
-
groupChildren
|
|
10750
|
-
.first().addClass(tm + '-corner-left').end()
|
|
10751
|
-
.last().addClass(tm + '-corner-right').end();
|
|
10752
|
-
}
|
|
10753
|
-
|
|
10754
|
-
if (groupChildren.length > 1) {
|
|
10755
|
-
groupEl = $('<div/>');
|
|
10756
|
-
if (isOnlyButtons) {
|
|
10757
|
-
groupEl.addClass('fc-button-group');
|
|
10758
|
-
}
|
|
10759
|
-
groupEl.append(groupChildren);
|
|
10760
|
-
sectionEl.append(groupEl);
|
|
10761
|
-
}
|
|
10762
|
-
else {
|
|
10763
|
-
sectionEl.append(groupChildren); // 1 or 0 children
|
|
10764
|
-
}
|
|
10765
|
-
});
|
|
10766
|
-
}
|
|
10767
|
-
|
|
10768
|
-
return sectionEl;
|
|
10769
|
-
}
|
|
10770
|
-
|
|
10771
|
-
|
|
10772
|
-
function updateTitle(text) {
|
|
10773
|
-
if (el) {
|
|
10774
|
-
el.find('h2').text(text);
|
|
10775
|
-
}
|
|
10776
|
-
}
|
|
10777
|
-
|
|
10778
|
-
|
|
10779
|
-
function activateButton(buttonName) {
|
|
10780
|
-
if (el) {
|
|
10781
|
-
el.find('.fc-' + buttonName + '-button')
|
|
10782
|
-
.addClass(tm + '-state-active');
|
|
10783
|
-
}
|
|
10784
|
-
}
|
|
10785
|
-
|
|
10786
|
-
|
|
10787
|
-
function deactivateButton(buttonName) {
|
|
10788
|
-
if (el) {
|
|
10789
|
-
el.find('.fc-' + buttonName + '-button')
|
|
10790
|
-
.removeClass(tm + '-state-active');
|
|
10791
|
-
}
|
|
11304
|
+
today: stripHtmlEntities(dpOptions.currentText)
|
|
11305
|
+
};
|
|
11306
|
+
},
|
|
11307
|
+
|
|
11308
|
+
// Produces format strings like "MMMM YYYY" -> "September 2014"
|
|
11309
|
+
monthYearFormat: function(dpOptions) {
|
|
11310
|
+
return dpOptions.showMonthAfterYear ?
|
|
11311
|
+
'YYYY[' + dpOptions.yearSuffix + '] MMMM' :
|
|
11312
|
+
'MMMM YYYY[' + dpOptions.yearSuffix + ']';
|
|
10792
11313
|
}
|
|
10793
|
-
|
|
10794
|
-
|
|
10795
|
-
|
|
10796
|
-
|
|
10797
|
-
|
|
10798
|
-
|
|
10799
|
-
|
|
11314
|
+
|
|
11315
|
+
};
|
|
11316
|
+
|
|
11317
|
+
var momComputableOptions = {
|
|
11318
|
+
|
|
11319
|
+
// Produces format strings like "ddd M/D" -> "Fri 9/15"
|
|
11320
|
+
dayOfMonthFormat: function(momOptions, fcOptions) {
|
|
11321
|
+
var format = momOptions.longDateFormat('l'); // for the format like "M/D/YYYY"
|
|
11322
|
+
|
|
11323
|
+
// strip the year off the edge, as well as other misc non-whitespace chars
|
|
11324
|
+
format = format.replace(/^Y+[^\w\s]*|[^\w\s]*Y+$/g, '');
|
|
11325
|
+
|
|
11326
|
+
if (fcOptions.isRTL) {
|
|
11327
|
+
format += ' ddd'; // for RTL, add day-of-week to end
|
|
10800
11328
|
}
|
|
10801
|
-
|
|
10802
|
-
|
|
10803
|
-
|
|
10804
|
-
function enableButton(buttonName) {
|
|
10805
|
-
if (el) {
|
|
10806
|
-
el.find('.fc-' + buttonName + '-button')
|
|
10807
|
-
.prop('disabled', false)
|
|
10808
|
-
.removeClass(tm + '-state-disabled');
|
|
11329
|
+
else {
|
|
11330
|
+
format = 'ddd ' + format; // for LTR, add day-of-week to beginning
|
|
10809
11331
|
}
|
|
11332
|
+
return format;
|
|
11333
|
+
},
|
|
11334
|
+
|
|
11335
|
+
// Produces format strings like "h:mma" -> "6:00pm"
|
|
11336
|
+
mediumTimeFormat: function(momOptions) { // can't be called `timeFormat` because collides with option
|
|
11337
|
+
return momOptions.longDateFormat('LT')
|
|
11338
|
+
.replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand
|
|
11339
|
+
},
|
|
11340
|
+
|
|
11341
|
+
// Produces format strings like "h(:mm)a" -> "6pm" / "6:30pm"
|
|
11342
|
+
smallTimeFormat: function(momOptions) {
|
|
11343
|
+
return momOptions.longDateFormat('LT')
|
|
11344
|
+
.replace(':mm', '(:mm)')
|
|
11345
|
+
.replace(/(\Wmm)$/, '($1)') // like above, but for foreign locales
|
|
11346
|
+
.replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand
|
|
11347
|
+
},
|
|
11348
|
+
|
|
11349
|
+
// Produces format strings like "h(:mm)t" -> "6p" / "6:30p"
|
|
11350
|
+
extraSmallTimeFormat: function(momOptions) {
|
|
11351
|
+
return momOptions.longDateFormat('LT')
|
|
11352
|
+
.replace(':mm', '(:mm)')
|
|
11353
|
+
.replace(/(\Wmm)$/, '($1)') // like above, but for foreign locales
|
|
11354
|
+
.replace(/\s*a$/i, 't'); // convert to AM/PM/am/pm to lowercase one-letter. remove any spaces beforehand
|
|
11355
|
+
},
|
|
11356
|
+
|
|
11357
|
+
// Produces format strings like "ha" / "H" -> "6pm" / "18"
|
|
11358
|
+
hourFormat: function(momOptions) {
|
|
11359
|
+
return momOptions.longDateFormat('LT')
|
|
11360
|
+
.replace(':mm', '')
|
|
11361
|
+
.replace(/(\Wmm)$/, '') // like above, but for foreign locales
|
|
11362
|
+
.replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand
|
|
11363
|
+
},
|
|
11364
|
+
|
|
11365
|
+
// Produces format strings like "h:mm" -> "6:30" (with no AM/PM)
|
|
11366
|
+
noMeridiemTimeFormat: function(momOptions) {
|
|
11367
|
+
return momOptions.longDateFormat('LT')
|
|
11368
|
+
.replace(/\s*a$/i, ''); // remove trailing AM/PM
|
|
10810
11369
|
}
|
|
10811
11370
|
|
|
11371
|
+
};
|
|
10812
11372
|
|
|
10813
|
-
|
|
10814
|
-
|
|
11373
|
+
|
|
11374
|
+
// options that should be computed off live calendar options (considers override options)
|
|
11375
|
+
// TODO: best place for this? related to locale?
|
|
11376
|
+
// TODO: flipping text based on isRTL is a bad idea because the CSS `direction` might want to handle it
|
|
11377
|
+
var instanceComputableOptions = {
|
|
11378
|
+
|
|
11379
|
+
// Produces format strings for results like "Mo 16"
|
|
11380
|
+
smallDayDateFormat: function(options) {
|
|
11381
|
+
return options.isRTL ?
|
|
11382
|
+
'D dd' :
|
|
11383
|
+
'dd D';
|
|
11384
|
+
},
|
|
11385
|
+
|
|
11386
|
+
// Produces format strings for results like "Wk 5"
|
|
11387
|
+
weekFormat: function(options) {
|
|
11388
|
+
return options.isRTL ?
|
|
11389
|
+
'w[ ' + options.weekNumberTitle + ']' :
|
|
11390
|
+
'[' + options.weekNumberTitle + ' ]w';
|
|
11391
|
+
},
|
|
11392
|
+
|
|
11393
|
+
// Produces format strings for results like "Wk5"
|
|
11394
|
+
smallWeekFormat: function(options) {
|
|
11395
|
+
return options.isRTL ?
|
|
11396
|
+
'w[' + options.weekNumberTitle + ']' :
|
|
11397
|
+
'[' + options.weekNumberTitle + ']w';
|
|
10815
11398
|
}
|
|
10816
11399
|
|
|
11400
|
+
};
|
|
11401
|
+
|
|
11402
|
+
function populateInstanceComputableOptions(options) {
|
|
11403
|
+
$.each(instanceComputableOptions, function(name, func) {
|
|
11404
|
+
if (options[name] == null) {
|
|
11405
|
+
options[name] = func(options);
|
|
11406
|
+
}
|
|
11407
|
+
});
|
|
11408
|
+
}
|
|
11409
|
+
|
|
11410
|
+
|
|
11411
|
+
// Returns moment's internal locale data. If doesn't exist, returns English.
|
|
11412
|
+
function getMomentLocaleData(localeCode) {
|
|
11413
|
+
return moment.localeData(localeCode) || moment.localeData('en');
|
|
10817
11414
|
}
|
|
10818
11415
|
|
|
11416
|
+
|
|
11417
|
+
// Initialize English by forcing computation of moment-derived options.
|
|
11418
|
+
// Also, sets it as the default.
|
|
11419
|
+
FC.locale('en', Calendar.englishDefaults);
|
|
11420
|
+
|
|
10819
11421
|
;;
|
|
10820
11422
|
|
|
10821
11423
|
FC.sourceNormalizers = [];
|
|
@@ -10831,38 +11433,39 @@ var eventGUID = 1;
|
|
|
10831
11433
|
|
|
10832
11434
|
function EventManager() { // assumed to be a calendar
|
|
10833
11435
|
var t = this;
|
|
10834
|
-
|
|
10835
|
-
|
|
11436
|
+
|
|
11437
|
+
|
|
10836
11438
|
// exports
|
|
11439
|
+
t.requestEvents = requestEvents;
|
|
11440
|
+
t.reportEventChange = reportEventChange;
|
|
10837
11441
|
t.isFetchNeeded = isFetchNeeded;
|
|
10838
11442
|
t.fetchEvents = fetchEvents;
|
|
10839
11443
|
t.fetchEventSources = fetchEventSources;
|
|
11444
|
+
t.refetchEvents = refetchEvents;
|
|
11445
|
+
t.refetchEventSources = refetchEventSources;
|
|
10840
11446
|
t.getEventSources = getEventSources;
|
|
10841
11447
|
t.getEventSourceById = getEventSourceById;
|
|
10842
|
-
t.getEventSourcesByMatchArray = getEventSourcesByMatchArray;
|
|
10843
|
-
t.getEventSourcesByMatch = getEventSourcesByMatch;
|
|
10844
11448
|
t.addEventSource = addEventSource;
|
|
10845
11449
|
t.removeEventSource = removeEventSource;
|
|
10846
11450
|
t.removeEventSources = removeEventSources;
|
|
10847
11451
|
t.updateEvent = updateEvent;
|
|
11452
|
+
t.updateEvents = updateEvents;
|
|
10848
11453
|
t.renderEvent = renderEvent;
|
|
11454
|
+
t.renderEvents = renderEvents;
|
|
10849
11455
|
t.removeEvents = removeEvents;
|
|
10850
11456
|
t.clientEvents = clientEvents;
|
|
10851
11457
|
t.mutateEvent = mutateEvent;
|
|
10852
11458
|
t.normalizeEventDates = normalizeEventDates;
|
|
10853
11459
|
t.normalizeEventTimes = normalizeEventTimes;
|
|
10854
|
-
|
|
10855
|
-
|
|
10856
|
-
// imports
|
|
10857
|
-
var reportEvents = t.reportEvents;
|
|
10858
|
-
|
|
10859
|
-
|
|
11460
|
+
|
|
11461
|
+
|
|
10860
11462
|
// locals
|
|
10861
11463
|
var stickySource = { events: [] };
|
|
10862
11464
|
var sources = [ stickySource ];
|
|
10863
11465
|
var rangeStart, rangeEnd;
|
|
10864
11466
|
var pendingSourceCnt = 0; // outstanding fetch requests, max one per source
|
|
10865
11467
|
var cache = []; // holds events that have already been expanded
|
|
11468
|
+
var prunedCache; // like cache, but only events that intersect with rangeStart/rangeEnd
|
|
10866
11469
|
|
|
10867
11470
|
|
|
10868
11471
|
$.each(
|
|
@@ -10874,9 +11477,55 @@ function EventManager() { // assumed to be a calendar
|
|
|
10874
11477
|
}
|
|
10875
11478
|
}
|
|
10876
11479
|
);
|
|
10877
|
-
|
|
10878
|
-
|
|
10879
|
-
|
|
11480
|
+
|
|
11481
|
+
|
|
11482
|
+
|
|
11483
|
+
function requestEvents(start, end) {
|
|
11484
|
+
if (!t.options.lazyFetching || isFetchNeeded(start, end)) {
|
|
11485
|
+
return fetchEvents(start, end);
|
|
11486
|
+
}
|
|
11487
|
+
else {
|
|
11488
|
+
return Promise.resolve(prunedCache);
|
|
11489
|
+
}
|
|
11490
|
+
}
|
|
11491
|
+
|
|
11492
|
+
|
|
11493
|
+
function reportEventChange() {
|
|
11494
|
+
prunedCache = filterEventsWithinRange(cache);
|
|
11495
|
+
t.trigger('eventsReset', prunedCache);
|
|
11496
|
+
}
|
|
11497
|
+
|
|
11498
|
+
|
|
11499
|
+
function filterEventsWithinRange(events) {
|
|
11500
|
+
var filteredEvents = [];
|
|
11501
|
+
var i, event;
|
|
11502
|
+
|
|
11503
|
+
for (i = 0; i < events.length; i++) {
|
|
11504
|
+
event = events[i];
|
|
11505
|
+
|
|
11506
|
+
if (
|
|
11507
|
+
event.start.clone().stripZone() < rangeEnd &&
|
|
11508
|
+
t.getEventEnd(event).stripZone() > rangeStart
|
|
11509
|
+
) {
|
|
11510
|
+
filteredEvents.push(event);
|
|
11511
|
+
}
|
|
11512
|
+
}
|
|
11513
|
+
|
|
11514
|
+
return filteredEvents;
|
|
11515
|
+
}
|
|
11516
|
+
|
|
11517
|
+
|
|
11518
|
+
t.getEventCache = function() {
|
|
11519
|
+
return cache;
|
|
11520
|
+
};
|
|
11521
|
+
|
|
11522
|
+
|
|
11523
|
+
t.getPrunedEventCache = function() {
|
|
11524
|
+
return prunedCache;
|
|
11525
|
+
};
|
|
11526
|
+
|
|
11527
|
+
|
|
11528
|
+
|
|
10880
11529
|
/* Fetching
|
|
10881
11530
|
-----------------------------------------------------------------------------*/
|
|
10882
11531
|
|
|
@@ -10886,12 +11535,24 @@ function EventManager() { // assumed to be a calendar
|
|
|
10886
11535
|
return !rangeStart || // nothing has been fetched yet?
|
|
10887
11536
|
start < rangeStart || end > rangeEnd; // is part of the new range outside of the old range?
|
|
10888
11537
|
}
|
|
10889
|
-
|
|
10890
|
-
|
|
11538
|
+
|
|
11539
|
+
|
|
10891
11540
|
function fetchEvents(start, end) {
|
|
10892
11541
|
rangeStart = start;
|
|
10893
11542
|
rangeEnd = end;
|
|
10894
|
-
|
|
11543
|
+
return refetchEvents();
|
|
11544
|
+
}
|
|
11545
|
+
|
|
11546
|
+
|
|
11547
|
+
// poorly named. fetches all sources with current `rangeStart` and `rangeEnd`.
|
|
11548
|
+
function refetchEvents() {
|
|
11549
|
+
return fetchEventSources(sources, 'reset');
|
|
11550
|
+
}
|
|
11551
|
+
|
|
11552
|
+
|
|
11553
|
+
// poorly named. fetches a subset of event sources.
|
|
11554
|
+
function refetchEventSources(matchInputs) {
|
|
11555
|
+
return fetchEventSources(getEventSourcesByMatchArray(matchInputs));
|
|
10895
11556
|
}
|
|
10896
11557
|
|
|
10897
11558
|
|
|
@@ -10921,9 +11582,17 @@ function EventManager() { // assumed to be a calendar
|
|
|
10921
11582
|
|
|
10922
11583
|
for (i = 0; i < specificSources.length; i++) {
|
|
10923
11584
|
source = specificSources[i];
|
|
10924
|
-
|
|
10925
11585
|
tryFetchEventSource(source, source._fetchId);
|
|
10926
11586
|
}
|
|
11587
|
+
|
|
11588
|
+
if (pendingSourceCnt) {
|
|
11589
|
+
return new Promise(function(resolve) {
|
|
11590
|
+
t.one('eventsReceived', resolve); // will send prunedCache
|
|
11591
|
+
});
|
|
11592
|
+
}
|
|
11593
|
+
else { // executed all synchronously, or no sources at all
|
|
11594
|
+
return Promise.resolve(prunedCache);
|
|
11595
|
+
}
|
|
10927
11596
|
}
|
|
10928
11597
|
|
|
10929
11598
|
|
|
@@ -10956,7 +11625,7 @@ function EventManager() { // assumed to be a calendar
|
|
|
10956
11625
|
}
|
|
10957
11626
|
|
|
10958
11627
|
if (abstractEvent) { // not false (an invalid event)
|
|
10959
|
-
cache.push.apply(
|
|
11628
|
+
cache.push.apply( // append
|
|
10960
11629
|
cache,
|
|
10961
11630
|
expandEvent(abstractEvent) // add individual expanded events to the cache
|
|
10962
11631
|
);
|
|
@@ -10984,11 +11653,12 @@ function EventManager() { // assumed to be a calendar
|
|
|
10984
11653
|
function decrementPendingSourceCnt() {
|
|
10985
11654
|
pendingSourceCnt--;
|
|
10986
11655
|
if (!pendingSourceCnt) {
|
|
10987
|
-
|
|
11656
|
+
reportEventChange(cache); // updates prunedCache
|
|
11657
|
+
t.trigger('eventsReceived', prunedCache);
|
|
10988
11658
|
}
|
|
10989
11659
|
}
|
|
10990
|
-
|
|
10991
|
-
|
|
11660
|
+
|
|
11661
|
+
|
|
10992
11662
|
function _fetchEventSource(source, callback) {
|
|
10993
11663
|
var i;
|
|
10994
11664
|
var fetchers = FC.sourceFetchers;
|
|
@@ -11097,9 +11767,9 @@ function EventManager() { // assumed to be a calendar
|
|
|
11097
11767
|
}
|
|
11098
11768
|
}
|
|
11099
11769
|
}
|
|
11100
|
-
|
|
11101
|
-
|
|
11102
|
-
|
|
11770
|
+
|
|
11771
|
+
|
|
11772
|
+
|
|
11103
11773
|
/* Sources
|
|
11104
11774
|
-----------------------------------------------------------------------------*/
|
|
11105
11775
|
|
|
@@ -11108,7 +11778,7 @@ function EventManager() { // assumed to be a calendar
|
|
|
11108
11778
|
var source = buildEventSource(sourceInput);
|
|
11109
11779
|
if (source) {
|
|
11110
11780
|
sources.push(source);
|
|
11111
|
-
fetchEventSources([ source ], 'add'); // will eventually call
|
|
11781
|
+
fetchEventSources([ source ], 'add'); // will eventually call reportEventChange
|
|
11112
11782
|
}
|
|
11113
11783
|
}
|
|
11114
11784
|
|
|
@@ -11204,7 +11874,7 @@ function EventManager() { // assumed to be a calendar
|
|
|
11204
11874
|
cache = excludeEventsBySources(cache, targetSources);
|
|
11205
11875
|
}
|
|
11206
11876
|
|
|
11207
|
-
|
|
11877
|
+
reportEventChange();
|
|
11208
11878
|
}
|
|
11209
11879
|
|
|
11210
11880
|
|
|
@@ -11298,27 +11968,39 @@ function EventManager() { // assumed to be a calendar
|
|
|
11298
11968
|
return true; // keep
|
|
11299
11969
|
});
|
|
11300
11970
|
}
|
|
11301
|
-
|
|
11302
|
-
|
|
11303
|
-
|
|
11971
|
+
|
|
11972
|
+
|
|
11973
|
+
|
|
11304
11974
|
/* Manipulation
|
|
11305
11975
|
-----------------------------------------------------------------------------*/
|
|
11306
11976
|
|
|
11307
11977
|
|
|
11308
11978
|
// Only ever called from the externally-facing API
|
|
11309
11979
|
function updateEvent(event) {
|
|
11980
|
+
updateEvents([ event ]);
|
|
11981
|
+
}
|
|
11310
11982
|
|
|
11311
|
-
|
|
11312
|
-
|
|
11313
|
-
|
|
11314
|
-
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
event
|
|
11983
|
+
|
|
11984
|
+
// Only ever called from the externally-facing API
|
|
11985
|
+
function updateEvents(events) {
|
|
11986
|
+
var i, event;
|
|
11987
|
+
|
|
11988
|
+
for (i = 0; i < events.length; i++) {
|
|
11989
|
+
event = events[i];
|
|
11990
|
+
|
|
11991
|
+
// massage start/end values, even if date string values
|
|
11992
|
+
event.start = t.moment(event.start);
|
|
11993
|
+
if (event.end) {
|
|
11994
|
+
event.end = t.moment(event.end);
|
|
11995
|
+
}
|
|
11996
|
+
else {
|
|
11997
|
+
event.end = null;
|
|
11998
|
+
}
|
|
11999
|
+
|
|
12000
|
+
mutateEvent(event, getMiscEventProps(event)); // will handle start/end/allDay normalization
|
|
11318
12001
|
}
|
|
11319
12002
|
|
|
11320
|
-
|
|
11321
|
-
reportEvents(cache); // reports event modifications (so we can redraw)
|
|
12003
|
+
reportEventChange(); // reports event modifications (so we can redraw)
|
|
11322
12004
|
}
|
|
11323
12005
|
|
|
11324
12006
|
|
|
@@ -11342,37 +12024,50 @@ function EventManager() { // assumed to be a calendar
|
|
|
11342
12024
|
return !/^_|^(id|allDay|start|end)$/.test(name);
|
|
11343
12025
|
}
|
|
11344
12026
|
|
|
11345
|
-
|
|
12027
|
+
|
|
11346
12028
|
// returns the expanded events that were created
|
|
11347
12029
|
function renderEvent(eventInput, stick) {
|
|
11348
|
-
|
|
11349
|
-
|
|
11350
|
-
var i, event;
|
|
12030
|
+
return renderEvents([ eventInput ], stick);
|
|
12031
|
+
}
|
|
11351
12032
|
|
|
11352
|
-
if (abstractEvent) { // not false (a valid input)
|
|
11353
|
-
events = expandEvent(abstractEvent);
|
|
11354
12033
|
|
|
11355
|
-
|
|
11356
|
-
|
|
12034
|
+
// returns the expanded events that were created
|
|
12035
|
+
function renderEvents(eventInputs, stick) {
|
|
12036
|
+
var renderedEvents = [];
|
|
12037
|
+
var renderableEvents;
|
|
12038
|
+
var abstractEvent;
|
|
12039
|
+
var i, j, event;
|
|
12040
|
+
|
|
12041
|
+
for (i = 0; i < eventInputs.length; i++) {
|
|
12042
|
+
abstractEvent = buildEventFromInput(eventInputs[i]);
|
|
12043
|
+
|
|
12044
|
+
if (abstractEvent) { // not false (a valid input)
|
|
12045
|
+
renderableEvents = expandEvent(abstractEvent);
|
|
12046
|
+
|
|
12047
|
+
for (j = 0; j < renderableEvents.length; j++) {
|
|
12048
|
+
event = renderableEvents[j];
|
|
11357
12049
|
|
|
11358
|
-
|
|
11359
|
-
|
|
11360
|
-
|
|
11361
|
-
|
|
12050
|
+
if (!event.source) {
|
|
12051
|
+
if (stick) {
|
|
12052
|
+
stickySource.events.push(event);
|
|
12053
|
+
event.source = stickySource;
|
|
12054
|
+
}
|
|
12055
|
+
cache.push(event);
|
|
11362
12056
|
}
|
|
11363
|
-
cache.push(event);
|
|
11364
12057
|
}
|
|
11365
|
-
}
|
|
11366
12058
|
|
|
11367
|
-
|
|
12059
|
+
renderedEvents = renderedEvents.concat(renderableEvents);
|
|
12060
|
+
}
|
|
12061
|
+
}
|
|
11368
12062
|
|
|
11369
|
-
|
|
12063
|
+
if (renderedEvents.length) { // any new events rendered?
|
|
12064
|
+
reportEventChange();
|
|
11370
12065
|
}
|
|
11371
12066
|
|
|
11372
|
-
return
|
|
12067
|
+
return renderedEvents;
|
|
11373
12068
|
}
|
|
11374
|
-
|
|
11375
|
-
|
|
12069
|
+
|
|
12070
|
+
|
|
11376
12071
|
function removeEvents(filter) {
|
|
11377
12072
|
var eventID;
|
|
11378
12073
|
var i;
|
|
@@ -11399,10 +12094,10 @@ function EventManager() { // assumed to be a calendar
|
|
|
11399
12094
|
}
|
|
11400
12095
|
}
|
|
11401
12096
|
|
|
11402
|
-
|
|
12097
|
+
reportEventChange();
|
|
11403
12098
|
}
|
|
11404
12099
|
|
|
11405
|
-
|
|
12100
|
+
|
|
11406
12101
|
function clientEvents(filter) {
|
|
11407
12102
|
if ($.isFunction(filter)) {
|
|
11408
12103
|
return $.grep(cache, filter);
|
|
@@ -11442,8 +12137,8 @@ function EventManager() { // assumed to be a calendar
|
|
|
11442
12137
|
}
|
|
11443
12138
|
backupEventDates(event);
|
|
11444
12139
|
}
|
|
11445
|
-
|
|
11446
|
-
|
|
12140
|
+
|
|
12141
|
+
|
|
11447
12142
|
/* Event Normalization
|
|
11448
12143
|
-----------------------------------------------------------------------------*/
|
|
11449
12144
|
|
|
@@ -11853,11 +12548,6 @@ function EventManager() { // assumed to be a calendar
|
|
|
11853
12548
|
};
|
|
11854
12549
|
}
|
|
11855
12550
|
|
|
11856
|
-
|
|
11857
|
-
t.getEventCache = function() {
|
|
11858
|
-
return cache;
|
|
11859
|
-
};
|
|
11860
|
-
|
|
11861
12551
|
}
|
|
11862
12552
|
|
|
11863
12553
|
|
|
@@ -12386,13 +13076,18 @@ var BasicView = FC.BasicView = View.extend({
|
|
|
12386
13076
|
------------------------------------------------------------------------------------------------------------------*/
|
|
12387
13077
|
|
|
12388
13078
|
|
|
13079
|
+
computeInitialScroll: function() {
|
|
13080
|
+
return { top: 0 };
|
|
13081
|
+
},
|
|
13082
|
+
|
|
13083
|
+
|
|
12389
13084
|
queryScroll: function() {
|
|
12390
|
-
return this.scroller.getScrollTop();
|
|
13085
|
+
return { top: this.scroller.getScrollTop() };
|
|
12391
13086
|
},
|
|
12392
13087
|
|
|
12393
13088
|
|
|
12394
|
-
setScroll: function(
|
|
12395
|
-
this.scroller.setScrollTop(top);
|
|
13089
|
+
setScroll: function(scroll) {
|
|
13090
|
+
this.scroller.setScrollTop(scroll.top);
|
|
12396
13091
|
},
|
|
12397
13092
|
|
|
12398
13093
|
|
|
@@ -12909,17 +13604,17 @@ var AgendaView = FC.AgendaView = View.extend({
|
|
|
12909
13604
|
top++; // to overcome top border that slots beyond the first have. looks better
|
|
12910
13605
|
}
|
|
12911
13606
|
|
|
12912
|
-
return top;
|
|
13607
|
+
return { top: top };
|
|
12913
13608
|
},
|
|
12914
13609
|
|
|
12915
13610
|
|
|
12916
13611
|
queryScroll: function() {
|
|
12917
|
-
return this.scroller.getScrollTop();
|
|
13612
|
+
return { top: this.scroller.getScrollTop() };
|
|
12918
13613
|
},
|
|
12919
13614
|
|
|
12920
13615
|
|
|
12921
|
-
setScroll: function(
|
|
12922
|
-
this.scroller.setScrollTop(top);
|
|
13616
|
+
setScroll: function(scroll) {
|
|
13617
|
+
this.scroller.setScrollTop(scroll.top);
|
|
12923
13618
|
},
|
|
12924
13619
|
|
|
12925
13620
|
|