fullcalendar.io-rails 2.9.1 → 3.0.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/README.md +2 -2
- data/lib/fullcalendar.io/rails/version.rb +1 -1
- data/spec/features/assets_spec.rb +2 -2
- data/vendor/assets/javascripts/fullcalendar.js +897 -668
- data/vendor/assets/javascripts/fullcalendar/gcal.js +3 -3
- data/vendor/assets/javascripts/fullcalendar/locale-all.js +5 -0
- data/vendor/assets/javascripts/fullcalendar/locale/ar-ma.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/ar-sa.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/ar-tn.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/ar.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/bg.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/ca.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/cs.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/da.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/de-at.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/de.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/el.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/en-au.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/en-ca.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/en-gb.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/en-ie.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/en-nz.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/es-do.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/es.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/eu.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/fa.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/fi.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/fr-ca.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/fr-ch.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/fr.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/gl.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/he.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/hi.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/hr.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/hu.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/id.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/is.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/it.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/ja.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/ko.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/lb.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/lt.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/lv.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/mk.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/ms-my.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/ms.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/nb.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/nl.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/nn.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/pl.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/pt-br.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/pt.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/ro.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/ru.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/sk.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/sl.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/sr-cyrl.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/sr.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/sv.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/th.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/tr.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/uk.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/vi.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/zh-cn.js +1 -0
- data/vendor/assets/javascripts/fullcalendar/locale/zh-tw.js +1 -0
- data/vendor/assets/stylesheets/fullcalendar.css +172 -36
- data/vendor/assets/stylesheets/fullcalendar.print.css +3 -3
- metadata +132 -58
- data/vendor/assets/javascripts/fullcalendar/lang-all.js +0 -4
- data/vendor/assets/javascripts/fullcalendar/lang/ar-ma.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/ar-sa.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/ar-tn.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/ar.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/bg.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/ca.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/cs.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/da.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/de-at.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/de.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/el.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/en-au.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/en-ca.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/en-gb.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/en-ie.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/en-nz.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/es.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/eu.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/fa.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/fi.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/fr-ca.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/fr-ch.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/fr.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/gl.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/he.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/hi.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/hr.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/hu.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/id.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/is.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/it.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/ja.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/ko.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/lb.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/lt.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/lv.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/nb.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/nl.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/nn.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/pl.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/pt-br.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/pt.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/ro.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/ru.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/sk.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/sl.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/sr-cyrl.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/sr.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/sv.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/th.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/tr.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/uk.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/vi.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/zh-cn.js +0 -1
- data/vendor/assets/javascripts/fullcalendar/lang/zh-tw.js +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 080eb65bbd868198fdad6cba05d63a26cd761794
|
|
4
|
+
data.tar.gz: a78008ae83226e149ba731c61741b0dddf4ff447
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e187a13847636e4a8ab145ecb702adb0688aa6ff71d57cf4bc86040c9bd0ca12c043b98ac8e265743bf3ac94ecf75b734b4bb38fc69c0513577f9dba3f298c1f
|
|
7
|
+
data.tar.gz: 3d9bff653feea5d47b21c5937d534cf8955df67109f76abef3336928534a049b6aeb8b3686a7a62e6a3d4c9d1235a7298510fa71bc9b2da7c8c20fde9a1d2e9c
|
data/README.md
CHANGED
|
@@ -28,10 +28,10 @@ And in your application.js:
|
|
|
28
28
|
//= require moment
|
|
29
29
|
//= require fullcalendar
|
|
30
30
|
|
|
31
|
-
Language files, gcal.js and
|
|
31
|
+
Language files, gcal.js and locale-all.js are located under "fullcalendar" subdirectory.
|
|
32
32
|
|
|
33
33
|
//= require fullcalendar/gcal
|
|
34
|
-
//= require fullcalendar/
|
|
34
|
+
//= require fullcalendar/locale/pl
|
|
35
35
|
|
|
36
36
|
## Usage
|
|
37
37
|
|
|
@@ -11,8 +11,8 @@ feature 'Assets integration' do
|
|
|
11
11
|
expect(page.status_code).to be 200
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
it 'provides fullcalendar/
|
|
15
|
-
visit '/assets/fullcalendar/
|
|
14
|
+
it 'provides fullcalendar/locale/pl.js on the asset pipeline' do
|
|
15
|
+
visit '/assets/fullcalendar/locale/pl.js'
|
|
16
16
|
expect(page.status_code).to be 200
|
|
17
17
|
end
|
|
18
18
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
*
|
|
3
|
-
* Docs & License:
|
|
4
|
-
* (c)
|
|
2
|
+
* FullCalendar v3.0.0
|
|
3
|
+
* Docs & License: http://fullcalendar.io/
|
|
4
|
+
* (c) 2016 Adam Shaw
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
(function(factory) {
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
;;
|
|
20
20
|
|
|
21
21
|
var FC = $.fullCalendar = {
|
|
22
|
-
version: "
|
|
23
|
-
internalApiVersion:
|
|
22
|
+
version: "3.0.0",
|
|
23
|
+
internalApiVersion: 6
|
|
24
24
|
};
|
|
25
25
|
var fcViews = FC.views = {};
|
|
26
26
|
|
|
@@ -71,56 +71,6 @@ function mergeOptions(optionObjs) {
|
|
|
71
71
|
return mergeProps(optionObjs, complexOptions);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
// Given options specified for the calendar's constructor, massages any legacy options into a non-legacy form.
|
|
76
|
-
// Converts View-Option-Hashes into the View-Specific-Options format.
|
|
77
|
-
function massageOverrides(input) {
|
|
78
|
-
var overrides = { views: input.views || {} }; // the output. ensure a `views` hash
|
|
79
|
-
var subObj;
|
|
80
|
-
|
|
81
|
-
// iterate through all option override properties (except `views`)
|
|
82
|
-
$.each(input, function(name, val) {
|
|
83
|
-
if (name != 'views') {
|
|
84
|
-
|
|
85
|
-
// could the value be a legacy View-Option-Hash?
|
|
86
|
-
if (
|
|
87
|
-
$.isPlainObject(val) &&
|
|
88
|
-
!/(time|duration|interval)$/i.test(name) && // exclude duration options. might be given as objects
|
|
89
|
-
$.inArray(name, complexOptions) == -1 // complex options aren't allowed to be View-Option-Hashes
|
|
90
|
-
) {
|
|
91
|
-
subObj = null;
|
|
92
|
-
|
|
93
|
-
// iterate through the properties of this possible View-Option-Hash value
|
|
94
|
-
$.each(val, function(subName, subVal) {
|
|
95
|
-
|
|
96
|
-
// is the property targeting a view?
|
|
97
|
-
if (/^(month|week|day|default|basic(Week|Day)?|agenda(Week|Day)?)$/.test(subName)) {
|
|
98
|
-
if (!overrides.views[subName]) { // ensure the view-target entry exists
|
|
99
|
-
overrides.views[subName] = {};
|
|
100
|
-
}
|
|
101
|
-
overrides.views[subName][name] = subVal; // record the value in the `views` object
|
|
102
|
-
}
|
|
103
|
-
else { // a non-View-Option-Hash property
|
|
104
|
-
if (!subObj) {
|
|
105
|
-
subObj = {};
|
|
106
|
-
}
|
|
107
|
-
subObj[subName] = subVal; // accumulate these unrelated values for later
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
if (subObj) { // non-View-Option-Hash properties? transfer them as-is
|
|
112
|
-
overrides[name] = subObj;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
overrides[name] = val; // transfer normal options as-is
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
return overrides;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
74
|
;;
|
|
125
75
|
|
|
126
76
|
// exports
|
|
@@ -247,7 +197,7 @@ function undistributeHeight(els) {
|
|
|
247
197
|
function matchCellWidths(els) {
|
|
248
198
|
var maxInnerWidth = 0;
|
|
249
199
|
|
|
250
|
-
els.find('>
|
|
200
|
+
els.find('> *').each(function(i, innerEl) {
|
|
251
201
|
var innerWidth = $(innerEl).outerWidth();
|
|
252
202
|
if (innerWidth > maxInnerWidth) {
|
|
253
203
|
maxInnerWidth = innerWidth;
|
|
@@ -628,7 +578,8 @@ function flexibleCompare(a, b) {
|
|
|
628
578
|
----------------------------------------------------------------------------------------------------------------------*/
|
|
629
579
|
|
|
630
580
|
|
|
631
|
-
// Computes the intersection of the two ranges.
|
|
581
|
+
// Computes the intersection of the two ranges. Will return fresh date clones in a range.
|
|
582
|
+
// Returns undefined if no intersection.
|
|
632
583
|
// Expects all dates to be normalized to the same timezone beforehand.
|
|
633
584
|
// TODO: move to date section?
|
|
634
585
|
function intersectRanges(subjectRange, constraintRange) {
|
|
@@ -908,22 +859,6 @@ function copyOwnProps(src, dest) {
|
|
|
908
859
|
}
|
|
909
860
|
|
|
910
861
|
|
|
911
|
-
// Copies over certain methods with the same names as Object.prototype methods. Overcomes an IE<=8 bug:
|
|
912
|
-
// https://developer.mozilla.org/en-US/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
|
|
913
|
-
function copyNativeMethods(src, dest) {
|
|
914
|
-
var names = [ 'constructor', 'toString', 'valueOf' ];
|
|
915
|
-
var i, name;
|
|
916
|
-
|
|
917
|
-
for (i = 0; i < names.length; i++) {
|
|
918
|
-
name = names[i];
|
|
919
|
-
|
|
920
|
-
if (src[name] !== Object.prototype[name]) {
|
|
921
|
-
dest[name] = src[name];
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
|
|
926
|
-
|
|
927
862
|
function hasOwnProp(obj, name) {
|
|
928
863
|
return hasOwnPropMethod.call(obj, name);
|
|
929
864
|
}
|
|
@@ -989,6 +924,21 @@ function cssToStr(cssProps) {
|
|
|
989
924
|
}
|
|
990
925
|
|
|
991
926
|
|
|
927
|
+
// Given an object hash of HTML attribute names to values,
|
|
928
|
+
// generates a string that can be injected between < > in HTML
|
|
929
|
+
function attrsToStr(attrs) {
|
|
930
|
+
var parts = [];
|
|
931
|
+
|
|
932
|
+
$.each(attrs, function(name, val) {
|
|
933
|
+
if (val != null) {
|
|
934
|
+
parts.push(name + '="' + htmlEscape(val) + '"');
|
|
935
|
+
}
|
|
936
|
+
});
|
|
937
|
+
|
|
938
|
+
return parts.join(' ');
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
|
|
992
942
|
function capitaliseFirstLetter(str) {
|
|
993
943
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
994
944
|
}
|
|
@@ -1070,14 +1020,24 @@ function syncThen(promise, thenFunc) {
|
|
|
1070
1020
|
|
|
1071
1021
|
;;
|
|
1072
1022
|
|
|
1023
|
+
/*
|
|
1024
|
+
GENERAL NOTE on moments throughout the *entire rest* of the codebase:
|
|
1025
|
+
All moments are assumed to be ambiguously-zoned unless otherwise noted,
|
|
1026
|
+
with the NOTABLE EXCEOPTION of start/end dates that live on *Event Objects*.
|
|
1027
|
+
Ambiguously-TIMED moments are assumed to be ambiguously-zoned by nature.
|
|
1028
|
+
*/
|
|
1029
|
+
|
|
1073
1030
|
var ambigDateOfMonthRegex = /^\s*\d{4}-\d\d$/;
|
|
1074
1031
|
var ambigTimeOrZoneRegex =
|
|
1075
1032
|
/^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?)?$/;
|
|
1076
1033
|
var newMomentProto = moment.fn; // where we will attach our new methods
|
|
1077
1034
|
var oldMomentProto = $.extend({}, newMomentProto); // copy of original moment methods
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
var
|
|
1035
|
+
|
|
1036
|
+
// tell momentjs to transfer these properties upon clone
|
|
1037
|
+
var momentProperties = moment.momentProperties;
|
|
1038
|
+
momentProperties.push('_fullCalendar');
|
|
1039
|
+
momentProperties.push('_ambigTime');
|
|
1040
|
+
momentProperties.push('_ambigZone');
|
|
1081
1041
|
|
|
1082
1042
|
|
|
1083
1043
|
// Creating
|
|
@@ -1123,12 +1083,8 @@ function makeMoment(args, parseAsUTC, parseZone) {
|
|
|
1123
1083
|
var ambigMatch;
|
|
1124
1084
|
var mom;
|
|
1125
1085
|
|
|
1126
|
-
if (moment.isMoment(input)) {
|
|
1127
|
-
mom = moment.apply(null, args);
|
|
1128
|
-
transferAmbigs(input, mom); // the ambig flags weren't transfered with the clone
|
|
1129
|
-
}
|
|
1130
|
-
else if (isNativeDate(input) || input === undefined) {
|
|
1131
|
-
mom = moment.apply(null, args); // will be local
|
|
1086
|
+
if (moment.isMoment(input) || isNativeDate(input) || input === undefined) {
|
|
1087
|
+
mom = moment.apply(null, args);
|
|
1132
1088
|
}
|
|
1133
1089
|
else { // "parsing" is required
|
|
1134
1090
|
isAmbigTime = false;
|
|
@@ -1169,12 +1125,7 @@ function makeMoment(args, parseAsUTC, parseZone) {
|
|
|
1169
1125
|
mom._ambigZone = true;
|
|
1170
1126
|
}
|
|
1171
1127
|
else if (isSingleString) {
|
|
1172
|
-
|
|
1173
|
-
mom.utcOffset(input); // if not a valid zone, will assign UTC
|
|
1174
|
-
}
|
|
1175
|
-
else {
|
|
1176
|
-
mom.zone(input); // for moment-pre-2.9
|
|
1177
|
-
}
|
|
1128
|
+
mom.utcOffset(input); // if not a valid zone, will assign UTC
|
|
1178
1129
|
}
|
|
1179
1130
|
}
|
|
1180
1131
|
}
|
|
@@ -1185,21 +1136,6 @@ function makeMoment(args, parseAsUTC, parseZone) {
|
|
|
1185
1136
|
}
|
|
1186
1137
|
|
|
1187
1138
|
|
|
1188
|
-
// A clone method that works with the flags related to our enhanced functionality.
|
|
1189
|
-
// In the future, use moment.momentProperties
|
|
1190
|
-
newMomentProto.clone = function() {
|
|
1191
|
-
var mom = oldMomentProto.clone.apply(this, arguments);
|
|
1192
|
-
|
|
1193
|
-
// these flags weren't transfered with the clone
|
|
1194
|
-
transferAmbigs(this, mom);
|
|
1195
|
-
if (this._fullCalendar) {
|
|
1196
|
-
mom._fullCalendar = true;
|
|
1197
|
-
}
|
|
1198
|
-
|
|
1199
|
-
return mom;
|
|
1200
|
-
};
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
1139
|
// Week Number
|
|
1204
1140
|
// -------------------------------------------------------------------------------------------------
|
|
1205
1141
|
|
|
@@ -1207,8 +1143,7 @@ newMomentProto.clone = function() {
|
|
|
1207
1143
|
// Returns the week number, considering the locale's custom week number calcuation
|
|
1208
1144
|
// `weeks` is an alias for `week`
|
|
1209
1145
|
newMomentProto.week = newMomentProto.weeks = function(input) {
|
|
1210
|
-
var weekCalc =
|
|
1211
|
-
._fullCalendar_weekCalc;
|
|
1146
|
+
var weekCalc = this._locale._fullCalendar_weekCalc;
|
|
1212
1147
|
|
|
1213
1148
|
if (input == null && typeof weekCalc === 'function') { // custom function only works for getter
|
|
1214
1149
|
return weekCalc(this);
|
|
@@ -1275,19 +1210,21 @@ newMomentProto.time = function(time) {
|
|
|
1275
1210
|
// but preserving its YMD. A moment with a stripped time will display no time
|
|
1276
1211
|
// nor timezone offset when .format() is called.
|
|
1277
1212
|
newMomentProto.stripTime = function() {
|
|
1278
|
-
var a;
|
|
1279
1213
|
|
|
1280
1214
|
if (!this._ambigTime) {
|
|
1281
1215
|
|
|
1282
|
-
//
|
|
1283
|
-
a = this.toArray(); // array of y/m/d/h/m/s/ms
|
|
1216
|
+
this.utc(true); // keepLocalTime=true (for keeping *date* value)
|
|
1284
1217
|
|
|
1285
|
-
//
|
|
1286
|
-
this.
|
|
1287
|
-
|
|
1218
|
+
// set time to zero
|
|
1219
|
+
this.set({
|
|
1220
|
+
hours: 0,
|
|
1221
|
+
minutes: 0,
|
|
1222
|
+
seconds: 0,
|
|
1223
|
+
ms: 0
|
|
1224
|
+
});
|
|
1288
1225
|
|
|
1289
1226
|
// Mark the time as ambiguous. This needs to happen after the .utc() call, which might call .utcOffset(),
|
|
1290
|
-
// which clears all ambig flags.
|
|
1227
|
+
// which clears all ambig flags.
|
|
1291
1228
|
this._ambigTime = true;
|
|
1292
1229
|
this._ambigZone = true; // if ambiguous time, also ambiguous timezone offset
|
|
1293
1230
|
}
|
|
@@ -1307,24 +1244,20 @@ newMomentProto.hasTime = function() {
|
|
|
1307
1244
|
// Converts the moment to UTC, stripping out its timezone offset, but preserving its
|
|
1308
1245
|
// YMD and time-of-day. A moment with a stripped timezone offset will display no
|
|
1309
1246
|
// timezone offset when .format() is called.
|
|
1310
|
-
// TODO: look into Moment's keepLocalTime functionality
|
|
1311
1247
|
newMomentProto.stripZone = function() {
|
|
1312
|
-
var
|
|
1248
|
+
var wasAmbigTime;
|
|
1313
1249
|
|
|
1314
1250
|
if (!this._ambigZone) {
|
|
1315
1251
|
|
|
1316
|
-
// get the values before any conversion happens
|
|
1317
|
-
a = this.toArray(); // array of y/m/d/h/m/s/ms
|
|
1318
1252
|
wasAmbigTime = this._ambigTime;
|
|
1319
1253
|
|
|
1320
|
-
this.utc(); //
|
|
1321
|
-
setUTCValues(this, a); // will set the year/month/date/hours/minutes/seconds/ms
|
|
1254
|
+
this.utc(true); // keepLocalTime=true (for keeping date and time values)
|
|
1322
1255
|
|
|
1323
1256
|
// the above call to .utc()/.utcOffset() unfortunately might clear the ambig flags, so restore
|
|
1324
1257
|
this._ambigTime = wasAmbigTime || false;
|
|
1325
1258
|
|
|
1326
1259
|
// Mark the zone as ambiguous. This needs to happen after the .utc() call, which might call .utcOffset(),
|
|
1327
|
-
// which clears the ambig flags.
|
|
1260
|
+
// which clears the ambig flags.
|
|
1328
1261
|
this._ambigZone = true;
|
|
1329
1262
|
}
|
|
1330
1263
|
|
|
@@ -1337,32 +1270,26 @@ newMomentProto.hasZone = function() {
|
|
|
1337
1270
|
};
|
|
1338
1271
|
|
|
1339
1272
|
|
|
1340
|
-
//
|
|
1341
|
-
newMomentProto.local = function() {
|
|
1342
|
-
var a = this.toArray(); // year,month,date,hours,minutes,seconds,ms as an array
|
|
1343
|
-
var wasAmbigZone = this._ambigZone;
|
|
1273
|
+
// implicitly marks a zone
|
|
1274
|
+
newMomentProto.local = function(keepLocalTime) {
|
|
1344
1275
|
|
|
1345
|
-
|
|
1276
|
+
// for when converting from ambiguously-zoned to local,
|
|
1277
|
+
// keep the time values when converting from UTC -> local
|
|
1278
|
+
oldMomentProto.local.call(this, this._ambigZone || keepLocalTime);
|
|
1346
1279
|
|
|
1347
1280
|
// ensure non-ambiguous
|
|
1348
1281
|
// this probably already happened via local() -> utcOffset(), but don't rely on Moment's internals
|
|
1349
1282
|
this._ambigTime = false;
|
|
1350
1283
|
this._ambigZone = false;
|
|
1351
1284
|
|
|
1352
|
-
if (wasAmbigZone) {
|
|
1353
|
-
// If the moment was ambiguously zoned, the date fields were stored as UTC.
|
|
1354
|
-
// We want to preserve these, but in local time.
|
|
1355
|
-
// TODO: look into Moment's keepLocalTime functionality
|
|
1356
|
-
setLocalValues(this, a);
|
|
1357
|
-
}
|
|
1358
|
-
|
|
1359
1285
|
return this; // for chaining
|
|
1360
1286
|
};
|
|
1361
1287
|
|
|
1362
1288
|
|
|
1363
1289
|
// implicitly marks a zone
|
|
1364
|
-
newMomentProto.utc = function() {
|
|
1365
|
-
|
|
1290
|
+
newMomentProto.utc = function(keepLocalTime) {
|
|
1291
|
+
|
|
1292
|
+
oldMomentProto.utc.call(this, keepLocalTime);
|
|
1366
1293
|
|
|
1367
1294
|
// ensure non-ambiguous
|
|
1368
1295
|
// this probably already happened via utc() -> utcOffset(), but don't rely on Moment's internals
|
|
@@ -1373,28 +1300,18 @@ newMomentProto.utc = function() {
|
|
|
1373
1300
|
};
|
|
1374
1301
|
|
|
1375
1302
|
|
|
1376
|
-
//
|
|
1377
|
-
|
|
1378
|
-
$.each([
|
|
1379
|
-
'zone', // only in moment-pre-2.9. deprecated afterwards
|
|
1380
|
-
'utcOffset'
|
|
1381
|
-
], function(i, name) {
|
|
1382
|
-
if (oldMomentProto[name]) { // original method exists?
|
|
1383
|
-
|
|
1384
|
-
// this method implicitly marks a zone (will probably get called upon .utc() and .local())
|
|
1385
|
-
newMomentProto[name] = function(tzo) {
|
|
1303
|
+
// implicitly marks a zone (will probably get called upon .utc() and .local())
|
|
1304
|
+
newMomentProto.utcOffset = function(tzo) {
|
|
1386
1305
|
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
}
|
|
1393
|
-
|
|
1394
|
-
return oldMomentProto[name].apply(this, arguments);
|
|
1395
|
-
};
|
|
1306
|
+
if (tzo != null) { // setter
|
|
1307
|
+
// these assignments needs to happen before the original zone method is called.
|
|
1308
|
+
// I forget why, something to do with a browser crash.
|
|
1309
|
+
this._ambigTime = false;
|
|
1310
|
+
this._ambigZone = false;
|
|
1396
1311
|
}
|
|
1397
|
-
|
|
1312
|
+
|
|
1313
|
+
return oldMomentProto.utcOffset.apply(this, arguments);
|
|
1314
|
+
};
|
|
1398
1315
|
|
|
1399
1316
|
|
|
1400
1317
|
// Formatting
|
|
@@ -1423,156 +1340,6 @@ newMomentProto.toISOString = function() {
|
|
|
1423
1340
|
return oldMomentProto.toISOString.apply(this, arguments);
|
|
1424
1341
|
};
|
|
1425
1342
|
|
|
1426
|
-
|
|
1427
|
-
// Querying
|
|
1428
|
-
// -------------------------------------------------------------------------------------------------
|
|
1429
|
-
|
|
1430
|
-
// Is the moment within the specified range? `end` is exclusive.
|
|
1431
|
-
// FYI, this method is not a standard Moment method, so always do our enhanced logic.
|
|
1432
|
-
newMomentProto.isWithin = function(start, end) {
|
|
1433
|
-
var a = commonlyAmbiguate([ this, start, end ]);
|
|
1434
|
-
return a[0] >= a[1] && a[0] < a[2];
|
|
1435
|
-
};
|
|
1436
|
-
|
|
1437
|
-
// When isSame is called with units, timezone ambiguity is normalized before the comparison happens.
|
|
1438
|
-
// If no units specified, the two moments must be identically the same, with matching ambig flags.
|
|
1439
|
-
newMomentProto.isSame = function(input, units) {
|
|
1440
|
-
var a;
|
|
1441
|
-
|
|
1442
|
-
// only do custom logic if this is an enhanced moment
|
|
1443
|
-
if (!this._fullCalendar) {
|
|
1444
|
-
return oldMomentProto.isSame.apply(this, arguments);
|
|
1445
|
-
}
|
|
1446
|
-
|
|
1447
|
-
if (units) {
|
|
1448
|
-
a = commonlyAmbiguate([ this, input ], true); // normalize timezones but don't erase times
|
|
1449
|
-
return oldMomentProto.isSame.call(a[0], a[1], units);
|
|
1450
|
-
}
|
|
1451
|
-
else {
|
|
1452
|
-
input = FC.moment.parseZone(input); // normalize input
|
|
1453
|
-
return oldMomentProto.isSame.call(this, input) &&
|
|
1454
|
-
Boolean(this._ambigTime) === Boolean(input._ambigTime) &&
|
|
1455
|
-
Boolean(this._ambigZone) === Boolean(input._ambigZone);
|
|
1456
|
-
}
|
|
1457
|
-
};
|
|
1458
|
-
|
|
1459
|
-
// Make these query methods work with ambiguous moments
|
|
1460
|
-
$.each([
|
|
1461
|
-
'isBefore',
|
|
1462
|
-
'isAfter'
|
|
1463
|
-
], function(i, methodName) {
|
|
1464
|
-
newMomentProto[methodName] = function(input, units) {
|
|
1465
|
-
var a;
|
|
1466
|
-
|
|
1467
|
-
// only do custom logic if this is an enhanced moment
|
|
1468
|
-
if (!this._fullCalendar) {
|
|
1469
|
-
return oldMomentProto[methodName].apply(this, arguments);
|
|
1470
|
-
}
|
|
1471
|
-
|
|
1472
|
-
a = commonlyAmbiguate([ this, input ]);
|
|
1473
|
-
return oldMomentProto[methodName].call(a[0], a[1], units);
|
|
1474
|
-
};
|
|
1475
|
-
});
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
// Misc Internals
|
|
1479
|
-
// -------------------------------------------------------------------------------------------------
|
|
1480
|
-
|
|
1481
|
-
// given an array of moment-like inputs, return a parallel array w/ moments similarly ambiguated.
|
|
1482
|
-
// for example, of one moment has ambig time, but not others, all moments will have their time stripped.
|
|
1483
|
-
// set `preserveTime` to `true` to keep times, but only normalize zone ambiguity.
|
|
1484
|
-
// returns the original moments if no modifications are necessary.
|
|
1485
|
-
function commonlyAmbiguate(inputs, preserveTime) {
|
|
1486
|
-
var anyAmbigTime = false;
|
|
1487
|
-
var anyAmbigZone = false;
|
|
1488
|
-
var len = inputs.length;
|
|
1489
|
-
var moms = [];
|
|
1490
|
-
var i, mom;
|
|
1491
|
-
|
|
1492
|
-
// parse inputs into real moments and query their ambig flags
|
|
1493
|
-
for (i = 0; i < len; i++) {
|
|
1494
|
-
mom = inputs[i];
|
|
1495
|
-
if (!moment.isMoment(mom)) {
|
|
1496
|
-
mom = FC.moment.parseZone(mom);
|
|
1497
|
-
}
|
|
1498
|
-
anyAmbigTime = anyAmbigTime || mom._ambigTime;
|
|
1499
|
-
anyAmbigZone = anyAmbigZone || mom._ambigZone;
|
|
1500
|
-
moms.push(mom);
|
|
1501
|
-
}
|
|
1502
|
-
|
|
1503
|
-
// strip each moment down to lowest common ambiguity
|
|
1504
|
-
// use clones to avoid modifying the original moments
|
|
1505
|
-
for (i = 0; i < len; i++) {
|
|
1506
|
-
mom = moms[i];
|
|
1507
|
-
if (!preserveTime && anyAmbigTime && !mom._ambigTime) {
|
|
1508
|
-
moms[i] = mom.clone().stripTime();
|
|
1509
|
-
}
|
|
1510
|
-
else if (anyAmbigZone && !mom._ambigZone) {
|
|
1511
|
-
moms[i] = mom.clone().stripZone();
|
|
1512
|
-
}
|
|
1513
|
-
}
|
|
1514
|
-
|
|
1515
|
-
return moms;
|
|
1516
|
-
}
|
|
1517
|
-
|
|
1518
|
-
// Transfers all the flags related to ambiguous time/zone from the `src` moment to the `dest` moment
|
|
1519
|
-
// TODO: look into moment.momentProperties for this.
|
|
1520
|
-
function transferAmbigs(src, dest) {
|
|
1521
|
-
if (src._ambigTime) {
|
|
1522
|
-
dest._ambigTime = true;
|
|
1523
|
-
}
|
|
1524
|
-
else if (dest._ambigTime) {
|
|
1525
|
-
dest._ambigTime = false;
|
|
1526
|
-
}
|
|
1527
|
-
|
|
1528
|
-
if (src._ambigZone) {
|
|
1529
|
-
dest._ambigZone = true;
|
|
1530
|
-
}
|
|
1531
|
-
else if (dest._ambigZone) {
|
|
1532
|
-
dest._ambigZone = false;
|
|
1533
|
-
}
|
|
1534
|
-
}
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
// Sets the year/month/date/etc values of the moment from the given array.
|
|
1538
|
-
// Inefficient because it calls each individual setter.
|
|
1539
|
-
function setMomentValues(mom, a) {
|
|
1540
|
-
mom.year(a[0] || 0)
|
|
1541
|
-
.month(a[1] || 0)
|
|
1542
|
-
.date(a[2] || 0)
|
|
1543
|
-
.hours(a[3] || 0)
|
|
1544
|
-
.minutes(a[4] || 0)
|
|
1545
|
-
.seconds(a[5] || 0)
|
|
1546
|
-
.milliseconds(a[6] || 0);
|
|
1547
|
-
}
|
|
1548
|
-
|
|
1549
|
-
// Can we set the moment's internal date directly?
|
|
1550
|
-
allowValueOptimization = '_d' in moment() && 'updateOffset' in moment;
|
|
1551
|
-
|
|
1552
|
-
// Utility function. Accepts a moment and an array of the UTC year/month/date/etc values to set.
|
|
1553
|
-
// Assumes the given moment is already in UTC mode.
|
|
1554
|
-
setUTCValues = allowValueOptimization ? function(mom, a) {
|
|
1555
|
-
// simlate what moment's accessors do
|
|
1556
|
-
mom._d.setTime(Date.UTC.apply(Date, a));
|
|
1557
|
-
moment.updateOffset(mom, false); // keepTime=false
|
|
1558
|
-
} : setMomentValues;
|
|
1559
|
-
|
|
1560
|
-
// Utility function. Accepts a moment and an array of the local year/month/date/etc values to set.
|
|
1561
|
-
// Assumes the given moment is already in local mode.
|
|
1562
|
-
setLocalValues = allowValueOptimization ? function(mom, a) {
|
|
1563
|
-
// simlate what moment's accessors do
|
|
1564
|
-
mom._d.setTime(+new Date( // FYI, there is now way to apply an array of args to a constructor
|
|
1565
|
-
a[0] || 0,
|
|
1566
|
-
a[1] || 0,
|
|
1567
|
-
a[2] || 0,
|
|
1568
|
-
a[3] || 0,
|
|
1569
|
-
a[4] || 0,
|
|
1570
|
-
a[5] || 0,
|
|
1571
|
-
a[6] || 0
|
|
1572
|
-
));
|
|
1573
|
-
moment.updateOffset(mom, false); // keepTime=false
|
|
1574
|
-
} : setMomentValues;
|
|
1575
|
-
|
|
1576
1343
|
;;
|
|
1577
1344
|
|
|
1578
1345
|
// Single Date Formatting
|
|
@@ -1653,7 +1420,7 @@ function formatRange(date1, date2, formatStr, separator, isRTL) {
|
|
|
1653
1420
|
date1 = FC.moment.parseZone(date1);
|
|
1654
1421
|
date2 = FC.moment.parseZone(date2);
|
|
1655
1422
|
|
|
1656
|
-
localeData =
|
|
1423
|
+
localeData = date1.localeData();
|
|
1657
1424
|
|
|
1658
1425
|
// Expand localized format strings, like "LL" -> "MMMM D YYYY"
|
|
1659
1426
|
formatStr = localeData.longDateFormat(formatStr) || formatStr;
|
|
@@ -1858,7 +1625,6 @@ function extendClass(superClass, members) {
|
|
|
1858
1625
|
|
|
1859
1626
|
// copy each member variable/method onto the the subclass's prototype
|
|
1860
1627
|
copyOwnProps(members, subClass.prototype);
|
|
1861
|
-
copyNativeMethods(members, subClass.prototype); // hack for IE8
|
|
1862
1628
|
|
|
1863
1629
|
// copy over all class variables/methods to the subclass, such as `extend` and `mixin`
|
|
1864
1630
|
copyOwnProps(superClass, subClass);
|
|
@@ -1868,7 +1634,7 @@ function extendClass(superClass, members) {
|
|
|
1868
1634
|
|
|
1869
1635
|
|
|
1870
1636
|
function mixIntoClass(theClass, members) {
|
|
1871
|
-
copyOwnProps(members, theClass.prototype);
|
|
1637
|
+
copyOwnProps(members, theClass.prototype);
|
|
1872
1638
|
}
|
|
1873
1639
|
;;
|
|
1874
1640
|
|
|
@@ -2446,10 +2212,7 @@ var CoordCache = FC.CoordCache = Class.extend({
|
|
|
2446
2212
|
var DragListener = FC.DragListener = Class.extend(ListenerMixin, MouseIgnorerMixin, {
|
|
2447
2213
|
|
|
2448
2214
|
options: null,
|
|
2449
|
-
|
|
2450
|
-
// for IE8 bug-fighting behavior
|
|
2451
2215
|
subjectEl: null,
|
|
2452
|
-
subjectHref: null,
|
|
2453
2216
|
|
|
2454
2217
|
// coordinates of the initial mousedown
|
|
2455
2218
|
originX: null,
|
|
@@ -2640,7 +2403,6 @@ var DragListener = FC.DragListener = Class.extend(ListenerMixin, MouseIgnorerMix
|
|
|
2640
2403
|
|
|
2641
2404
|
handleDragStart: function(ev) {
|
|
2642
2405
|
this.trigger('dragStart', ev);
|
|
2643
|
-
this.initHrefHack();
|
|
2644
2406
|
},
|
|
2645
2407
|
|
|
2646
2408
|
|
|
@@ -2680,7 +2442,6 @@ var DragListener = FC.DragListener = Class.extend(ListenerMixin, MouseIgnorerMix
|
|
|
2680
2442
|
|
|
2681
2443
|
handleDragEnd: function(ev) {
|
|
2682
2444
|
this.trigger('dragEnd', ev);
|
|
2683
|
-
this.destroyHrefHack();
|
|
2684
2445
|
},
|
|
2685
2446
|
|
|
2686
2447
|
|
|
@@ -2756,33 +2517,6 @@ var DragListener = FC.DragListener = Class.extend(ListenerMixin, MouseIgnorerMix
|
|
|
2756
2517
|
},
|
|
2757
2518
|
|
|
2758
2519
|
|
|
2759
|
-
// <A> HREF Hack
|
|
2760
|
-
// -----------------------------------------------------------------------------------------------------------------
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
initHrefHack: function() {
|
|
2764
|
-
var subjectEl = this.subjectEl;
|
|
2765
|
-
|
|
2766
|
-
// remove a mousedown'd <a>'s href so it is not visited (IE8 bug)
|
|
2767
|
-
if ((this.subjectHref = subjectEl ? subjectEl.attr('href') : null)) {
|
|
2768
|
-
subjectEl.removeAttr('href');
|
|
2769
|
-
}
|
|
2770
|
-
},
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
destroyHrefHack: function() {
|
|
2774
|
-
var subjectEl = this.subjectEl;
|
|
2775
|
-
var subjectHref = this.subjectHref;
|
|
2776
|
-
|
|
2777
|
-
// restore a mousedown'd <a>'s href (for IE8 bug)
|
|
2778
|
-
setTimeout(function() { // must be outside of the click's execution
|
|
2779
|
-
if (subjectHref) {
|
|
2780
|
-
subjectEl.attr('href', subjectHref);
|
|
2781
|
-
}
|
|
2782
|
-
}, 0);
|
|
2783
|
-
},
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
2520
|
// Utils
|
|
2787
2521
|
// -----------------------------------------------------------------------------------------------------------------
|
|
2788
2522
|
|
|
@@ -3306,7 +3040,6 @@ var MouseFollower = Class.extend(ListenerMixin, {
|
|
|
3306
3040
|
var el = this.el;
|
|
3307
3041
|
|
|
3308
3042
|
if (!el) {
|
|
3309
|
-
this.sourceEl.width(); // hack to force IE8 to compute correct bounding box
|
|
3310
3043
|
el = this.el = this.sourceEl.clone()
|
|
3311
3044
|
.addClass(this.options.additionalClass || '')
|
|
3312
3045
|
.css({
|
|
@@ -3351,7 +3084,6 @@ var MouseFollower = Class.extend(ListenerMixin, {
|
|
|
3351
3084
|
|
|
3352
3085
|
// make sure origin info was computed
|
|
3353
3086
|
if (this.top0 === null) {
|
|
3354
|
-
this.sourceEl.width(); // hack to force IE8 to compute correct bounding box
|
|
3355
3087
|
sourceOffset = this.sourceEl.offset();
|
|
3356
3088
|
origin = this.el.offsetParent().offset();
|
|
3357
3089
|
this.top0 = sourceOffset.top - origin.top;
|
|
@@ -3405,6 +3137,9 @@ var MouseFollower = Class.extend(ListenerMixin, {
|
|
|
3405
3137
|
|
|
3406
3138
|
var Grid = FC.Grid = Class.extend(ListenerMixin, MouseIgnorerMixin, {
|
|
3407
3139
|
|
|
3140
|
+
// self-config, overridable by subclasses
|
|
3141
|
+
hasDayInteractions: true, // can user click/select ranges of time?
|
|
3142
|
+
|
|
3408
3143
|
view: null, // a View object
|
|
3409
3144
|
isRTL: null, // shortcut to the view's isRTL option
|
|
3410
3145
|
|
|
@@ -3572,10 +3307,13 @@ var Grid = FC.Grid = Class.extend(ListenerMixin, MouseIgnorerMixin, {
|
|
|
3572
3307
|
// Does other DOM-related initializations.
|
|
3573
3308
|
setElement: function(el) {
|
|
3574
3309
|
this.el = el;
|
|
3575
|
-
preventSelection(el);
|
|
3576
3310
|
|
|
3577
|
-
|
|
3578
|
-
|
|
3311
|
+
if (this.hasDayInteractions) {
|
|
3312
|
+
preventSelection(el);
|
|
3313
|
+
|
|
3314
|
+
this.bindDayHandler('touchstart', this.dayTouchStart);
|
|
3315
|
+
this.bindDayHandler('mousedown', this.dayMousedown);
|
|
3316
|
+
}
|
|
3579
3317
|
|
|
3580
3318
|
// attach event-element-related handlers. in Grid.events
|
|
3581
3319
|
// same garbage collection note as above.
|
|
@@ -3592,7 +3330,12 @@ var Grid = FC.Grid = Class.extend(ListenerMixin, MouseIgnorerMixin, {
|
|
|
3592
3330
|
// jQuery will take care of unregistering them when removeElement gets called.
|
|
3593
3331
|
this.el.on(name, function(ev) {
|
|
3594
3332
|
if (
|
|
3595
|
-
!$(ev.target).is(
|
|
3333
|
+
!$(ev.target).is(
|
|
3334
|
+
_this.segSelector + ',' + // directly on an event element
|
|
3335
|
+
_this.segSelector + ' *,' + // within an event element
|
|
3336
|
+
'.fc-more,' + // a "more.." link
|
|
3337
|
+
'a[data-goto]' // a clickable nav link
|
|
3338
|
+
)
|
|
3596
3339
|
) {
|
|
3597
3340
|
return handler.call(_this, ev);
|
|
3598
3341
|
}
|
|
@@ -4044,6 +3787,9 @@ var Grid = FC.Grid = Class.extend(ListenerMixin, MouseIgnorerMixin, {
|
|
|
4044
3787
|
|
|
4045
3788
|
Grid.mixin({
|
|
4046
3789
|
|
|
3790
|
+
// self-config, overridable by subclasses
|
|
3791
|
+
segSelector: '.fc-event-container > *', // what constitutes an event element?
|
|
3792
|
+
|
|
4047
3793
|
mousedOverSeg: null, // the segment object the user's mouse is over. null if over nothing
|
|
4048
3794
|
isDraggingSeg: false, // is a segment being dragged? boolean
|
|
4049
3795
|
isResizingSeg: false, // is a segment being resized? boolean
|
|
@@ -4265,7 +4011,7 @@ Grid.mixin({
|
|
|
4265
4011
|
bindSegHandlerToEl: function(el, name, handler) {
|
|
4266
4012
|
var _this = this;
|
|
4267
4013
|
|
|
4268
|
-
el.on(name,
|
|
4014
|
+
el.on(name, this.segSelector, function(ev) {
|
|
4269
4015
|
var seg = $(this).data('fc-seg'); // grab segment data. put there by View::renderEvents
|
|
4270
4016
|
|
|
4271
4017
|
// only call the handlers if there is not a drag/resize in progress
|
|
@@ -4277,7 +4023,10 @@ Grid.mixin({
|
|
|
4277
4023
|
|
|
4278
4024
|
|
|
4279
4025
|
handleSegClick: function(seg, ev) {
|
|
4280
|
-
|
|
4026
|
+
var res = this.view.trigger('eventClick', seg.el[0], seg.event, ev); // can return `false` to cancel
|
|
4027
|
+
if (res === false) {
|
|
4028
|
+
ev.preventDefault();
|
|
4029
|
+
}
|
|
4281
4030
|
},
|
|
4282
4031
|
|
|
4283
4032
|
|
|
@@ -4288,7 +4037,9 @@ Grid.mixin({
|
|
|
4288
4037
|
!this.mousedOverSeg
|
|
4289
4038
|
) {
|
|
4290
4039
|
this.mousedOverSeg = seg;
|
|
4291
|
-
|
|
4040
|
+
if (this.view.isEventResizable(seg.event)) {
|
|
4041
|
+
seg.el.addClass('fc-allow-mouse-resize');
|
|
4042
|
+
}
|
|
4292
4043
|
this.view.trigger('eventMouseover', seg.el[0], seg.event, ev);
|
|
4293
4044
|
}
|
|
4294
4045
|
},
|
|
@@ -4302,7 +4053,9 @@ Grid.mixin({
|
|
|
4302
4053
|
if (this.mousedOverSeg) {
|
|
4303
4054
|
seg = seg || this.mousedOverSeg; // if given no args, use the currently moused-over segment
|
|
4304
4055
|
this.mousedOverSeg = null;
|
|
4305
|
-
|
|
4056
|
+
if (this.view.isEventResizable(seg.event)) {
|
|
4057
|
+
seg.el.removeClass('fc-allow-mouse-resize');
|
|
4058
|
+
}
|
|
4306
4059
|
this.view.trigger('eventMouseout', seg.el[0], seg.event, ev);
|
|
4307
4060
|
}
|
|
4308
4061
|
},
|
|
@@ -4557,11 +4310,7 @@ Grid.mixin({
|
|
|
4557
4310
|
}
|
|
4558
4311
|
// othewise, work off existing values
|
|
4559
4312
|
else {
|
|
4560
|
-
dropLocation =
|
|
4561
|
-
start: event.start.clone(),
|
|
4562
|
-
end: event.end ? event.end.clone() : null,
|
|
4563
|
-
allDay: event.allDay // keep it the same
|
|
4564
|
-
};
|
|
4313
|
+
dropLocation = pluckEventDateProps(event);
|
|
4565
4314
|
}
|
|
4566
4315
|
|
|
4567
4316
|
dropLocation.start.add(delta);
|
|
@@ -4587,11 +4336,7 @@ Grid.mixin({
|
|
|
4587
4336
|
var opacity = this.view.opt('dragOpacity');
|
|
4588
4337
|
|
|
4589
4338
|
if (opacity != null) {
|
|
4590
|
-
els.
|
|
4591
|
-
// Don't use jQuery (will set an IE filter), do it the old fashioned way.
|
|
4592
|
-
// In IE8, a helper element will disappears if there's a filter.
|
|
4593
|
-
node.style.opacity = opacity;
|
|
4594
|
-
});
|
|
4339
|
+
els.css('opacity', opacity);
|
|
4595
4340
|
}
|
|
4596
4341
|
},
|
|
4597
4342
|
|
|
@@ -4757,8 +4502,11 @@ Grid.mixin({
|
|
|
4757
4502
|
disableCursor();
|
|
4758
4503
|
resizeLocation = null;
|
|
4759
4504
|
}
|
|
4760
|
-
// no change? (
|
|
4761
|
-
else if (
|
|
4505
|
+
// no change? (FYI, event dates might have zones)
|
|
4506
|
+
else if (
|
|
4507
|
+
resizeLocation.start.isSame(event.start.clone().stripZone()) &&
|
|
4508
|
+
resizeLocation.end.isSame(eventEnd.clone().stripZone())
|
|
4509
|
+
) {
|
|
4762
4510
|
resizeLocation = null;
|
|
4763
4511
|
}
|
|
4764
4512
|
}
|
|
@@ -4911,15 +4659,11 @@ Grid.mixin({
|
|
|
4911
4659
|
// Generic utility for generating the HTML classNames for an event segment's element
|
|
4912
4660
|
getSegClasses: function(seg, isDraggable, isResizable) {
|
|
4913
4661
|
var view = this.view;
|
|
4914
|
-
var event = seg.event;
|
|
4915
4662
|
var classes = [
|
|
4916
4663
|
'fc-event',
|
|
4917
4664
|
seg.isStart ? 'fc-start' : 'fc-not-start',
|
|
4918
4665
|
seg.isEnd ? 'fc-end' : 'fc-not-end'
|
|
4919
|
-
].concat(
|
|
4920
|
-
event.className,
|
|
4921
|
-
event.source ? event.source.className : []
|
|
4922
|
-
);
|
|
4666
|
+
].concat(this.getSegCustomClasses(seg));
|
|
4923
4667
|
|
|
4924
4668
|
if (isDraggable) {
|
|
4925
4669
|
classes.push('fc-draggable');
|
|
@@ -4929,7 +4673,7 @@ Grid.mixin({
|
|
|
4929
4673
|
}
|
|
4930
4674
|
|
|
4931
4675
|
// event is currently selected? attach a className.
|
|
4932
|
-
if (view.isEventSelected(event)) {
|
|
4676
|
+
if (view.isEventSelected(seg.event)) {
|
|
4933
4677
|
classes.push('fc-selected');
|
|
4934
4678
|
}
|
|
4935
4679
|
|
|
@@ -4937,38 +4681,78 @@ Grid.mixin({
|
|
|
4937
4681
|
},
|
|
4938
4682
|
|
|
4939
4683
|
|
|
4940
|
-
//
|
|
4941
|
-
|
|
4684
|
+
// List of classes that were defined by the caller of the API in some way
|
|
4685
|
+
getSegCustomClasses: function(seg) {
|
|
4942
4686
|
var event = seg.event;
|
|
4943
|
-
var view = this.view;
|
|
4944
|
-
var source = event.source || {};
|
|
4945
|
-
var eventColor = event.color;
|
|
4946
|
-
var sourceColor = source.color;
|
|
4947
|
-
var optionColor = view.opt('eventColor');
|
|
4948
4687
|
|
|
4688
|
+
return [].concat(
|
|
4689
|
+
event.className, // guaranteed to be an array
|
|
4690
|
+
event.source ? event.source.className : []
|
|
4691
|
+
);
|
|
4692
|
+
},
|
|
4693
|
+
|
|
4694
|
+
|
|
4695
|
+
// Utility for generating event skin-related CSS properties
|
|
4696
|
+
getSegSkinCss: function(seg) {
|
|
4949
4697
|
return {
|
|
4950
|
-
'background-color':
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
source.backgroundColor ||
|
|
4954
|
-
sourceColor ||
|
|
4955
|
-
view.opt('eventBackgroundColor') ||
|
|
4956
|
-
optionColor,
|
|
4957
|
-
'border-color':
|
|
4958
|
-
event.borderColor ||
|
|
4959
|
-
eventColor ||
|
|
4960
|
-
source.borderColor ||
|
|
4961
|
-
sourceColor ||
|
|
4962
|
-
view.opt('eventBorderColor') ||
|
|
4963
|
-
optionColor,
|
|
4964
|
-
color:
|
|
4965
|
-
event.textColor ||
|
|
4966
|
-
source.textColor ||
|
|
4967
|
-
view.opt('eventTextColor')
|
|
4698
|
+
'background-color': this.getSegBackgroundColor(seg),
|
|
4699
|
+
'border-color': this.getSegBorderColor(seg),
|
|
4700
|
+
color: this.getSegTextColor(seg)
|
|
4968
4701
|
};
|
|
4969
4702
|
},
|
|
4970
4703
|
|
|
4971
4704
|
|
|
4705
|
+
// Queries for caller-specified color, then falls back to default
|
|
4706
|
+
getSegBackgroundColor: function(seg) {
|
|
4707
|
+
return seg.event.backgroundColor ||
|
|
4708
|
+
seg.event.color ||
|
|
4709
|
+
this.getSegDefaultBackgroundColor(seg);
|
|
4710
|
+
},
|
|
4711
|
+
|
|
4712
|
+
|
|
4713
|
+
getSegDefaultBackgroundColor: function(seg) {
|
|
4714
|
+
var source = seg.event.source || {};
|
|
4715
|
+
|
|
4716
|
+
return source.backgroundColor ||
|
|
4717
|
+
source.color ||
|
|
4718
|
+
this.view.opt('eventBackgroundColor') ||
|
|
4719
|
+
this.view.opt('eventColor');
|
|
4720
|
+
},
|
|
4721
|
+
|
|
4722
|
+
|
|
4723
|
+
// Queries for caller-specified color, then falls back to default
|
|
4724
|
+
getSegBorderColor: function(seg) {
|
|
4725
|
+
return seg.event.borderColor ||
|
|
4726
|
+
seg.event.color ||
|
|
4727
|
+
this.getSegDefaultBorderColor(seg);
|
|
4728
|
+
},
|
|
4729
|
+
|
|
4730
|
+
|
|
4731
|
+
getSegDefaultBorderColor: function(seg) {
|
|
4732
|
+
var source = seg.event.source || {};
|
|
4733
|
+
|
|
4734
|
+
return source.borderColor ||
|
|
4735
|
+
source.color ||
|
|
4736
|
+
this.view.opt('eventBorderColor') ||
|
|
4737
|
+
this.view.opt('eventColor');
|
|
4738
|
+
},
|
|
4739
|
+
|
|
4740
|
+
|
|
4741
|
+
// Queries for caller-specified color, then falls back to default
|
|
4742
|
+
getSegTextColor: function(seg) {
|
|
4743
|
+
return seg.event.textColor ||
|
|
4744
|
+
this.getSegDefaultTextColor(seg);
|
|
4745
|
+
},
|
|
4746
|
+
|
|
4747
|
+
|
|
4748
|
+
getSegDefaultTextColor: function(seg) {
|
|
4749
|
+
var source = seg.event.source || {};
|
|
4750
|
+
|
|
4751
|
+
return source.textColor ||
|
|
4752
|
+
this.view.opt('eventTextColor');
|
|
4753
|
+
},
|
|
4754
|
+
|
|
4755
|
+
|
|
4972
4756
|
/* Converting events -> eventRange -> eventSpan -> eventSegs
|
|
4973
4757
|
------------------------------------------------------------------------------------------------------------------*/
|
|
4974
4758
|
|
|
@@ -5036,20 +4820,25 @@ Grid.mixin({
|
|
|
5036
4820
|
// Generates the unzoned start/end dates an event appears to occupy
|
|
5037
4821
|
// Can accept an event "location" as well (which only has start/end and no allDay)
|
|
5038
4822
|
eventToRange: function(event) {
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
4823
|
+
var calendar = this.view.calendar;
|
|
4824
|
+
var start = event.start.clone().stripZone();
|
|
4825
|
+
var end = (
|
|
5042
4826
|
event.end ?
|
|
5043
4827
|
event.end.clone() :
|
|
5044
4828
|
// derive the end from the start and allDay. compute allDay if necessary
|
|
5045
|
-
|
|
4829
|
+
calendar.getDefaultEventEnd(
|
|
5046
4830
|
event.allDay != null ?
|
|
5047
4831
|
event.allDay :
|
|
5048
4832
|
!event.start.hasTime(),
|
|
5049
4833
|
event.start
|
|
5050
4834
|
)
|
|
5051
|
-
).stripZone()
|
|
5052
|
-
|
|
4835
|
+
).stripZone();
|
|
4836
|
+
|
|
4837
|
+
// hack: dynamic locale change forgets to upate stored event localed
|
|
4838
|
+
calendar.localizeMoment(start);
|
|
4839
|
+
calendar.localizeMoment(end);
|
|
4840
|
+
|
|
4841
|
+
return { start: start, end: end };
|
|
5053
4842
|
},
|
|
5054
4843
|
|
|
5055
4844
|
|
|
@@ -5152,6 +4941,16 @@ Grid.mixin({
|
|
|
5152
4941
|
----------------------------------------------------------------------------------------------------------------------*/
|
|
5153
4942
|
|
|
5154
4943
|
|
|
4944
|
+
function pluckEventDateProps(event) {
|
|
4945
|
+
return {
|
|
4946
|
+
start: event.start.clone(),
|
|
4947
|
+
end: event.end ? event.end.clone() : null,
|
|
4948
|
+
allDay: event.allDay // keep it the same
|
|
4949
|
+
};
|
|
4950
|
+
}
|
|
4951
|
+
FC.pluckEventDateProps = pluckEventDateProps;
|
|
4952
|
+
|
|
4953
|
+
|
|
5155
4954
|
function isBgEvent(event) { // returns true if background OR inverse-background
|
|
5156
4955
|
var rendering = getEventRendering(event);
|
|
5157
4956
|
return rendering === 'background' || rendering === 'inverse-background';
|
|
@@ -5542,7 +5341,7 @@ var DayTableMixin = FC.DayTableMixin = {
|
|
|
5542
5341
|
|
|
5543
5342
|
return '' +
|
|
5544
5343
|
'<th class="fc-day-header ' + view.widgetHeaderClass + ' fc-' + dayIDs[date.day()] + '"' +
|
|
5545
|
-
(this.rowCnt
|
|
5344
|
+
(this.rowCnt === 1 ?
|
|
5546
5345
|
' data-date="' + date.format('YYYY-MM-DD') + '"' :
|
|
5547
5346
|
'') +
|
|
5548
5347
|
(colspan > 1 ?
|
|
@@ -5551,8 +5350,12 @@ var DayTableMixin = FC.DayTableMixin = {
|
|
|
5551
5350
|
(otherAttrs ?
|
|
5552
5351
|
' ' + otherAttrs :
|
|
5553
5352
|
'') +
|
|
5554
|
-
|
|
5555
|
-
|
|
5353
|
+
'>' +
|
|
5354
|
+
// don't make a link if the heading could represent multiple days, or if there's only one day (forceOff)
|
|
5355
|
+
view.buildGotoAnchorHtml(
|
|
5356
|
+
{ date: date, forceOff: this.rowCnt > 1 || this.colCnt === 1 },
|
|
5357
|
+
htmlEscape(date.format(this.colHeadFormat)) // inner HTML
|
|
5358
|
+
) +
|
|
5556
5359
|
'</th>';
|
|
5557
5360
|
},
|
|
5558
5361
|
|
|
@@ -5781,19 +5584,53 @@ var DayGrid = FC.DayGrid = Grid.extend(DayTableMixin, {
|
|
|
5781
5584
|
// Generates the HTML for the <td>s of the "number" row in the DayGrid's content skeleton.
|
|
5782
5585
|
// The number row will only exist if either day numbers or week numbers are turned on.
|
|
5783
5586
|
renderNumberCellHtml: function(date) {
|
|
5587
|
+
var html = '';
|
|
5784
5588
|
var classes;
|
|
5589
|
+
var weekCalcFirstDoW;
|
|
5785
5590
|
|
|
5786
|
-
if (!this.view.dayNumbersVisible) {
|
|
5591
|
+
if (!this.view.dayNumbersVisible && !this.view.cellWeekNumbersVisible) {
|
|
5592
|
+
// no numbers in day cell (week number must be along the side)
|
|
5787
5593
|
return '<td/>'; // will create an empty space above events :(
|
|
5788
5594
|
}
|
|
5789
5595
|
|
|
5790
5596
|
classes = this.getDayClasses(date);
|
|
5791
|
-
classes.unshift('fc-day-
|
|
5597
|
+
classes.unshift('fc-day-top');
|
|
5792
5598
|
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
'
|
|
5599
|
+
if (this.view.cellWeekNumbersVisible) {
|
|
5600
|
+
// To determine the day of week number change under ISO, we cannot
|
|
5601
|
+
// rely on moment.js methods such as firstDayOfWeek() or weekday(),
|
|
5602
|
+
// because they rely on the locale's dow (possibly overridden by
|
|
5603
|
+
// our firstDay option), which may not be Monday. We cannot change
|
|
5604
|
+
// dow, because that would affect the calendar start day as well.
|
|
5605
|
+
if (date._locale._fullCalendar_weekCalc === 'ISO') {
|
|
5606
|
+
weekCalcFirstDoW = 1; // Monday by ISO 8601 definition
|
|
5607
|
+
}
|
|
5608
|
+
else {
|
|
5609
|
+
weekCalcFirstDoW = date._locale.firstDayOfWeek();
|
|
5610
|
+
}
|
|
5611
|
+
}
|
|
5612
|
+
|
|
5613
|
+
html += '<td class="' + classes.join(' ') + '" data-date="' + date.format() + '">';
|
|
5614
|
+
|
|
5615
|
+
if (this.view.cellWeekNumbersVisible && (date.day() == weekCalcFirstDoW)) {
|
|
5616
|
+
html += this.view.buildGotoAnchorHtml(
|
|
5617
|
+
{ date: date, type: 'week' },
|
|
5618
|
+
{ 'class': 'fc-week-number' },
|
|
5619
|
+
date.format('w') // inner HTML
|
|
5620
|
+
);
|
|
5621
|
+
}
|
|
5622
|
+
|
|
5623
|
+
if (this.view.dayNumbersVisible) {
|
|
5624
|
+
html += this.view.buildGotoAnchorHtml(
|
|
5625
|
+
date,
|
|
5626
|
+
{ 'class': 'fc-day-number' },
|
|
5627
|
+
date.date() // inner HTML
|
|
5628
|
+
);
|
|
5629
|
+
}
|
|
5630
|
+
|
|
5631
|
+
html += '</td>';
|
|
5632
|
+
|
|
5633
|
+
return html;
|
|
5797
5634
|
},
|
|
5798
5635
|
|
|
5799
5636
|
|
|
@@ -6901,7 +6738,6 @@ var TimeGrid = FC.TimeGrid = Grid.extend(DayTableMixin, {
|
|
|
6901
6738
|
|
|
6902
6739
|
this.labelFormat =
|
|
6903
6740
|
input ||
|
|
6904
|
-
view.opt('axisFormat') || // deprecated
|
|
6905
6741
|
view.opt('smallTimeFormat'); // the computed default
|
|
6906
6742
|
|
|
6907
6743
|
input = view.opt('slotLabelInterval');
|
|
@@ -8133,6 +7969,62 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
8133
7969
|
},
|
|
8134
7970
|
|
|
8135
7971
|
|
|
7972
|
+
getAllDayHtml: function() {
|
|
7973
|
+
return this.opt('allDayHtml') || htmlEscape(this.opt('allDayText'));
|
|
7974
|
+
},
|
|
7975
|
+
|
|
7976
|
+
|
|
7977
|
+
/* Navigation
|
|
7978
|
+
------------------------------------------------------------------------------------------------------------------*/
|
|
7979
|
+
|
|
7980
|
+
|
|
7981
|
+
// Generates HTML for an anchor to another view into the calendar.
|
|
7982
|
+
// Will either generate an <a> tag or a non-clickable <span> tag, depending on enabled settings.
|
|
7983
|
+
// `gotoOptions` can either be a moment input, or an object with the form:
|
|
7984
|
+
// { date, type, forceOff }
|
|
7985
|
+
// `type` is a view-type like "day" or "week". default value is "day".
|
|
7986
|
+
// `attrs` and `innerHtml` are use to generate the rest of the HTML tag.
|
|
7987
|
+
buildGotoAnchorHtml: function(gotoOptions, attrs, innerHtml) {
|
|
7988
|
+
var date, type, forceOff;
|
|
7989
|
+
var finalOptions;
|
|
7990
|
+
|
|
7991
|
+
if ($.isPlainObject(gotoOptions)) {
|
|
7992
|
+
date = gotoOptions.date;
|
|
7993
|
+
type = gotoOptions.type;
|
|
7994
|
+
forceOff = gotoOptions.forceOff;
|
|
7995
|
+
}
|
|
7996
|
+
else {
|
|
7997
|
+
date = gotoOptions; // a single moment input
|
|
7998
|
+
}
|
|
7999
|
+
date = FC.moment(date); // if a string, parse it
|
|
8000
|
+
|
|
8001
|
+
finalOptions = { // for serialization into the link
|
|
8002
|
+
date: date.format('YYYY-MM-DD'),
|
|
8003
|
+
type: type || 'day'
|
|
8004
|
+
};
|
|
8005
|
+
|
|
8006
|
+
if (typeof attrs === 'string') {
|
|
8007
|
+
innerHtml = attrs;
|
|
8008
|
+
attrs = null;
|
|
8009
|
+
}
|
|
8010
|
+
|
|
8011
|
+
attrs = attrs ? ' ' + attrsToStr(attrs) : ''; // will have a leading space
|
|
8012
|
+
innerHtml = innerHtml || '';
|
|
8013
|
+
|
|
8014
|
+
if (!forceOff && this.opt('navLinks')) {
|
|
8015
|
+
return '<a' + attrs +
|
|
8016
|
+
' data-goto="' + htmlEscape(JSON.stringify(finalOptions)) + '">' +
|
|
8017
|
+
innerHtml +
|
|
8018
|
+
'</a>';
|
|
8019
|
+
}
|
|
8020
|
+
else {
|
|
8021
|
+
return '<span' + attrs + '>' +
|
|
8022
|
+
innerHtml +
|
|
8023
|
+
'</span>';
|
|
8024
|
+
}
|
|
8025
|
+
},
|
|
8026
|
+
|
|
8027
|
+
|
|
8136
8028
|
/* Rendering
|
|
8137
8029
|
------------------------------------------------------------------------------------------------------------------*/
|
|
8138
8030
|
|
|
@@ -8628,14 +8520,24 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
|
|
|
8628
8520
|
|
|
8629
8521
|
// Computes if the given event is allowed to be dragged by the user
|
|
8630
8522
|
isEventDraggable: function(event) {
|
|
8631
|
-
|
|
8523
|
+
return this.isEventStartEditable(event);
|
|
8524
|
+
},
|
|
8525
|
+
|
|
8632
8526
|
|
|
8527
|
+
isEventStartEditable: function(event) {
|
|
8633
8528
|
return firstDefined(
|
|
8634
8529
|
event.startEditable,
|
|
8635
|
-
source.startEditable,
|
|
8530
|
+
(event.source || {}).startEditable,
|
|
8636
8531
|
this.opt('eventStartEditable'),
|
|
8532
|
+
this.isEventGenerallyEditable(event)
|
|
8533
|
+
);
|
|
8534
|
+
},
|
|
8535
|
+
|
|
8536
|
+
|
|
8537
|
+
isEventGenerallyEditable: function(event) {
|
|
8538
|
+
return firstDefined(
|
|
8637
8539
|
event.editable,
|
|
8638
|
-
source.editable,
|
|
8540
|
+
(event.source || {}).editable,
|
|
8639
8541
|
this.opt('editable')
|
|
8640
8542
|
);
|
|
8641
8543
|
},
|
|
@@ -9135,7 +9037,7 @@ var Scroller = FC.Scroller = Class.extend({
|
|
|
9135
9037
|
var Calendar = FC.Calendar = Class.extend({
|
|
9136
9038
|
|
|
9137
9039
|
dirDefaults: null, // option defaults related to LTR or RTL
|
|
9138
|
-
|
|
9040
|
+
localeDefaults: null, // option defaults related to current locale
|
|
9139
9041
|
overrides: null, // option overrides given to the fullCalendar constructor
|
|
9140
9042
|
dynamicOverrides: null, // options set with dynamic setter method. higher precedence than view overrides.
|
|
9141
9043
|
options: null, // all defaults combined with overrides
|
|
@@ -9158,33 +9060,33 @@ var Calendar = FC.Calendar = Class.extend({
|
|
|
9158
9060
|
// Computes the flattened options hash for the calendar and assigns to `this.options`.
|
|
9159
9061
|
// Assumes this.overrides and this.dynamicOverrides have already been initialized.
|
|
9160
9062
|
populateOptionsHash: function() {
|
|
9161
|
-
var
|
|
9063
|
+
var locale, localeDefaults;
|
|
9162
9064
|
var isRTL, dirDefaults;
|
|
9163
9065
|
|
|
9164
|
-
|
|
9165
|
-
this.dynamicOverrides.
|
|
9166
|
-
this.overrides.
|
|
9066
|
+
locale = firstDefined( // explicit locale option given?
|
|
9067
|
+
this.dynamicOverrides.locale,
|
|
9068
|
+
this.overrides.locale
|
|
9167
9069
|
);
|
|
9168
|
-
|
|
9169
|
-
if (!
|
|
9170
|
-
|
|
9171
|
-
|
|
9070
|
+
localeDefaults = localeOptionHash[locale];
|
|
9071
|
+
if (!localeDefaults) { // explicit locale option not given or invalid?
|
|
9072
|
+
locale = Calendar.defaults.locale;
|
|
9073
|
+
localeDefaults = localeOptionHash[locale] || {};
|
|
9172
9074
|
}
|
|
9173
9075
|
|
|
9174
9076
|
isRTL = firstDefined( // based on options computed so far, is direction RTL?
|
|
9175
9077
|
this.dynamicOverrides.isRTL,
|
|
9176
9078
|
this.overrides.isRTL,
|
|
9177
|
-
|
|
9079
|
+
localeDefaults.isRTL,
|
|
9178
9080
|
Calendar.defaults.isRTL
|
|
9179
9081
|
);
|
|
9180
9082
|
dirDefaults = isRTL ? Calendar.rtlDefaults : {};
|
|
9181
9083
|
|
|
9182
9084
|
this.dirDefaults = dirDefaults;
|
|
9183
|
-
this.
|
|
9085
|
+
this.localeDefaults = localeDefaults;
|
|
9184
9086
|
this.options = mergeOptions([ // merge defaults and overrides. lowest to highest precedence
|
|
9185
9087
|
Calendar.defaults, // global defaults
|
|
9186
9088
|
dirDefaults,
|
|
9187
|
-
|
|
9089
|
+
localeDefaults,
|
|
9188
9090
|
this.overrides,
|
|
9189
9091
|
this.dynamicOverrides
|
|
9190
9092
|
]);
|
|
@@ -9300,7 +9202,7 @@ var Calendar = FC.Calendar = Class.extend({
|
|
|
9300
9202
|
Calendar.defaults, // global defaults
|
|
9301
9203
|
spec.defaults, // view's defaults (from ViewSubclass.defaults)
|
|
9302
9204
|
this.dirDefaults,
|
|
9303
|
-
this.
|
|
9205
|
+
this.localeDefaults, // locale and dir take precedence over view's defaults!
|
|
9304
9206
|
this.overrides, // calendar's overrides (options given to constructor)
|
|
9305
9207
|
spec.overrides, // view's overrides (view-specific options)
|
|
9306
9208
|
this.dynamicOverrides // dynamically set via setter. highest precedence
|
|
@@ -9317,6 +9219,9 @@ var Calendar = FC.Calendar = Class.extend({
|
|
|
9317
9219
|
function queryButtonText(options) {
|
|
9318
9220
|
var buttonText = options.buttonText || {};
|
|
9319
9221
|
return buttonText[requestedViewType] ||
|
|
9222
|
+
// view can decide to look up a certain key
|
|
9223
|
+
(spec.buttonTextKey ? buttonText[spec.buttonTextKey] : null) ||
|
|
9224
|
+
// a key like "month"
|
|
9320
9225
|
(spec.singleUnit ? buttonText[spec.singleUnit] : null);
|
|
9321
9226
|
}
|
|
9322
9227
|
|
|
@@ -9328,7 +9233,7 @@ var Calendar = FC.Calendar = Class.extend({
|
|
|
9328
9233
|
|
|
9329
9234
|
// highest to lowest priority. mirrors buildViewSpecOptions
|
|
9330
9235
|
spec.buttonTextDefault =
|
|
9331
|
-
queryButtonText(this.
|
|
9236
|
+
queryButtonText(this.localeDefaults) ||
|
|
9332
9237
|
queryButtonText(this.dirDefaults) ||
|
|
9333
9238
|
spec.defaults.buttonText || // a single string. from ViewSubclass.defaults
|
|
9334
9239
|
queryButtonText(Calendar.defaults) ||
|
|
@@ -9429,29 +9334,31 @@ function Calendar_constructor(element, overrides) {
|
|
|
9429
9334
|
t.dynamicOverrides = {};
|
|
9430
9335
|
t.viewSpecCache = {};
|
|
9431
9336
|
t.optionHandlers = {}; // for Calendar.options.js
|
|
9432
|
-
|
|
9433
|
-
// convert legacy options into non-legacy ones.
|
|
9434
|
-
// in the future, when this is removed, don't use `overrides` reference. make a copy.
|
|
9435
|
-
t.overrides = massageOverrides(overrides || {});
|
|
9337
|
+
t.overrides = $.extend({}, overrides); // make a copy
|
|
9436
9338
|
|
|
9437
9339
|
t.populateOptionsHash(); // sets this.options
|
|
9438
9340
|
|
|
9439
9341
|
|
|
9440
9342
|
|
|
9441
|
-
//
|
|
9343
|
+
// Locale-data Internals
|
|
9442
9344
|
// -----------------------------------------------------------------------------------
|
|
9443
|
-
// Apply overrides to the current
|
|
9345
|
+
// Apply overrides to the current locale's data
|
|
9444
9346
|
|
|
9445
9347
|
var localeData;
|
|
9446
9348
|
|
|
9447
9349
|
// Called immediately, and when any of the options change.
|
|
9448
9350
|
// Happens before any internal objects rebuild or rerender, because this is very core.
|
|
9449
9351
|
t.bindOptions([
|
|
9450
|
-
'
|
|
9451
|
-
], function(
|
|
9352
|
+
'locale', 'monthNames', 'monthNamesShort', 'dayNames', 'dayNamesShort', 'firstDay', 'weekNumberCalculation'
|
|
9353
|
+
], function(locale, monthNames, monthNamesShort, dayNames, dayNamesShort, firstDay, weekNumberCalculation) {
|
|
9354
|
+
|
|
9355
|
+
// normalize
|
|
9356
|
+
if (weekNumberCalculation === 'iso') {
|
|
9357
|
+
weekNumberCalculation = 'ISO'; // normalize
|
|
9358
|
+
}
|
|
9452
9359
|
|
|
9453
9360
|
localeData = createObject( // make a cheap copy
|
|
9454
|
-
getMomentLocaleData(
|
|
9361
|
+
getMomentLocaleData(locale) // will fall back to en
|
|
9455
9362
|
);
|
|
9456
9363
|
|
|
9457
9364
|
if (monthNames) {
|
|
@@ -9466,15 +9373,16 @@ function Calendar_constructor(element, overrides) {
|
|
|
9466
9373
|
if (dayNamesShort) {
|
|
9467
9374
|
localeData._weekdaysShort = dayNamesShort;
|
|
9468
9375
|
}
|
|
9376
|
+
|
|
9377
|
+
if (firstDay == null && weekNumberCalculation === 'ISO') {
|
|
9378
|
+
firstDay = 1;
|
|
9379
|
+
}
|
|
9469
9380
|
if (firstDay != null) {
|
|
9470
9381
|
var _week = createObject(localeData._week); // _week: { dow: # }
|
|
9471
9382
|
_week.dow = firstDay;
|
|
9472
9383
|
localeData._week = _week;
|
|
9473
9384
|
}
|
|
9474
9385
|
|
|
9475
|
-
if (weekNumberCalculation === 'iso') {
|
|
9476
|
-
weekNumberCalculation = 'ISO'; // normalize
|
|
9477
|
-
}
|
|
9478
9386
|
if ( // whitelist certain kinds of input
|
|
9479
9387
|
weekNumberCalculation === 'ISO' ||
|
|
9480
9388
|
weekNumberCalculation === 'local' ||
|
|
@@ -9491,7 +9399,6 @@ function Calendar_constructor(element, overrides) {
|
|
|
9491
9399
|
});
|
|
9492
9400
|
|
|
9493
9401
|
|
|
9494
|
-
|
|
9495
9402
|
// Calendar-specific Date Utilities
|
|
9496
9403
|
// -----------------------------------------------------------------------------------
|
|
9497
9404
|
|
|
@@ -9500,7 +9407,7 @@ function Calendar_constructor(element, overrides) {
|
|
|
9500
9407
|
t.defaultTimedEventDuration = moment.duration(t.options.defaultTimedEventDuration);
|
|
9501
9408
|
|
|
9502
9409
|
|
|
9503
|
-
// Builds a moment using the settings of the current calendar: timezone and
|
|
9410
|
+
// Builds a moment using the settings of the current calendar: timezone and locale.
|
|
9504
9411
|
// Accepts anything the vanilla moment() constructor accepts.
|
|
9505
9412
|
t.moment = function() {
|
|
9506
9413
|
var mom;
|
|
@@ -9528,13 +9435,9 @@ function Calendar_constructor(element, overrides) {
|
|
|
9528
9435
|
|
|
9529
9436
|
// Updates the given moment's locale settings to the current calendar locale settings.
|
|
9530
9437
|
function localizeMoment(mom) {
|
|
9531
|
-
|
|
9532
|
-
mom._locale = localeData;
|
|
9533
|
-
}
|
|
9534
|
-
else { // pre-moment-2.8
|
|
9535
|
-
mom._lang = localeData;
|
|
9536
|
-
}
|
|
9438
|
+
mom._locale = localeData;
|
|
9537
9439
|
}
|
|
9440
|
+
t.localizeMoment = localizeMoment;
|
|
9538
9441
|
|
|
9539
9442
|
|
|
9540
9443
|
// Returns a boolean about whether or not the calendar knows how to calculate
|
|
@@ -9611,8 +9514,7 @@ function Calendar_constructor(element, overrides) {
|
|
|
9611
9514
|
// Produces a human-readable string for the given duration.
|
|
9612
9515
|
// Side-effect: changes the locale of the given duration.
|
|
9613
9516
|
t.humanizeDuration = function(duration) {
|
|
9614
|
-
return
|
|
9615
|
-
.humanize();
|
|
9517
|
+
return duration.locale(t.options.locale).humanize();
|
|
9616
9518
|
};
|
|
9617
9519
|
|
|
9618
9520
|
|
|
@@ -9674,16 +9576,37 @@ function Calendar_constructor(element, overrides) {
|
|
|
9674
9576
|
function initialRender() {
|
|
9675
9577
|
element.addClass('fc');
|
|
9676
9578
|
|
|
9677
|
-
//
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9579
|
+
// event delegation for nav links
|
|
9580
|
+
element.on('click.fc', 'a[data-goto]', function(ev) {
|
|
9581
|
+
var anchorEl = $(this);
|
|
9582
|
+
var gotoOptions = anchorEl.data('goto'); // will automatically parse JSON
|
|
9583
|
+
var date = t.moment(gotoOptions.date);
|
|
9584
|
+
var viewType = gotoOptions.type;
|
|
9585
|
+
|
|
9586
|
+
// property like "navLinkDayClick". might be a string or a function
|
|
9587
|
+
var customAction = currentView.opt('navLink' + capitaliseFirstLetter(viewType) + 'Click');
|
|
9588
|
+
|
|
9589
|
+
if (typeof customAction === 'function') {
|
|
9590
|
+
customAction(date, ev);
|
|
9591
|
+
}
|
|
9592
|
+
else {
|
|
9593
|
+
if (typeof customAction === 'string') {
|
|
9594
|
+
viewType = customAction;
|
|
9595
|
+
}
|
|
9596
|
+
zoomTo(date, viewType);
|
|
9597
|
+
}
|
|
9598
|
+
});
|
|
9599
|
+
|
|
9600
|
+
// called immediately, and upon option change
|
|
9601
|
+
t.bindOption('theme', function(theme) {
|
|
9602
|
+
tm = theme ? 'ui' : 'fc'; // affects a larger scope
|
|
9603
|
+
element.toggleClass('ui-widget', theme);
|
|
9604
|
+
element.toggleClass('fc-unthemed', !theme);
|
|
9682
9605
|
});
|
|
9683
9606
|
|
|
9684
9607
|
// called immediately, and upon option change.
|
|
9685
|
-
// HACK:
|
|
9686
|
-
t.bindOptions([ 'isRTL', '
|
|
9608
|
+
// HACK: locale often affects isRTL, so we explicitly listen to that too.
|
|
9609
|
+
t.bindOptions([ 'isRTL', 'locale' ], function(isRTL) {
|
|
9687
9610
|
element.toggleClass('fc-ltr', !isRTL);
|
|
9688
9611
|
element.toggleClass('fc-rtl', isRTL);
|
|
9689
9612
|
});
|
|
@@ -9724,6 +9647,8 @@ function Calendar_constructor(element, overrides) {
|
|
|
9724
9647
|
content.remove();
|
|
9725
9648
|
element.removeClass('fc fc-ltr fc-rtl fc-unthemed ui-widget');
|
|
9726
9649
|
|
|
9650
|
+
element.off('.fc'); // unbind nav link handlers
|
|
9651
|
+
|
|
9727
9652
|
if (windowResizeProxy) {
|
|
9728
9653
|
$(window).unbind('resize', windowResizeProxy);
|
|
9729
9654
|
}
|
|
@@ -9772,7 +9697,10 @@ function Calendar_constructor(element, overrides) {
|
|
|
9772
9697
|
// render or rerender the view
|
|
9773
9698
|
if (
|
|
9774
9699
|
!currentView.displaying ||
|
|
9775
|
-
!
|
|
9700
|
+
!( // NOT within interval range signals an implicit date window change
|
|
9701
|
+
date >= currentView.intervalStart &&
|
|
9702
|
+
date < currentView.intervalEnd
|
|
9703
|
+
)
|
|
9776
9704
|
) {
|
|
9777
9705
|
if (elementVisible()) {
|
|
9778
9706
|
|
|
@@ -9971,7 +9899,8 @@ function Calendar_constructor(element, overrides) {
|
|
|
9971
9899
|
|
|
9972
9900
|
function updateTodayButton() {
|
|
9973
9901
|
var now = t.getNow();
|
|
9974
|
-
|
|
9902
|
+
|
|
9903
|
+
if (now >= currentView.intervalStart && now < currentView.intervalEnd) {
|
|
9975
9904
|
header.disableButton('today');
|
|
9976
9905
|
}
|
|
9977
9906
|
else {
|
|
@@ -10258,7 +10187,7 @@ Calendar.mixin({
|
|
|
10258
10187
|
Calendar.defaults = {
|
|
10259
10188
|
|
|
10260
10189
|
titleRangeSeparator: ' \u2013 ', // en dash
|
|
10261
|
-
monthYearFormat: 'MMMM YYYY', // required for en. other
|
|
10190
|
+
monthYearFormat: 'MMMM YYYY', // required for en. other locales rely on datepicker computable option
|
|
10262
10191
|
|
|
10263
10192
|
defaultTimedEventDuration: '02:00:00',
|
|
10264
10193
|
defaultAllDayEventDuration: { days: 1 },
|
|
@@ -10315,6 +10244,8 @@ Calendar.defaults = {
|
|
|
10315
10244
|
prevYear: 'left-double-arrow',
|
|
10316
10245
|
nextYear: 'right-double-arrow'
|
|
10317
10246
|
},
|
|
10247
|
+
|
|
10248
|
+
allDayText: 'all-day',
|
|
10318
10249
|
|
|
10319
10250
|
// jquery-ui theming
|
|
10320
10251
|
theme: false,
|
|
@@ -10350,7 +10281,7 @@ Calendar.defaults = {
|
|
|
10350
10281
|
};
|
|
10351
10282
|
|
|
10352
10283
|
|
|
10353
|
-
Calendar.englishDefaults = { // used by
|
|
10284
|
+
Calendar.englishDefaults = { // used by locale.js
|
|
10354
10285
|
dayPopoverFormat: 'dddd, MMMM D'
|
|
10355
10286
|
};
|
|
10356
10287
|
|
|
@@ -10377,19 +10308,18 @@ Calendar.rtlDefaults = { // right-to-left defaults
|
|
|
10377
10308
|
|
|
10378
10309
|
;;
|
|
10379
10310
|
|
|
10380
|
-
var
|
|
10311
|
+
var localeOptionHash = FC.locales = {}; // initialize and expose
|
|
10381
10312
|
|
|
10382
10313
|
|
|
10383
|
-
// TODO: document the structure and ordering of a FullCalendar
|
|
10384
|
-
// TODO: rename everything "lang" to "locale", like what the moment project did
|
|
10314
|
+
// TODO: document the structure and ordering of a FullCalendar locale file
|
|
10385
10315
|
|
|
10386
10316
|
|
|
10387
10317
|
// Initialize jQuery UI datepicker translations while using some of the translations
|
|
10388
|
-
// Will set this as the default
|
|
10389
|
-
FC.
|
|
10318
|
+
// Will set this as the default locales for datepicker.
|
|
10319
|
+
FC.datepickerLocale = function(localeCode, dpLocaleCode, dpOptions) {
|
|
10390
10320
|
|
|
10391
|
-
// get the FullCalendar internal option hash for this
|
|
10392
|
-
var fcOptions =
|
|
10321
|
+
// get the FullCalendar internal option hash for this locale. create if necessary
|
|
10322
|
+
var fcOptions = localeOptionHash[localeCode] || (localeOptionHash[localeCode] = {});
|
|
10393
10323
|
|
|
10394
10324
|
// transfer some simple options from datepicker to fc
|
|
10395
10325
|
fcOptions.isRTL = dpOptions.isRTL;
|
|
@@ -10403,15 +10333,15 @@ FC.datepickerLang = function(langCode, dpLangCode, dpOptions) {
|
|
|
10403
10333
|
// is jQuery UI Datepicker is on the page?
|
|
10404
10334
|
if ($.datepicker) {
|
|
10405
10335
|
|
|
10406
|
-
// Register the
|
|
10407
|
-
// FullCalendar and MomentJS use
|
|
10408
|
-
// does it like "pt-BR" or if it doesn't have the
|
|
10409
|
-
// Make an alias so the
|
|
10410
|
-
$.datepicker.regional[
|
|
10411
|
-
$.datepicker.regional[
|
|
10336
|
+
// Register the locale data.
|
|
10337
|
+
// FullCalendar and MomentJS use locale codes like "pt-br" but Datepicker
|
|
10338
|
+
// does it like "pt-BR" or if it doesn't have the locale, maybe just "pt".
|
|
10339
|
+
// Make an alias so the locale can be referenced either way.
|
|
10340
|
+
$.datepicker.regional[dpLocaleCode] =
|
|
10341
|
+
$.datepicker.regional[localeCode] = // alias
|
|
10412
10342
|
dpOptions;
|
|
10413
10343
|
|
|
10414
|
-
// Alias 'en' to the default
|
|
10344
|
+
// Alias 'en' to the default locale data. Do this every time.
|
|
10415
10345
|
$.datepicker.regional.en = $.datepicker.regional[''];
|
|
10416
10346
|
|
|
10417
10347
|
// Set as Datepicker's global defaults.
|
|
@@ -10420,35 +10350,35 @@ FC.datepickerLang = function(langCode, dpLangCode, dpOptions) {
|
|
|
10420
10350
|
};
|
|
10421
10351
|
|
|
10422
10352
|
|
|
10423
|
-
// Sets FullCalendar-specific translations. Will set the
|
|
10424
|
-
FC.
|
|
10353
|
+
// Sets FullCalendar-specific translations. Will set the locales as the global default.
|
|
10354
|
+
FC.locale = function(localeCode, newFcOptions) {
|
|
10425
10355
|
var fcOptions;
|
|
10426
10356
|
var momOptions;
|
|
10427
10357
|
|
|
10428
|
-
// get the FullCalendar internal option hash for this
|
|
10429
|
-
fcOptions =
|
|
10358
|
+
// get the FullCalendar internal option hash for this locale. create if necessary
|
|
10359
|
+
fcOptions = localeOptionHash[localeCode] || (localeOptionHash[localeCode] = {});
|
|
10430
10360
|
|
|
10431
|
-
// provided new options for this
|
|
10361
|
+
// provided new options for this locales? merge them in
|
|
10432
10362
|
if (newFcOptions) {
|
|
10433
|
-
fcOptions =
|
|
10363
|
+
fcOptions = localeOptionHash[localeCode] = mergeOptions([ fcOptions, newFcOptions ]);
|
|
10434
10364
|
}
|
|
10435
10365
|
|
|
10436
|
-
// compute
|
|
10366
|
+
// compute locale options that weren't defined.
|
|
10437
10367
|
// always do this. newFcOptions can be undefined when initializing from i18n file,
|
|
10438
10368
|
// so no way to tell if this is an initialization or a default-setting.
|
|
10439
|
-
momOptions = getMomentLocaleData(
|
|
10369
|
+
momOptions = getMomentLocaleData(localeCode); // will fall back to en
|
|
10440
10370
|
$.each(momComputableOptions, function(name, func) {
|
|
10441
10371
|
if (fcOptions[name] == null) {
|
|
10442
10372
|
fcOptions[name] = func(momOptions, fcOptions);
|
|
10443
10373
|
}
|
|
10444
10374
|
});
|
|
10445
10375
|
|
|
10446
|
-
// set it as the default
|
|
10447
|
-
Calendar.defaults.
|
|
10376
|
+
// set it as the default locale for FullCalendar
|
|
10377
|
+
Calendar.defaults.locale = localeCode;
|
|
10448
10378
|
};
|
|
10449
10379
|
|
|
10450
10380
|
|
|
10451
|
-
// NOTE: can't guarantee any of these computations will run because not every
|
|
10381
|
+
// NOTE: can't guarantee any of these computations will run because not every locale has datepicker
|
|
10452
10382
|
// configs, so make sure there are English fallbacks for these in the defaults file.
|
|
10453
10383
|
var dpComputableOptions = {
|
|
10454
10384
|
|
|
@@ -10498,7 +10428,7 @@ var momComputableOptions = {
|
|
|
10498
10428
|
smallTimeFormat: function(momOptions) {
|
|
10499
10429
|
return momOptions.longDateFormat('LT')
|
|
10500
10430
|
.replace(':mm', '(:mm)')
|
|
10501
|
-
.replace(/(\Wmm)$/, '($1)') // like above, but for foreign
|
|
10431
|
+
.replace(/(\Wmm)$/, '($1)') // like above, but for foreign locales
|
|
10502
10432
|
.replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand
|
|
10503
10433
|
},
|
|
10504
10434
|
|
|
@@ -10506,7 +10436,7 @@ var momComputableOptions = {
|
|
|
10506
10436
|
extraSmallTimeFormat: function(momOptions) {
|
|
10507
10437
|
return momOptions.longDateFormat('LT')
|
|
10508
10438
|
.replace(':mm', '(:mm)')
|
|
10509
|
-
.replace(/(\Wmm)$/, '($1)') // like above, but for foreign
|
|
10439
|
+
.replace(/(\Wmm)$/, '($1)') // like above, but for foreign locales
|
|
10510
10440
|
.replace(/\s*a$/i, 't'); // convert to AM/PM/am/pm to lowercase one-letter. remove any spaces beforehand
|
|
10511
10441
|
},
|
|
10512
10442
|
|
|
@@ -10514,7 +10444,7 @@ var momComputableOptions = {
|
|
|
10514
10444
|
hourFormat: function(momOptions) {
|
|
10515
10445
|
return momOptions.longDateFormat('LT')
|
|
10516
10446
|
.replace(':mm', '')
|
|
10517
|
-
.replace(/(\Wmm)$/, '') // like above, but for foreign
|
|
10447
|
+
.replace(/(\Wmm)$/, '') // like above, but for foreign locales
|
|
10518
10448
|
.replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand
|
|
10519
10449
|
},
|
|
10520
10450
|
|
|
@@ -10528,7 +10458,7 @@ var momComputableOptions = {
|
|
|
10528
10458
|
|
|
10529
10459
|
|
|
10530
10460
|
// options that should be computed off live calendar options (considers override options)
|
|
10531
|
-
// TODO: best place for this? related to
|
|
10461
|
+
// TODO: best place for this? related to locale?
|
|
10532
10462
|
// TODO: flipping text based on isRTL is a bad idea because the CSS `direction` might want to handle it
|
|
10533
10463
|
var instanceComputableOptions = {
|
|
10534
10464
|
|
|
@@ -10565,17 +10495,14 @@ function populateInstanceComputableOptions(options) {
|
|
|
10565
10495
|
|
|
10566
10496
|
|
|
10567
10497
|
// Returns moment's internal locale data. If doesn't exist, returns English.
|
|
10568
|
-
|
|
10569
|
-
|
|
10570
|
-
var func = moment.localeData || moment.langData;
|
|
10571
|
-
return func.call(moment, langCode) ||
|
|
10572
|
-
func.call(moment, 'en'); // the newer localData could return null, so fall back to en
|
|
10498
|
+
function getMomentLocaleData(localeCode) {
|
|
10499
|
+
return moment.localeData(localeCode) || moment.localeData('en');
|
|
10573
10500
|
}
|
|
10574
10501
|
|
|
10575
10502
|
|
|
10576
10503
|
// Initialize English by forcing computation of moment-derived options.
|
|
10577
10504
|
// Also, sets it as the default.
|
|
10578
|
-
FC.
|
|
10505
|
+
FC.locale('en', Calendar.englishDefaults);
|
|
10579
10506
|
|
|
10580
10507
|
;;
|
|
10581
10508
|
|
|
@@ -11884,78 +11811,134 @@ function EventManager() { // assumed to be a calendar
|
|
|
11884
11811
|
}
|
|
11885
11812
|
|
|
11886
11813
|
|
|
11887
|
-
|
|
11888
|
-
|
|
11814
|
+
t.getEventCache = function() {
|
|
11815
|
+
return cache;
|
|
11816
|
+
};
|
|
11889
11817
|
|
|
11890
|
-
|
|
11891
|
-
t.isExternalSpanAllowed = isExternalSpanAllowed;
|
|
11892
|
-
t.isSelectionSpanAllowed = isSelectionSpanAllowed;
|
|
11818
|
+
}
|
|
11893
11819
|
|
|
11894
11820
|
|
|
11895
|
-
|
|
11896
|
-
|
|
11897
|
-
|
|
11898
|
-
|
|
11899
|
-
event.constraint,
|
|
11900
|
-
source.constraint,
|
|
11901
|
-
t.options.eventConstraint
|
|
11902
|
-
);
|
|
11903
|
-
var overlap = firstDefined(
|
|
11904
|
-
event.overlap,
|
|
11905
|
-
source.overlap,
|
|
11906
|
-
t.options.eventOverlap
|
|
11907
|
-
);
|
|
11908
|
-
return isSpanAllowed(span, constraint, overlap, event);
|
|
11909
|
-
}
|
|
11821
|
+
// hook for external libs to manipulate event properties upon creation.
|
|
11822
|
+
// should manipulate the event in-place.
|
|
11823
|
+
Calendar.prototype.normalizeEvent = function(event) {
|
|
11824
|
+
};
|
|
11910
11825
|
|
|
11911
11826
|
|
|
11912
|
-
|
|
11913
|
-
|
|
11914
|
-
|
|
11915
|
-
|
|
11827
|
+
// Does the given span (start, end, and other location information)
|
|
11828
|
+
// fully contain the other?
|
|
11829
|
+
Calendar.prototype.spanContainsSpan = function(outerSpan, innerSpan) {
|
|
11830
|
+
var eventStart = outerSpan.start.clone().stripZone();
|
|
11831
|
+
var eventEnd = this.getEventEnd(outerSpan).stripZone();
|
|
11916
11832
|
|
|
11917
|
-
|
|
11918
|
-
|
|
11919
|
-
eventInput = $.extend({}, eventProps, eventLocation);
|
|
11920
|
-
event = expandEvent(buildEventFromInput(eventInput))[0];
|
|
11921
|
-
}
|
|
11833
|
+
return innerSpan.start >= eventStart && innerSpan.end <= eventEnd;
|
|
11834
|
+
};
|
|
11922
11835
|
|
|
11923
|
-
if (event) {
|
|
11924
|
-
return isEventSpanAllowed(eventSpan, event);
|
|
11925
|
-
}
|
|
11926
|
-
else { // treat it as a selection
|
|
11927
11836
|
|
|
11928
|
-
|
|
11837
|
+
// Returns a list of events that the given event should be compared against when being considered for a move to
|
|
11838
|
+
// the specified span. Attached to the Calendar's prototype because EventManager is a mixin for a Calendar.
|
|
11839
|
+
Calendar.prototype.getPeerEvents = function(span, event) {
|
|
11840
|
+
var cache = this.getEventCache();
|
|
11841
|
+
var peerEvents = [];
|
|
11842
|
+
var i, otherEvent;
|
|
11843
|
+
|
|
11844
|
+
for (i = 0; i < cache.length; i++) {
|
|
11845
|
+
otherEvent = cache[i];
|
|
11846
|
+
if (
|
|
11847
|
+
!event ||
|
|
11848
|
+
event._id !== otherEvent._id // don't compare the event to itself or other related [repeating] events
|
|
11849
|
+
) {
|
|
11850
|
+
peerEvents.push(otherEvent);
|
|
11929
11851
|
}
|
|
11930
11852
|
}
|
|
11931
11853
|
|
|
11854
|
+
return peerEvents;
|
|
11855
|
+
};
|
|
11856
|
+
|
|
11857
|
+
|
|
11858
|
+
// updates the "backup" properties, which are preserved in order to compute diffs later on.
|
|
11859
|
+
function backupEventDates(event) {
|
|
11860
|
+
event._allDay = event.allDay;
|
|
11861
|
+
event._start = event.start.clone();
|
|
11862
|
+
event._end = event.end ? event.end.clone() : null;
|
|
11863
|
+
}
|
|
11864
|
+
|
|
11865
|
+
|
|
11866
|
+
/* Overlapping / Constraining
|
|
11867
|
+
-----------------------------------------------------------------------------------------*/
|
|
11868
|
+
|
|
11869
|
+
|
|
11870
|
+
// Determines if the given event can be relocated to the given span (unzoned start/end with other misc data)
|
|
11871
|
+
Calendar.prototype.isEventSpanAllowed = function(span, event) {
|
|
11872
|
+
var source = event.source || {};
|
|
11932
11873
|
|
|
11933
|
-
|
|
11934
|
-
|
|
11935
|
-
|
|
11874
|
+
var constraint = firstDefined(
|
|
11875
|
+
event.constraint,
|
|
11876
|
+
source.constraint,
|
|
11877
|
+
this.options.eventConstraint
|
|
11878
|
+
);
|
|
11879
|
+
|
|
11880
|
+
var overlap = firstDefined(
|
|
11881
|
+
event.overlap,
|
|
11882
|
+
source.overlap,
|
|
11883
|
+
this.options.eventOverlap
|
|
11884
|
+
);
|
|
11885
|
+
|
|
11886
|
+
return this.isSpanAllowed(span, constraint, overlap, event) &&
|
|
11887
|
+
(!this.options.eventAllow || this.options.eventAllow(span, event) !== false);
|
|
11888
|
+
};
|
|
11889
|
+
|
|
11890
|
+
|
|
11891
|
+
// Determines if an external event can be relocated to the given span (unzoned start/end with other misc data)
|
|
11892
|
+
Calendar.prototype.isExternalSpanAllowed = function(eventSpan, eventLocation, eventProps) {
|
|
11893
|
+
var eventInput;
|
|
11894
|
+
var event;
|
|
11895
|
+
|
|
11896
|
+
// note: very similar logic is in View's reportExternalDrop
|
|
11897
|
+
if (eventProps) {
|
|
11898
|
+
eventInput = $.extend({}, eventProps, eventLocation);
|
|
11899
|
+
event = this.expandEvent(
|
|
11900
|
+
this.buildEventFromInput(eventInput)
|
|
11901
|
+
)[0];
|
|
11936
11902
|
}
|
|
11937
11903
|
|
|
11904
|
+
if (event) {
|
|
11905
|
+
return this.isEventSpanAllowed(eventSpan, event);
|
|
11906
|
+
}
|
|
11907
|
+
else { // treat it as a selection
|
|
11938
11908
|
|
|
11939
|
-
|
|
11940
|
-
|
|
11941
|
-
|
|
11942
|
-
|
|
11943
|
-
|
|
11944
|
-
|
|
11945
|
-
|
|
11946
|
-
|
|
11947
|
-
|
|
11909
|
+
return this.isSelectionSpanAllowed(eventSpan);
|
|
11910
|
+
}
|
|
11911
|
+
};
|
|
11912
|
+
|
|
11913
|
+
|
|
11914
|
+
// Determines the given span (unzoned start/end with other misc data) can be selected.
|
|
11915
|
+
Calendar.prototype.isSelectionSpanAllowed = function(span) {
|
|
11916
|
+
return this.isSpanAllowed(span, this.options.selectConstraint, this.options.selectOverlap) &&
|
|
11917
|
+
(!this.options.selectAllow || this.options.selectAllow(span) !== false);
|
|
11918
|
+
};
|
|
11948
11919
|
|
|
11949
|
-
// the range must be fully contained by at least one of produced constraint events
|
|
11950
|
-
if (constraint != null) {
|
|
11951
11920
|
|
|
11952
|
-
|
|
11953
|
-
|
|
11954
|
-
|
|
11921
|
+
// Returns true if the given span (caused by an event drop/resize or a selection) is allowed to exist
|
|
11922
|
+
// according to the constraint/overlap settings.
|
|
11923
|
+
// `event` is not required if checking a selection.
|
|
11924
|
+
Calendar.prototype.isSpanAllowed = function(span, constraint, overlap, event) {
|
|
11925
|
+
var constraintEvents;
|
|
11926
|
+
var anyContainment;
|
|
11927
|
+
var peerEvents;
|
|
11928
|
+
var i, peerEvent;
|
|
11929
|
+
var peerOverlap;
|
|
11930
|
+
|
|
11931
|
+
// the range must be fully contained by at least one of produced constraint events
|
|
11932
|
+
if (constraint != null) {
|
|
11933
|
+
|
|
11934
|
+
// not treated as an event! intermediate data structure
|
|
11935
|
+
// TODO: use ranges in the future
|
|
11936
|
+
constraintEvents = this.constraintToEvents(constraint);
|
|
11937
|
+
if (constraintEvents) { // not invalid
|
|
11955
11938
|
|
|
11956
11939
|
anyContainment = false;
|
|
11957
11940
|
for (i = 0; i < constraintEvents.length; i++) {
|
|
11958
|
-
if (
|
|
11941
|
+
if (this.spanContainsSpan(constraintEvents[i], span)) {
|
|
11959
11942
|
anyContainment = true;
|
|
11960
11943
|
break;
|
|
11961
11944
|
}
|
|
@@ -11965,127 +11948,81 @@ function EventManager() { // assumed to be a calendar
|
|
|
11965
11948
|
return false;
|
|
11966
11949
|
}
|
|
11967
11950
|
}
|
|
11951
|
+
}
|
|
11968
11952
|
|
|
11969
|
-
|
|
11953
|
+
peerEvents = this.getPeerEvents(span, event);
|
|
11970
11954
|
|
|
11971
|
-
|
|
11972
|
-
|
|
11955
|
+
for (i = 0; i < peerEvents.length; i++) {
|
|
11956
|
+
peerEvent = peerEvents[i];
|
|
11973
11957
|
|
|
11974
|
-
|
|
11975
|
-
|
|
11958
|
+
// there needs to be an actual intersection before disallowing anything
|
|
11959
|
+
if (this.eventIntersectsRange(peerEvent, span)) {
|
|
11960
|
+
|
|
11961
|
+
// evaluate overlap for the given range and short-circuit if necessary
|
|
11962
|
+
if (overlap === false) {
|
|
11963
|
+
return false;
|
|
11964
|
+
}
|
|
11965
|
+
// if the event's overlap is a test function, pass the peer event in question as the first param
|
|
11966
|
+
else if (typeof overlap === 'function' && !overlap(peerEvent, event)) {
|
|
11967
|
+
return false;
|
|
11968
|
+
}
|
|
11976
11969
|
|
|
11977
|
-
|
|
11978
|
-
|
|
11970
|
+
// if we are computing if the given range is allowable for an event, consider the other event's
|
|
11971
|
+
// EventObject-specific or Source-specific `overlap` property
|
|
11972
|
+
if (event) {
|
|
11973
|
+
peerOverlap = firstDefined(
|
|
11974
|
+
peerEvent.overlap,
|
|
11975
|
+
(peerEvent.source || {}).overlap
|
|
11976
|
+
// we already considered the global `eventOverlap`
|
|
11977
|
+
);
|
|
11978
|
+
if (peerOverlap === false) {
|
|
11979
11979
|
return false;
|
|
11980
11980
|
}
|
|
11981
|
-
// if the event's overlap is a test function, pass the
|
|
11982
|
-
|
|
11981
|
+
// if the peer event's overlap is a test function, pass the subject event as the first param
|
|
11982
|
+
if (typeof peerOverlap === 'function' && !peerOverlap(event, peerEvent)) {
|
|
11983
11983
|
return false;
|
|
11984
11984
|
}
|
|
11985
|
-
|
|
11986
|
-
// if we are computing if the given range is allowable for an event, consider the other event's
|
|
11987
|
-
// EventObject-specific or Source-specific `overlap` property
|
|
11988
|
-
if (event) {
|
|
11989
|
-
peerOverlap = firstDefined(
|
|
11990
|
-
peerEvent.overlap,
|
|
11991
|
-
(peerEvent.source || {}).overlap
|
|
11992
|
-
// we already considered the global `eventOverlap`
|
|
11993
|
-
);
|
|
11994
|
-
if (peerOverlap === false) {
|
|
11995
|
-
return false;
|
|
11996
|
-
}
|
|
11997
|
-
// if the peer event's overlap is a test function, pass the subject event as the first param
|
|
11998
|
-
if (typeof peerOverlap === 'function' && !peerOverlap(event, peerEvent)) {
|
|
11999
|
-
return false;
|
|
12000
|
-
}
|
|
12001
|
-
}
|
|
12002
11985
|
}
|
|
12003
11986
|
}
|
|
12004
|
-
|
|
12005
|
-
return true;
|
|
12006
11987
|
}
|
|
12007
11988
|
|
|
11989
|
+
return true;
|
|
11990
|
+
};
|
|
12008
11991
|
|
|
12009
|
-
// Given an event input from the API, produces an array of event objects. Possible event inputs:
|
|
12010
|
-
// 'businessHours'
|
|
12011
|
-
// An event ID (number or string)
|
|
12012
|
-
// An object with specific start/end dates or a recurring event (like what businessHours accepts)
|
|
12013
|
-
function constraintToEvents(constraintInput) {
|
|
12014
|
-
|
|
12015
|
-
if (constraintInput === 'businessHours') {
|
|
12016
|
-
return t.getCurrentBusinessHourEvents();
|
|
12017
|
-
}
|
|
12018
11992
|
|
|
12019
|
-
|
|
12020
|
-
|
|
12021
|
-
|
|
11993
|
+
// Given an event input from the API, produces an array of event objects. Possible event inputs:
|
|
11994
|
+
// 'businessHours'
|
|
11995
|
+
// An event ID (number or string)
|
|
11996
|
+
// An object with specific start/end dates or a recurring event (like what businessHours accepts)
|
|
11997
|
+
Calendar.prototype.constraintToEvents = function(constraintInput) {
|
|
12022
11998
|
|
|
12023
|
-
|
|
11999
|
+
if (constraintInput === 'businessHours') {
|
|
12000
|
+
return this.getCurrentBusinessHourEvents();
|
|
12024
12001
|
}
|
|
12025
12002
|
|
|
12026
|
-
|
|
12027
|
-
|
|
12028
|
-
|
|
12029
|
-
|
|
12030
|
-
|
|
12031
|
-
|
|
12032
|
-
|
|
12033
|
-
return range.start < eventEnd && range.end > eventStart;
|
|
12003
|
+
if (typeof constraintInput === 'object') {
|
|
12004
|
+
if (constraintInput.start != null) { // needs to be event-like input
|
|
12005
|
+
return this.expandEvent(this.buildEventFromInput(constraintInput));
|
|
12006
|
+
}
|
|
12007
|
+
else {
|
|
12008
|
+
return null; // invalid
|
|
12009
|
+
}
|
|
12034
12010
|
}
|
|
12035
12011
|
|
|
12036
|
-
|
|
12037
|
-
t.getEventCache = function() {
|
|
12038
|
-
return cache;
|
|
12039
|
-
};
|
|
12040
|
-
|
|
12041
|
-
}
|
|
12042
|
-
|
|
12043
|
-
|
|
12044
|
-
// hook for external libs to manipulate event properties upon creation.
|
|
12045
|
-
// should manipulate the event in-place.
|
|
12046
|
-
Calendar.prototype.normalizeEvent = function(event) {
|
|
12047
|
-
};
|
|
12048
|
-
|
|
12049
|
-
|
|
12050
|
-
// Does the given span (start, end, and other location information)
|
|
12051
|
-
// fully contain the other?
|
|
12052
|
-
Calendar.prototype.spanContainsSpan = function(outerSpan, innerSpan) {
|
|
12053
|
-
var eventStart = outerSpan.start.clone().stripZone();
|
|
12054
|
-
var eventEnd = this.getEventEnd(outerSpan).stripZone();
|
|
12055
|
-
|
|
12056
|
-
return innerSpan.start >= eventStart && innerSpan.end <= eventEnd;
|
|
12012
|
+
return this.clientEvents(constraintInput); // probably an ID
|
|
12057
12013
|
};
|
|
12058
12014
|
|
|
12059
12015
|
|
|
12060
|
-
//
|
|
12061
|
-
//
|
|
12062
|
-
Calendar.prototype.
|
|
12063
|
-
var
|
|
12064
|
-
var
|
|
12065
|
-
var i, otherEvent;
|
|
12066
|
-
|
|
12067
|
-
for (i = 0; i < cache.length; i++) {
|
|
12068
|
-
otherEvent = cache[i];
|
|
12069
|
-
if (
|
|
12070
|
-
!event ||
|
|
12071
|
-
event._id !== otherEvent._id // don't compare the event to itself or other related [repeating] events
|
|
12072
|
-
) {
|
|
12073
|
-
peerEvents.push(otherEvent);
|
|
12074
|
-
}
|
|
12075
|
-
}
|
|
12016
|
+
// Does the event's date range intersect with the given range?
|
|
12017
|
+
// start/end already assumed to have stripped zones :(
|
|
12018
|
+
Calendar.prototype.eventIntersectsRange = function(event, range) {
|
|
12019
|
+
var eventStart = event.start.clone().stripZone();
|
|
12020
|
+
var eventEnd = this.getEventEnd(event).stripZone();
|
|
12076
12021
|
|
|
12077
|
-
return
|
|
12022
|
+
return range.start < eventEnd && range.end > eventStart;
|
|
12078
12023
|
};
|
|
12079
12024
|
|
|
12080
12025
|
|
|
12081
|
-
// updates the "backup" properties, which are preserved in order to compute diffs later on.
|
|
12082
|
-
function backupEventDates(event) {
|
|
12083
|
-
event._allDay = event.allDay;
|
|
12084
|
-
event._start = event.start.clone();
|
|
12085
|
-
event._end = event.end ? event.end.clone() : null;
|
|
12086
|
-
}
|
|
12087
|
-
|
|
12088
|
-
|
|
12089
12026
|
/* Business Hours
|
|
12090
12027
|
-----------------------------------------------------------------------------------------*/
|
|
12091
12028
|
|
|
@@ -12170,7 +12107,8 @@ var BasicView = FC.BasicView = View.extend({
|
|
|
12170
12107
|
dayGrid: null, // the main subcomponent that does most of the heavy lifting
|
|
12171
12108
|
|
|
12172
12109
|
dayNumbersVisible: false, // display day numbers on each day cell?
|
|
12173
|
-
|
|
12110
|
+
colWeekNumbersVisible: false, // display week numbers along the side?
|
|
12111
|
+
cellWeekNumbersVisible: false, // display week numbers in day cell?
|
|
12174
12112
|
|
|
12175
12113
|
weekNumberWidth: null, // width of all the week-number cells running down the side
|
|
12176
12114
|
|
|
@@ -12231,8 +12169,18 @@ var BasicView = FC.BasicView = View.extend({
|
|
|
12231
12169
|
renderDates: function() {
|
|
12232
12170
|
|
|
12233
12171
|
this.dayNumbersVisible = this.dayGrid.rowCnt > 1; // TODO: make grid responsible
|
|
12234
|
-
|
|
12235
|
-
|
|
12172
|
+
if (this.opt('weekNumbers')) {
|
|
12173
|
+
if (this.opt('weekNumbersWithinDays')) {
|
|
12174
|
+
this.cellWeekNumbersVisible = true;
|
|
12175
|
+
this.colWeekNumbersVisible = false;
|
|
12176
|
+
}
|
|
12177
|
+
else {
|
|
12178
|
+
this.cellWeekNumbersVisible = false;
|
|
12179
|
+
this.colWeekNumbersVisible = true;
|
|
12180
|
+
};
|
|
12181
|
+
}
|
|
12182
|
+
this.dayGrid.numbersVisible = this.dayNumbersVisible ||
|
|
12183
|
+
this.cellWeekNumbersVisible || this.colWeekNumbersVisible;
|
|
12236
12184
|
|
|
12237
12185
|
this.el.addClass('fc-basic-view').html(this.renderSkeletonHtml());
|
|
12238
12186
|
this.renderHead();
|
|
@@ -12316,7 +12264,7 @@ var BasicView = FC.BasicView = View.extend({
|
|
|
12316
12264
|
|
|
12317
12265
|
// Refreshes the horizontal dimensions of the view
|
|
12318
12266
|
updateWidth: function() {
|
|
12319
|
-
if (this.
|
|
12267
|
+
if (this.colWeekNumbersVisible) {
|
|
12320
12268
|
// Make sure all week number cells running down the side have the same width.
|
|
12321
12269
|
// Record the width for cells created later.
|
|
12322
12270
|
this.weekNumberWidth = matchCellWidths(
|
|
@@ -12457,9 +12405,8 @@ var BasicView = FC.BasicView = View.extend({
|
|
|
12457
12405
|
unrenderEvents: function() {
|
|
12458
12406
|
this.dayGrid.unrenderEvents();
|
|
12459
12407
|
|
|
12460
|
-
// we DON'T need to call updateHeight() because
|
|
12461
|
-
//
|
|
12462
|
-
// B) in IE8, this causes a flash whenever events are rerendered
|
|
12408
|
+
// we DON'T need to call updateHeight() because
|
|
12409
|
+
// a renderEvents() call always happens after this, which will eventually call updateHeight()
|
|
12463
12410
|
},
|
|
12464
12411
|
|
|
12465
12412
|
|
|
@@ -12504,7 +12451,7 @@ var basicDayGridMethods = {
|
|
|
12504
12451
|
renderHeadIntroHtml: function() {
|
|
12505
12452
|
var view = this.view;
|
|
12506
12453
|
|
|
12507
|
-
if (view.
|
|
12454
|
+
if (view.colWeekNumbersVisible) {
|
|
12508
12455
|
return '' +
|
|
12509
12456
|
'<th class="fc-week-number ' + view.widgetHeaderClass + '" ' + view.weekNumberStyleAttr() + '>' +
|
|
12510
12457
|
'<span>' + // needed for matchCellWidths
|
|
@@ -12520,13 +12467,15 @@ var basicDayGridMethods = {
|
|
|
12520
12467
|
// Generates the HTML that will go before content-skeleton cells that display the day/week numbers
|
|
12521
12468
|
renderNumberIntroHtml: function(row) {
|
|
12522
12469
|
var view = this.view;
|
|
12470
|
+
var weekStart = this.getCellDate(row, 0);
|
|
12523
12471
|
|
|
12524
|
-
if (view.
|
|
12472
|
+
if (view.colWeekNumbersVisible) {
|
|
12525
12473
|
return '' +
|
|
12526
12474
|
'<td class="fc-week-number" ' + view.weekNumberStyleAttr() + '>' +
|
|
12527
|
-
|
|
12528
|
-
|
|
12529
|
-
|
|
12475
|
+
view.buildGotoAnchorHtml( // aside from link, important for matchCellWidths
|
|
12476
|
+
{ date: weekStart, type: 'week', forceOff: this.colCnt === 1 },
|
|
12477
|
+
weekStart.format('w') // inner HTML
|
|
12478
|
+
) +
|
|
12530
12479
|
'</td>';
|
|
12531
12480
|
}
|
|
12532
12481
|
|
|
@@ -12538,7 +12487,7 @@ var basicDayGridMethods = {
|
|
|
12538
12487
|
renderBgIntroHtml: function() {
|
|
12539
12488
|
var view = this.view;
|
|
12540
12489
|
|
|
12541
|
-
if (view.
|
|
12490
|
+
if (view.colWeekNumbersVisible) {
|
|
12542
12491
|
return '<td class="fc-week-number ' + view.widgetContentClass + '" ' +
|
|
12543
12492
|
view.weekNumberStyleAttr() + '></td>';
|
|
12544
12493
|
}
|
|
@@ -12552,7 +12501,7 @@ var basicDayGridMethods = {
|
|
|
12552
12501
|
renderIntroHtml: function() {
|
|
12553
12502
|
var view = this.view;
|
|
12554
12503
|
|
|
12555
|
-
if (view.
|
|
12504
|
+
if (view.colWeekNumbersVisible) {
|
|
12556
12505
|
return '<td class="fc-week-number" ' + view.weekNumberStyleAttr() + '></td>';
|
|
12557
12506
|
}
|
|
12558
12507
|
|
|
@@ -12586,8 +12535,6 @@ var MonthView = FC.MonthView = BasicView.extend({
|
|
|
12586
12535
|
// Overrides the default BasicView behavior to have special multi-week auto-height logic
|
|
12587
12536
|
setGridHeight: function(height, isAuto) {
|
|
12588
12537
|
|
|
12589
|
-
isAuto = isAuto || this.opt('weekMode') === 'variable'; // LEGACY: weekMode is deprecated
|
|
12590
|
-
|
|
12591
12538
|
// if auto, make the height of each row the height that it would be if there were 6 weeks
|
|
12592
12539
|
if (isAuto) {
|
|
12593
12540
|
height *= this.rowCnt / 6;
|
|
@@ -12598,11 +12545,6 @@ var MonthView = FC.MonthView = BasicView.extend({
|
|
|
12598
12545
|
|
|
12599
12546
|
|
|
12600
12547
|
isFixedWeeks: function() {
|
|
12601
|
-
var weekMode = this.opt('weekMode'); // LEGACY: weekMode is deprecated
|
|
12602
|
-
if (weekMode) {
|
|
12603
|
-
return weekMode === 'fixed'; // if any other type of weekMode, assume NOT fixed
|
|
12604
|
-
}
|
|
12605
|
-
|
|
12606
12548
|
return this.opt('fixedWeekCount');
|
|
12607
12549
|
}
|
|
12608
12550
|
|
|
@@ -13032,9 +12974,8 @@ var AgendaView = FC.AgendaView = View.extend({
|
|
|
13032
12974
|
this.dayGrid.unrenderEvents();
|
|
13033
12975
|
}
|
|
13034
12976
|
|
|
13035
|
-
// we DON'T need to call updateHeight() because
|
|
13036
|
-
//
|
|
13037
|
-
// B) in IE8, this causes a flash whenever events are rerendered
|
|
12977
|
+
// we DON'T need to call updateHeight() because
|
|
12978
|
+
// a renderEvents() call always happens after this, which will eventually call updateHeight()
|
|
13038
12979
|
},
|
|
13039
12980
|
|
|
13040
12981
|
|
|
@@ -13102,9 +13043,10 @@ var agendaTimeGridMethods = {
|
|
|
13102
13043
|
|
|
13103
13044
|
return '' +
|
|
13104
13045
|
'<th class="fc-axis fc-week-number ' + view.widgetHeaderClass + '" ' + view.axisStyleAttr() + '>' +
|
|
13105
|
-
|
|
13106
|
-
|
|
13107
|
-
|
|
13046
|
+
view.buildGotoAnchorHtml( // aside from link, important for matchCellWidths
|
|
13047
|
+
{ date: this.start, type: 'week', forceOff: this.colCnt > 1 },
|
|
13048
|
+
htmlEscape(weekText) // inner HTML
|
|
13049
|
+
) +
|
|
13108
13050
|
'</th>';
|
|
13109
13051
|
}
|
|
13110
13052
|
else {
|
|
@@ -13143,7 +13085,7 @@ var agendaDayGridMethods = {
|
|
|
13143
13085
|
return '' +
|
|
13144
13086
|
'<td class="fc-axis ' + view.widgetContentClass + '" ' + view.axisStyleAttr() + '>' +
|
|
13145
13087
|
'<span>' + // needed for matchCellWidths
|
|
13146
|
-
|
|
13088
|
+
view.getAllDayHtml() +
|
|
13147
13089
|
'</span>' +
|
|
13148
13090
|
'</td>';
|
|
13149
13091
|
},
|
|
@@ -13177,7 +13119,6 @@ fcViews.agenda = {
|
|
|
13177
13119
|
'class': AgendaView,
|
|
13178
13120
|
defaults: {
|
|
13179
13121
|
allDaySlot: true,
|
|
13180
|
-
allDayText: 'all-day',
|
|
13181
13122
|
slotDuration: '00:30:00',
|
|
13182
13123
|
minTime: '00:00:00',
|
|
13183
13124
|
maxTime: '24:00:00',
|
|
@@ -13195,6 +13136,294 @@ fcViews.agendaWeek = {
|
|
|
13195
13136
|
duration: { weeks: 1 }
|
|
13196
13137
|
};
|
|
13197
13138
|
;;
|
|
13139
|
+
|
|
13140
|
+
/*
|
|
13141
|
+
Responsible for the scroller, and forwarding event-related actions into the "grid"
|
|
13142
|
+
*/
|
|
13143
|
+
var ListView = View.extend({
|
|
13144
|
+
|
|
13145
|
+
grid: null,
|
|
13146
|
+
scroller: null,
|
|
13147
|
+
|
|
13148
|
+
initialize: function() {
|
|
13149
|
+
this.grid = new ListViewGrid(this);
|
|
13150
|
+
this.scroller = new Scroller({
|
|
13151
|
+
overflowX: 'hidden',
|
|
13152
|
+
overflowY: 'auto'
|
|
13153
|
+
});
|
|
13154
|
+
},
|
|
13155
|
+
|
|
13156
|
+
setRange: function(range) {
|
|
13157
|
+
View.prototype.setRange.call(this, range); // super
|
|
13158
|
+
|
|
13159
|
+
this.grid.setRange(range); // needs to process range-related options
|
|
13160
|
+
},
|
|
13161
|
+
|
|
13162
|
+
renderSkeleton: function() {
|
|
13163
|
+
this.el.addClass(
|
|
13164
|
+
'fc-list-view ' +
|
|
13165
|
+
this.widgetContentClass
|
|
13166
|
+
);
|
|
13167
|
+
|
|
13168
|
+
this.scroller.render();
|
|
13169
|
+
this.scroller.el.appendTo(this.el);
|
|
13170
|
+
|
|
13171
|
+
this.grid.setElement(this.scroller.scrollEl);
|
|
13172
|
+
},
|
|
13173
|
+
|
|
13174
|
+
unrenderSkeleton: function() {
|
|
13175
|
+
this.scroller.destroy(); // will remove the Grid too
|
|
13176
|
+
},
|
|
13177
|
+
|
|
13178
|
+
setHeight: function(totalHeight, isAuto) {
|
|
13179
|
+
this.scroller.setHeight(this.computeScrollerHeight(totalHeight));
|
|
13180
|
+
},
|
|
13181
|
+
|
|
13182
|
+
computeScrollerHeight: function(totalHeight) {
|
|
13183
|
+
return totalHeight -
|
|
13184
|
+
subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
|
|
13185
|
+
},
|
|
13186
|
+
|
|
13187
|
+
renderEvents: function(events) {
|
|
13188
|
+
this.grid.renderEvents(events);
|
|
13189
|
+
},
|
|
13190
|
+
|
|
13191
|
+
unrenderEvents: function() {
|
|
13192
|
+
this.grid.unrenderEvents();
|
|
13193
|
+
},
|
|
13194
|
+
|
|
13195
|
+
isEventResizable: function(event) {
|
|
13196
|
+
return false;
|
|
13197
|
+
},
|
|
13198
|
+
|
|
13199
|
+
isEventDraggable: function(event) {
|
|
13200
|
+
return false;
|
|
13201
|
+
}
|
|
13202
|
+
|
|
13203
|
+
});
|
|
13204
|
+
|
|
13205
|
+
/*
|
|
13206
|
+
Responsible for event rendering and user-interaction.
|
|
13207
|
+
Its "el" is the inner-content of the above view's scroller.
|
|
13208
|
+
*/
|
|
13209
|
+
var ListViewGrid = Grid.extend({
|
|
13210
|
+
|
|
13211
|
+
segSelector: '.fc-list-item', // which elements accept event actions
|
|
13212
|
+
hasDayInteractions: false, // no day selection or day clicking
|
|
13213
|
+
|
|
13214
|
+
// slices by day
|
|
13215
|
+
spanToSegs: function(span) {
|
|
13216
|
+
var view = this.view;
|
|
13217
|
+
var dayStart = view.start.clone();
|
|
13218
|
+
var dayEnd;
|
|
13219
|
+
var seg;
|
|
13220
|
+
var segs = [];
|
|
13221
|
+
|
|
13222
|
+
while (dayStart < view.end) {
|
|
13223
|
+
dayEnd = dayStart.clone().add(1, 'day');
|
|
13224
|
+
seg = intersectRanges(span, {
|
|
13225
|
+
start: dayStart,
|
|
13226
|
+
end: dayEnd
|
|
13227
|
+
});
|
|
13228
|
+
if (seg) {
|
|
13229
|
+
segs.push(seg);
|
|
13230
|
+
}
|
|
13231
|
+
dayStart = dayEnd;
|
|
13232
|
+
}
|
|
13233
|
+
|
|
13234
|
+
return segs;
|
|
13235
|
+
},
|
|
13236
|
+
|
|
13237
|
+
// like "4:00am"
|
|
13238
|
+
computeEventTimeFormat: function() {
|
|
13239
|
+
return this.view.opt('mediumTimeFormat');
|
|
13240
|
+
},
|
|
13241
|
+
|
|
13242
|
+
// for events with a url, the whole <tr> should be clickable,
|
|
13243
|
+
// but it's impossible to wrap with an <a> tag. simulate this.
|
|
13244
|
+
handleSegClick: function(seg, ev) {
|
|
13245
|
+
var url;
|
|
13246
|
+
|
|
13247
|
+
Grid.prototype.handleSegClick.apply(this, arguments); // super. might prevent the default action
|
|
13248
|
+
|
|
13249
|
+
// not clicking on or within an <a> with an href
|
|
13250
|
+
if (!$(ev.target).closest('a[href]').length) {
|
|
13251
|
+
url = seg.event.url;
|
|
13252
|
+
if (url && !ev.isDefaultPrevented()) { // jsEvent not cancelled in handler
|
|
13253
|
+
window.location.href = url; // simulate link click
|
|
13254
|
+
}
|
|
13255
|
+
}
|
|
13256
|
+
},
|
|
13257
|
+
|
|
13258
|
+
// returns list of foreground segs that were actually rendered
|
|
13259
|
+
renderFgSegs: function(segs) {
|
|
13260
|
+
segs = this.renderFgSegEls(segs); // might filter away hidden events
|
|
13261
|
+
|
|
13262
|
+
if (!segs.length) {
|
|
13263
|
+
this.renderEmptyMessage();
|
|
13264
|
+
return segs;
|
|
13265
|
+
}
|
|
13266
|
+
else {
|
|
13267
|
+
return this.renderSegList(segs);
|
|
13268
|
+
}
|
|
13269
|
+
},
|
|
13270
|
+
|
|
13271
|
+
renderEmptyMessage: function() {
|
|
13272
|
+
this.el.html(
|
|
13273
|
+
'<div class="fc-list-empty-wrap2">' + // TODO: try less wraps
|
|
13274
|
+
'<div class="fc-list-empty-wrap1">' +
|
|
13275
|
+
'<div class="fc-list-empty">' +
|
|
13276
|
+
htmlEscape(this.view.opt('noEventsMessage')) +
|
|
13277
|
+
'</div>' +
|
|
13278
|
+
'</div>' +
|
|
13279
|
+
'</div>'
|
|
13280
|
+
);
|
|
13281
|
+
},
|
|
13282
|
+
|
|
13283
|
+
// render the event segments in the view. returns the mutated array.
|
|
13284
|
+
renderSegList: function(segs) {
|
|
13285
|
+
var tableEl = $('<table class="fc-list-table"><tbody/></table>');
|
|
13286
|
+
var tbodyEl = tableEl.find('tbody');
|
|
13287
|
+
var i, seg;
|
|
13288
|
+
var dayDate;
|
|
13289
|
+
|
|
13290
|
+
this.sortEventSegs(segs);
|
|
13291
|
+
|
|
13292
|
+
for (i = 0; i < segs.length; i++) {
|
|
13293
|
+
seg = segs[i];
|
|
13294
|
+
|
|
13295
|
+
// append a day header
|
|
13296
|
+
if (!dayDate || !seg.start.isSame(dayDate, 'day')) {
|
|
13297
|
+
dayDate = seg.start.clone().stripTime();
|
|
13298
|
+
tbodyEl.append(this.dayHeaderHtml(dayDate));
|
|
13299
|
+
}
|
|
13300
|
+
|
|
13301
|
+
tbodyEl.append(seg.el); // append event row
|
|
13302
|
+
}
|
|
13303
|
+
|
|
13304
|
+
this.el.empty().append(tableEl);
|
|
13305
|
+
|
|
13306
|
+
return segs; // return the sorted list
|
|
13307
|
+
},
|
|
13308
|
+
|
|
13309
|
+
// generates the HTML for the day headers that live amongst the event rows
|
|
13310
|
+
dayHeaderHtml: function(dayDate) {
|
|
13311
|
+
var view = this.view;
|
|
13312
|
+
var mainFormat = view.opt('listDayFormat');
|
|
13313
|
+
var altFormat = view.opt('listDayAltFormat');
|
|
13314
|
+
|
|
13315
|
+
return '<tr class="fc-list-heading" data-date="' + dayDate.format('YYYY-MM-DD') + '">' +
|
|
13316
|
+
'<td class="' + view.widgetHeaderClass + '" colspan="3">' +
|
|
13317
|
+
(mainFormat ?
|
|
13318
|
+
view.buildGotoAnchorHtml(
|
|
13319
|
+
dayDate,
|
|
13320
|
+
{ 'class': 'fc-list-heading-main' },
|
|
13321
|
+
htmlEscape(dayDate.format(mainFormat)) // inner HTML
|
|
13322
|
+
) :
|
|
13323
|
+
'') +
|
|
13324
|
+
(altFormat ?
|
|
13325
|
+
view.buildGotoAnchorHtml(
|
|
13326
|
+
dayDate,
|
|
13327
|
+
{ 'class': 'fc-list-heading-alt' },
|
|
13328
|
+
htmlEscape(dayDate.format(altFormat)) // inner HTML
|
|
13329
|
+
) :
|
|
13330
|
+
'') +
|
|
13331
|
+
'</td>' +
|
|
13332
|
+
'</tr>';
|
|
13333
|
+
},
|
|
13334
|
+
|
|
13335
|
+
// generates the HTML for a single event row
|
|
13336
|
+
fgSegHtml: function(seg) {
|
|
13337
|
+
var view = this.view;
|
|
13338
|
+
var classes = [ 'fc-list-item' ].concat(this.getSegCustomClasses(seg));
|
|
13339
|
+
var bgColor = this.getSegBackgroundColor(seg);
|
|
13340
|
+
var event = seg.event;
|
|
13341
|
+
var url = event.url;
|
|
13342
|
+
var timeHtml;
|
|
13343
|
+
|
|
13344
|
+
if (!seg.start.hasTime()) {
|
|
13345
|
+
if (this.displayEventTime) {
|
|
13346
|
+
timeHtml = view.getAllDayHtml();
|
|
13347
|
+
}
|
|
13348
|
+
}
|
|
13349
|
+
else {
|
|
13350
|
+
timeHtml = htmlEscape(this.getEventTimeText(event)); // might return empty
|
|
13351
|
+
}
|
|
13352
|
+
|
|
13353
|
+
if (url) {
|
|
13354
|
+
classes.push('fc-has-url');
|
|
13355
|
+
}
|
|
13356
|
+
|
|
13357
|
+
return '<tr class="' + classes.join(' ') + '">' +
|
|
13358
|
+
(timeHtml ?
|
|
13359
|
+
'<td class="fc-list-item-time ' + view.widgetContentClass + '">' +
|
|
13360
|
+
timeHtml +
|
|
13361
|
+
'</td>' :
|
|
13362
|
+
'') +
|
|
13363
|
+
'<td class="fc-list-item-marker ' + view.widgetContentClass + '">' +
|
|
13364
|
+
'<span class="fc-event-dot"' +
|
|
13365
|
+
(bgColor ?
|
|
13366
|
+
' style="background-color:' + bgColor + '"' :
|
|
13367
|
+
'') +
|
|
13368
|
+
'></span>' +
|
|
13369
|
+
'</td>' +
|
|
13370
|
+
'<td class="fc-list-item-title ' + view.widgetContentClass + '">' +
|
|
13371
|
+
'<a' + (url ? ' href="' + htmlEscape(url) + '"' : '') + '>' +
|
|
13372
|
+
htmlEscape(seg.event.title) +
|
|
13373
|
+
'</a>' +
|
|
13374
|
+
'</td>' +
|
|
13375
|
+
'</tr>';
|
|
13376
|
+
}
|
|
13377
|
+
|
|
13378
|
+
});
|
|
13379
|
+
|
|
13380
|
+
;;
|
|
13381
|
+
|
|
13382
|
+
fcViews.list = {
|
|
13383
|
+
'class': ListView,
|
|
13384
|
+
buttonTextKey: 'list', // what to lookup in locale files
|
|
13385
|
+
defaults: {
|
|
13386
|
+
buttonText: 'list', // text to display for English
|
|
13387
|
+
listTime: true, // show the time column?
|
|
13388
|
+
listDayFormat: 'LL', // like "January 1, 2016"
|
|
13389
|
+
noEventsMessage: 'No events to display'
|
|
13390
|
+
}
|
|
13391
|
+
};
|
|
13392
|
+
|
|
13393
|
+
fcViews.listDay = {
|
|
13394
|
+
type: 'list',
|
|
13395
|
+
duration: { days: 1 },
|
|
13396
|
+
defaults: {
|
|
13397
|
+
listDayFormat: 'dddd' // day-of-week is all we need. full date is probably in header
|
|
13398
|
+
}
|
|
13399
|
+
};
|
|
13400
|
+
|
|
13401
|
+
fcViews.listWeek = {
|
|
13402
|
+
type: 'list',
|
|
13403
|
+
duration: { weeks: 1 },
|
|
13404
|
+
defaults: {
|
|
13405
|
+
listDayFormat: 'dddd', // day-of-week is more important
|
|
13406
|
+
listDayAltFormat: 'LL'
|
|
13407
|
+
}
|
|
13408
|
+
};
|
|
13409
|
+
|
|
13410
|
+
fcViews.listMonth = {
|
|
13411
|
+
type: 'list',
|
|
13412
|
+
duration: { month: 1 },
|
|
13413
|
+
defaults: {
|
|
13414
|
+
listDayAltFormat: 'dddd' // day-of-week is nice-to-have
|
|
13415
|
+
}
|
|
13416
|
+
};
|
|
13417
|
+
|
|
13418
|
+
fcViews.listYear = {
|
|
13419
|
+
type: 'list',
|
|
13420
|
+
duration: { year: 1 },
|
|
13421
|
+
defaults: {
|
|
13422
|
+
listDayAltFormat: 'dddd' // day-of-week is nice-to-have
|
|
13423
|
+
}
|
|
13424
|
+
};
|
|
13425
|
+
|
|
13426
|
+
;;
|
|
13198
13427
|
|
|
13199
13428
|
return FC; // export for Node/CommonJS
|
|
13200
13429
|
});
|