PageSourceSearch

https://www.os3.nl/lib/exe/js.php?t=website&tseed=161997d80947c4edd60fb9761c9583c7

js os3.nl collected 2026-09-24 19:28:34 UTC 1,142,200 bytes, 30,523 lines download raw bytes

1var DOKU_BASE   = '/';var DOKU_TPL    = '/lib/tpl/website/';var DOKU_COOKIE_PARAM = {"path":"\/","secure":true};Object.defineProperty(window, 'DOKU_UHN', { get: function() {console.warn('Using DOKU_UHN is deprecated. Please use JSINFO.useHeadingNavigation instead');return JSINFO.useHeadingNavigation; } });Object.defineProperty(window, 'DOKU_UHC', { get: function() {console.warn('Using DOKU_UHC is deprecated. Please use JSINFO.useHeadingContent instead');return JSINFO.useHeadingContent; } });LANG = {"search_toggle_tools":"Toggle Search Tools","willexpire":"Your lock for editing this page is about to expire in a minute.\\nTo avoid conflicts use the preview button to reset the locktimer.","notsavedyet":"Unsaved changes will be lost.","searchmedia":"Search for files","keepopen":"Keep window open on selection","hidedetails":"Hide Details","mediatitle":"Link settings","mediadisplay":"Link type","mediaalign":"Alignment","mediasize":"Image size","mediatarget":"Link target","mediaclose":"Close","mediainsert":"Insert","mediadisplayimg":"Show the image.","mediadisplaylnk":"Show only the link.","mediasmall":"Small version","mediamedium":"Medium version","medialarge":"Large version","mediaoriginal":"Original version","medialnk":"Link to detail page","mediadirect":"Direct link to original","medianolnk":"No link","medianolink":"Do not link the image","medialeft":"Align the image on the left.","mediaright":"Align the image on the right.","mediacenter":"Align the image in the middle.","medianoalign":"Use no align.","nosmblinks":"Linking to Windows shares only works in Microsoft Internet Explorer.\\nYou still can copy and paste the link.","linkwiz":"Link Wizard","linkto":"Link to:","del_confirm":"Really delete selected item(s)?","restore_confirm":"Really restore this version?","media_diff":"View differences:","media_diff_both":"Side by Side","media_diff_opacity":"Shine-through","media_diff_portions":"Swipe","media_select":"Select files\u2026","media_upload_btn":"Upload","media_done_btn":"Done","media_drop":"Drop files here to upload","media_cancel":"remove","media_overwrt":"Overwrite existing files","data_insecure":"WARNING: It seems your data directory is not properly secured. Please read about <a href=\"https:\/\/www.dokuwiki.org\/security#web_access_security\">Web Access Security in DokuWiki<\/a>.","plugins":{"davcal":{"create_new_event":"Create new Event","cancel":"Cancel","create":"Create","save":"Save","settings":"Settings","edit":"Edit","delete":"Delete","edit_event":"Edit Event","allday":"All Day Event","title":"Title","location":"Location","from":"From","to":"To","yes":"Yes","confirmation":"Confirmation","ok":"OK","info":"Info","really_delete_this_event":"Really delete this event?","timezone":"Timezone","weeknumbers":"Week Numbers","use_lang_tz":"Use Timezone from language setting","only_workweek":"Show only Work Week","sync_url":"CalDAV URL","error_retrieving_data":"There was an error retrieving data from the calendar server.","start_date_invalid":"Start date\/time is invalid.","end_date_invalid":"End date\/time is invalid.","end_date_before_start_date":"End date\/time is before start date\/time.","end_date_is_same_as_start_date":"End date\/time is equal to start date\/time.","description":"Description","private_url":"Private URL","recurring_cant_edit":"Editing recurring events is currently not supported","no_permission":"You don't have permission to modify this calendar","calendar":"Calendar","start_monday":"Week starts on Monday","nothing_to_show":"Nothing to show","add_attachment":"Add link","attachments":"Attached links","language_specific":"Language specific","sync_ical":"iCal Sync URL","timeformat":"Time Format"},"extension":{"reallydel":"Really uninstall this extension?","display_viewoptions":"View Options:","display_enabled":"enabled","display_disabled":"disabled","display_updatable":"updatable"},"logviewer":{"filter":"Filter Loglines:"},"overlay":{"fix_title":"Enable overlay to move with page","unfix_title":"Enable overlay to float freely","detach":"Detach","attach":"Attach","absolute":"Detach","fixed":"Attach"},"styling":{"loader":"Preview is loading...<br \/>if this does not goes away, your values may be faulty","popup":"Open as a popup"}}};
2var toolbar = [{"type":"format","title":"Bold Text","icon":"bold.png","key":"b","open":"**","close":"**","block":false},{"type":"format","title":"Italic Text","icon":"italic.png","key":"i","open":"\/\/","close":"\/\/","block":false},{"type":"format","title":"Underlined Text","icon":"underline.png","key":"u","open":"__","close":"__","block":false},{"type":"format","title":"Monospaced Text","icon":"mono.png","key":"m","open":"''","close":"''","block":false},{"type":"format","title":"Strike-through Text","icon":"strike.png","key":"d","open":"<del>","close":"<\/del>","block":false},{"type":"autohead","title":"Same Level Headline","icon":"hequal.png","key":"8","text":"Headline","mod":0,"block":true},{"type":"autohead","title":"Lower Headline","icon":"hminus.png","key":"9","text":"Headline","mod":1,"block":true},{"type":"autohead","title":"Higher Headline","icon":"hplus.png","key":"0","text":"Headline","mod":-1,"block":true},{"type":"picker","title":"Select Headline","icon":"h.png","class":"pk_hl","list":[{"type":"format","title":"Level 1 Headline","icon":"h1.png","key":"1","open":"====== ","close":" ======\\n"},{"type":"format","title":"Level 2 Headline","icon":"h2.png","key":"2","open":"===== ","close":" =====\\n"},{"type":"format","title":"Level 3 Headline","icon":"h3.png","key":"3","open":"==== ","close":" ====\\n"},{"type":"format","title":"Level 4 Headline","icon":"h4.png","key":"4","open":"=== ","close":" ===\\n"},{"type":"format","title":"Level 5 Headline","icon":"h5.png","key":"5","open":"== ","close":" ==\\n"}],"block":true},{"type":"linkwiz","title":"Internal Link","icon":"link.png","key":"l","open":"[[","close":"]]","block":false},{"type":"format","title":"External Link","icon":"linkextern.png","open":"[[","close":"]]","sample":"http:\/\/example.com|External Link","block":false},{"type":"formatln","title":"Ordered List Item","icon":"ol.png","open":"  - ","close":"","key":"-","block":true},{"type":"formatln","title":"Unordered List Item","icon":"ul.png","open":"  * ","close":"","key":".","block":true},{"type":"insert","title":"Horizontal Rule","icon":"hr.png","insert":"\\n----\\n","block":true},{"type":"mediapopup","title":"Add Images and other files (opens in a new window)","icon":"image.png","url":"lib\/exe\/mediamanager.php?ns=","name":"mediaselect","options":"width=750,height=500,left=20,top=20,scrollbars=yes,resizable=yes","block":false},{"type":"picker","title":"Smileys","icon":"smiley.png","list":{"8-)":"cool.svg","8-O":"eek.svg","8-o":"eek.svg",":-(":"sad.svg",":-)":"smile.svg","=)":"smile2.svg",":-\/":"doubt.svg",":-\\":"doubt2.svg",":-?":"confused.svg",":-D":"biggrin.svg",":-P":"razz.svg",":-o":"surprised.svg",":-O":"surprised.svg",":-x":"silenced.svg",":-X":"silenced.svg",":-|":"neutral.svg",";-)":"wink.svg","m(":"facepalm.svg","^_^":"fun.svg",":?:":"question.svg",":!:":"exclaim.svg","LOL":"lol.svg","FIXME":"fixme.svg","DELETEME":"deleteme.svg"},"icobase":"smileys","block":false},{"type":"picker","title":"Special Chars","icon":"chars.png","list":["\u00c0","\u00e0","\u00c1","\u00e1","\u00c2","\u00e2","\u00c3","\u00e3","\u00c4","\u00e4","\u01cd","\u01ce","\u0102","\u0103","\u00c5","\u00e5","\u0100","\u0101","\u0104","\u0105","\u00c6","\u00e6","\u0106","\u0107","\u00c7","\u00e7","\u010c","\u010d","\u0108","\u0109","\u010a","\u010b","\u00d0","\u0111","\u00f0","\u010e","\u010f","\u00c8","\u00e8","\u00c9","\u00e9","\u00ca","\u00ea","\u00cb","\u00eb","\u011a","\u011b","\u0112","\u0113","\u0116","\u0117","\u0118","\u0119","\u0122","\u0123","\u011c","\u011d","\u011e","\u011f","\u0120","\u0121","\u0124","\u0125","\u00cc","\u00ec","\u00cd","\u00ed","\u00ce","\u00ee","\u00cf","\u00ef","\u01cf","\u01d0","\u012a","\u012b","\u0130","\u0131","\u012e","\u012f","\u0134","\u0135","\u0136","\u0137","\u0139","\u013a","\u013b","\u013c","\u013d","\u013e","\u0141","\u0142","\u013f","\u0140","\u0143","\u0144","\u00d1","\u00f1","\u0145","\u0146","\u0147","\u0148","\u00d2","\u00f2","\u00d3","\u00f3","\u00d4","\u00f4","\u00d5","\u00f5","\u00d6","\u00f6","\u01d1","\u01d2","\u014c","\u014d","\u0150","\u0151","\u0152","\u0153","\u00d8","\u00f8","\u0154","\u0155","\u0156","\u0157","\u0158","\u0159","\u015a","\u015b","\u015e","\u015f","\u0160","\u0161","\u015c","\u015d","\u0162","\u0163","\u0164","\u0165","\u00d9","\u00f9","\u00da","\u00fa","\u00db","\u00fb","\u00dc","\u00fc","\u01d3","\u01d4","\u016c","\u016d","\u016a","\u016b","\u016e","\u016f","\u01d6","\u01d8","\u01da","\u01dc","\u0172","\u0173","\u0170","\u0171","\u0174","\u0175","\u00dd","\u00fd","\u0178","\u00ff","\u0176","\u0177","\u0179","\u017a","\u017d","\u017e","\u017b","\u017c","\u00de","\u00fe","\u00df","\u0126","\u0127","\u00bf","\u00a1","\u00a2","\u00a3","\u00a4","\u00a5","\u20ac","\u00a6","\u00a7","\u00aa","\u00ac","\u00af","\u00b0","\u00b1","\u00f7","\u2030","\u00bc","\u00bd","\u00be","\u00b9","\u00b2","\u00b3","\u00b5","\u00b6","\u2020","\u2021","\u00b7","\u2022","\u00ba","\u2200","\u2202","\u2203","\u018f","\u0259","\u2205","\u2207","\u2208","\u2209","\u220b","\u220f","\u2211","\u203e","\u2212","\u2217","\u00d7","\u2044","\u221a","\u221d","\u221e","\u2220","\u2227","\u2228","\u2229","\u222a","\u222b","\u2234","\u223c","\u2245","\u2248","\u2260","\u2261","\u2264","\u2265","\u2282","\u2283","\u2284","\u2286","\u2287","\u2295","\u2297","\u22a5","\u22c5","\u25ca","\u2118","\u2111","\u211c","\u2135","\u2660","\u2663","\u2665","\u2666","\u03b1","\u03b2","\u0393","\u03b3","\u0394","\u03b4","\u03b5","\u03b6","\u03b7","\u0398","\u03b8","\u03b9","\u03ba","\u039b","\u03bb","\u03bc","\u039e","\u03be","\u03a0","\u03c0","\u03c1","\u03a3","\u03c3","\u03a4","\u03c4","\u03c5","\u03a6","\u03c6","\u03c7","\u03a8","\u03c8","\u03a9","\u03c9","\u2605","\u2606","\u260e","\u261a","\u261b","\u261c","\u261d","\u261e","\u261f","\u2639","\u263a","\u2714","\u2718","\u201e","\u201c","\u201d","\u201a","\u2018","\u2019","\u00ab","\u00bb","\u2039","\u203a","\u2014","\u2013","\u2026","\u2190","\u2191","\u2192","\u2193","\u2194","\u21d0","\u21d1","\u21d2","\u21d3","\u21d4","\u00a9","\u2122","\u00ae","\u2032","\u2033","[","]","{","}","~","(",")","%","\u00a7","$","#","|","@"],"block":false},{"type":"signature","title":"Insert Signature","icon":"sig.png","key":"y","block":false},{"type":"picker","title":"Wrap Plugin","icon":"..\/..\/plugins\/wrap\/images\/toolbar\/picker.png","list":[{"type":"format","t
2itle":"columns","icon":"..\/..\/plugins\/wrap\/images\/toolbar\/column.png","open":"<WRAP group>\\n<WRAP half column>\\n","close":"\\n<\/WRAP>\\n\\n<WRAP half column>\\n\\n<\/WRAP>\\n<\/WRAP>\\n"},{"type":"format","title":"simple centered box","icon":"..\/..\/plugins\/wrap\/images\/toolbar\/box.png","open":"<WRAP center round box 60%>\\n","close":"\\n<\/WRAP>\\n"},{"type":"format","title":"info box","icon":"..\/..\/plugins\/wrap\/images\/note\/16\/info.png","open":"<WRAP center round info 60%>\\n","close":"\\n<\/WRAP>\\n"},{"type":"format","title":"tip box","icon":"..\/..\/plugins\/wrap\/images\/note\/16\/tip.png","open":"<WRAP center round tip 60%>\\n","close":"\\n<\/WRAP>\\n"},{"type":"format","title":"important box","icon":"..\/..\/plugins\/wrap\/images\/note\/16\/important.png","open":"<WRAP center round important 60%>\\n","close":"\\n<\/WRAP>\\n"},{"type":"format","title":"alert box","icon":"..\/..\/plugins\/wrap\/images\/note\/16\/alert.png","open":"<WRAP center round alert 60%>\\n","close":"\\n<\/WRAP>\\n"},{"type":"format","title":"help box","icon":"..\/..\/plugins\/wrap\/images\/note\/16\/help.png","open":"<WRAP center round help 60%>\\n","close":"\\n<\/WRAP>\\n"},{"type":"format","title":"download box","icon":"..\/..\/plugins\/wrap\/images\/note\/16\/download.png","open":"<WRAP center round download 60%>\\n","close":"\\n<\/WRAP>\\n"},{"type":"format","title":"todo box","icon":"..\/..\/plugins\/wrap\/images\/note\/16\/todo.png","open":"<WRAP center round todo 60%>\\n","close":"\\n<\/WRAP>\\n"},{"type":"insert","title":"clear floats","icon":"..\/..\/plugins\/wrap\/images\/toolbar\/clear.png","insert":"<WRAP clear\/>\\n"},{"type":"format","title":"especially emphasised","icon":"..\/..\/plugins\/wrap\/images\/toolbar\/em.png","open":"<wrap em>","close":"<\/wrap>"},{"type":"format","title":"highlighted","icon":"..\/..\/plugins\/wrap\/images\/toolbar\/hi.png","open":"<wrap hi>","close":"<\/wrap>"},{"type":"format","title":"less significant","icon":"..\/..\/plugins\/wrap\/images\/toolbar\/lo.png","open":"<wrap lo>","close":"<\/wrap>"}]}];
3
4
5/* XXXXXXXXXX begin of /usr/share/javascript/jquery-cookie/jquery.cookie.js XXXXXXXXXX */
6
7/*!
8 * jQuery Cookie Plugin v1.4.1
9 * https://github.com/carhartl/jquery-cookie
10 *
11 * Copyright 2013 Klaus Hartl
12 * Released under the MIT license
13 */
14(function (factory) {
15	if (typeof define === 'function' && define.amd) {
16		// AMD
17		define(['jquery'], factory);
18	} else if (typeof exports === 'object') {
19		// CommonJS
20		factory(require('jquery'));
21	} else {
22		// Browser globals
23		factory(jQuery);
24	}
25}(function ($) {
26
27	var pluses = /\+/g;
28
29	function encode(s) {
30		return config.raw ? s : encodeURIComponent(s);
31	}
32
33	function decode(s) {
34		return config.raw ? s : decodeURIComponent(s);
35	}
36
37	function stringifyCookieValue(value) {
38		return encode(config.json ? JSON.stringify(value) : String(value));
39	}
40
41	function parseCookieValue(s) {
42		if (s.indexOf('"') === 0) {
43			// This is a quoted cookie as according to RFC2068, unescape...
44			s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
45		}
46
47		try {
48			// Replace server-side written pluses with spaces.
49			// If we can't decode the cookie, ignore it, it's unusable.
50			// If we can't parse the cookie, ignore it, it's unusable.
51			s = decodeURIComponent(s.replace(pluses, ' '));
52			return config.json ? JSON.parse(s) : s;
53		} catch(e) {}
54	}
55
56	function read(s, converter) {
57		var value = config.raw ? s : parseCookieValue(s);
58		return $.isFunction(converter) ? converter(value) : value;
59	}
60
61	var config = $.cookie = function (key, value, options) {
62
63		// Write
64
65		if (value !== undefined && !$.isFunction(value)) {
66			options = $.extend({}, config.defaults, options);
67
68			if (typeof options.expires === 'number') {
69				var days = options.expires, t = options.expires = new Date();
70				t.setTime(+t + days * 864e+5);
71			}
72
73			return (document.cookie = [
74				encode(key), '=', stringifyCookieValue(value),
75				options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
76				options.path    ? '; path=' + options.path : '',
77				options.domain  ? '; domain=' + options.domain : '',
78				options.secure  ? '; secure' : ''
79			].join(''));
80		}
81
82		// Read
83
84		var result = key ? undefined : {};
85
86		// To prevent the for loop in the first place assign an empty array
87		// in case there are no cookies at all. Also prevents odd result when
88		// calling $.cookie().
89		var cookies = document.cookie ? document.cookie.split('; ') : [];
90
91		for (var i = 0, l = cookies.length; i < l; i++) {
92			var parts = cookies[i].split('=');
93			var name = decode(parts.shift());
94			var cookie = parts.join('=');
95
96			if (key && key === name) {
97				// If second argument (value) is a function it's a converter...
98				result = read(cookie, value);
99				break;
100			}
101
102			// Prevent storing a cookie that we couldn't decode.
103			if (!key && (cookie = read(cookie)) !== undefined) {
104				result[name] = cookie;
105			}
106		}
107
108		return result;
109	};
110
111	config.defaults = {};
112
113	$.removeCookie = function (key, options) {
114		if ($.cookie(key) === undefined) {
115			return false;
116		}
117
118		// Must not alter options, thus extending a fresh object...
119		$.cookie(key, '', $.extend({}, options, { expires: -1 }));
120		return !$.cookie(key);
121	};
122
123}));
124
125
126
127/* XXXXXXXXXX end of /usr/share/javascript/jquery-cookie/jquery.cookie.js XXXXXXXXXX */
128
129
130
131/* XXXXXXXXXX begin of lib/scripts/fileuploader.js XXXXXXXXXX */
132
133/**
134 * http://github.com/valums/file-uploader
135 *
136 * Multiple file upload component with progress-bar, drag-and-drop.
137 * © 2010 Andrew Valums ( andrew(at)valums.com )
138 *
139 * Licensed under GNU GPL 2 or later and GNU LGPL 2 or later, see license.txt.
140 */
141
142//
143// Helper functions
144//
145
146var qq = qq || {};
147
148/**
149 * Adds all missing properties from second obj to first obj
150 */
151qq.extend = function(first, second){
152    for (var prop in second){
153        first[prop] = second[prop];
154    }
155};
156
157/**
158 * Searches for a given element in the array, returns -1 if it is not present.
159 * @param {Number} [from] The index at which to begin the search
160 */
161qq.indexOf = function(arr, elt, from){
162    if (arr.indexOf) return arr.indexOf(elt, from);
163
164    from = from || 0;
165    var len = arr.length;
166
167    if (from < 0) from += len;
168
169    for (; from < len; from++){
170        if (from in arr && arr[from] === elt){
171            return from;
172        }
173    }
174    return -1;
175};
176
177qq.getUniqueId = (function(){
178    var id = 0;
179    return function(){ return id++; };
180})();
181
182//
183// Events
184
185qq.attach = function(element, type, fn){
186    if (element.addEventListener){
187        element.addEventListener(type, fn, false);
188    } else if (element.attachEvent){
189        element.attachEvent('on' + type, fn);
190    }
191};
192qq.detach = function(element, type, fn){
193    if (element.removeEventListener){
194        element.removeEventListener(type, fn, false);
195    } else if (element.attachEvent){
196        element.detachEvent('on' + type, fn);
197    }
198};
199
200qq.preventDefault = function(e){
201    if (e.preventDefault){
202        e.preventDefault();
203    } else{
204        e.returnValue = false;
205    }
206};
207
208//
209// Node manipulations
210
211/**
212 * Insert node a before node b.
213 */
214qq.insertBefore = function(a, b){
215    b.parentNode.insertBefore(a, b);
216};
217qq.remove = function(element){
218    element.parentNode.removeChild(element);
219};
220
221qq.contains = function(parent, descendant){
222    // compareposition returns false in this case
223    if (parent == descendant) return true;
224
225    if (parent.contains){
226        return parent.contains(descendant);
227    } else {
228        return !!(descendant.compareDocumentPosition(parent) & 8);
229    }
230};
231
232/**
233 * Creates and returns element from html string
234 * Uses innerHTML to create an element
235 */
236qq.toElement = (function(){
237    var div = document.createElement('div');
238    return function(html){
239        div.innerHTML = html;
240        var element = div.firstChild;
241        div.removeChild(element);
242        return element;
243    };
244})();
245
246//
247// Node properties and attributes
248
249/**
250 * Sets styles for an element.
251 * Fixes opacity in IE6-8.
252 */
253qq.css = function(element, styles){
254    if (styles.opacity != null){
255        if (typeof element.style.opacity != 'string' && typeof(element.filters) != 'undefined'){
256            styles.filter = 'alpha(opacity=' + Math.round(100 * styles.opacity) + ')';
257        }
258    }
259    qq.extend(element.style, styles);
260};
261qq.hasClass = function(element, name){
262    var re = new RegExp('(^| )' + name + '( |$)');
263    return re.test(element.className);
264};
265qq.addClass = function(element, name){
266    if (!qq.hasClass(element, name)){
267        element.className += ' ' + name;
268    }
269};
270qq.removeClass = function(element, name){
271    var re = new RegExp('(^| )' + name + '( |$)');
272    element.className = element.className.replace(re, ' ').replace(/^\s+|\s+$/g, "");
273};
274qq.setText = function(element, text){
275    element.innerText = text;
276    element.textContent = text;
277};
278
279//
280// Selecting elements
281
282qq.children = function(element){
283    var children = [],
284    child = element.firstChild;
285
286    while (child){
287        if (child.nodeType == 1){
288            children.push(child);
289        }
290        child = child.nextSibling;
291    }
292
293    return children;
294};
295
296qq.getByClass = function(element, className){
297    if (element.querySelectorAll){
298        return element.querySelectorAll('.' + className);
299    }
300
301    var result = [];
302    var candidates = element.getElementsByTagName("*");
303    var len = candidates.length;
304
305    for (var i = 0; i < len; i++){
306        if (qq.hasClass(candidates[i], className)){
307            result.push(candidates[i]);
308        }
309    }
310    return result;
311};
312
313/**
314 * obj2url() takes a json-object as argument and generates
315 * a querystring. pretty much like jQuery.param()
316 *
317 * how to use:
318 *
319 *    `qq.obj2url({a:'b',c:'d'},'http://any.url/upload?otherParam=value');`
320 *
321 * will result in:
322 *
323 *    `http://any.url/upload?otherParam=value&a=b&c=d`
324 *
325 * @param  Object JSON-Object
326 * @param  String current querystring-part
327 * @return String encoded querystring
328 */
329qq.obj2url = function(obj, temp, prefixDone){
330    var uristrings = [],
331        prefix = '&',
332        add = function(nextObj, i){
333            var nextTemp = temp
334                ? (/\[\]$/.test(temp)) // prevent double-encoding
335                   ? temp
336                   : temp+'['+i+']'
337                : i;
338            if ((nextTemp != 'undefined') && (i != 'undefined')) {
339                uristrings.push(
340                    (typeof nextObj === 'object')
341                        ? qq.obj2url(nextObj, nextTemp, true)
342                        : (Object.prototype.toString.call(nextObj) === '[object Function]')
343                            ? encodeURIComponent(nextTemp) + '=' + encodeURIComponent(nextObj())
344                            : encodeURIComponent(nextTemp) + '=' + encodeURIComponent(nextObj)
345                );
346            }
347        };
348
349    if (!prefixDone && temp) {
350      prefix = (/\?/.test(temp)) ? (/\?$/.test(temp)) ? '' : '&' : '?';
351      uristrings.push(temp);
352      uristrings.push(qq.obj2url(obj));
353    } else if ((Object.prototype.toString.call(obj) === '[object Array]') && (typeof obj != 'undefined') ) {
354        // we wont use a for-in-loop on an array (performance)
355        for (var i = 0, len = obj.length; i < len; ++i){
356            add(obj[i], i);
357        }
358    } else if ((typeof obj != 'undefined') && (obj !== null) && (typeof obj === "object")){
359        // for anything else but a scalar, we will use for-in-loop
360        for (var i in obj){
361            if(obj.hasOwnProperty(i) && typeof obj[i] != 'function') {
362                add(obj[i], i);
363            }
364        }
365    } else {
366        uristrings.push(encodeURIComponent(temp) + '=' + encodeURIComponent(obj));
367    }
368
369    return uristrings.join(prefix)
370                     .replace(/^&/, '')
371                     .replace(/%20/g, '+');
372};
373
374//
375//
376// Uploader Classes
377//
378//
379
380var qq = qq || {};
381
382/**
383 * Creates upload button, validates upload, but doesn't create file list or dd.
384 */
385qq.FileUploaderBasic = function(o){
386    this._options = {
387        // set to true to see the server response
388        debug: false,
389        action: '/server/upload',
390        params: {},
391        button: null,
392        multiple: true,
393        maxConnections: 3,
394        // validation
395        allowedExtensions: [],
396        sizeLimit: 0,
397        minSizeLimit: 0,
398        // events
399        // return false to cancel submit
400        onSubmit: function(id, fileName){},
401        onProgress: function(id, fileName, loaded, total){},
402        onComplete: function(id, fileName, responseJSON){},
403        onCancel: function(id, fileName){},
404        // messages
405        messages: {
406            typeError: "{file} has invalid extension. Only {extensions} are allowed.",
407            sizeError: "{file} is too large, maximum file size is {sizeLimit}.",
408            minSizeError: "{file} is too small, minimum file size is {minSizeLimit}.",
409            emptyError: "{file} is empty, please select files again without it.",
410            onLeave: "The files are being uploaded, if you leave now the upload will be cancelled."
411        },
412        showMessage: function(message){
413            alert(message);
414        }
415    };
416    qq.extend(this._options, o);
417
418    // number of files being uploaded
419    this._filesInProgress = 0;
420    this._handler = this._createUploadHandler();
421
422    if (this._options.button){
423        this._button = this._createUploadButton(this._options.button);
424    }
425
426    this._preventLeaveInProgress();
427};
428
429qq.FileUploaderBasic.prototype = {
430    setParams: function(params){
431        this._options.params = params;
432    },
433    getInProgress: function(){
434        return this._filesInProgress;
435    },
436    _createUploadButton: function(element){
437        var self = this;
438
439        return new qq.UploadButton({
440            element: element,
441            multiple: this._options.multiple && qq.UploadHandlerXhr.isSupported(),
442            onChange: function(input){
443                self._onInputChange(input);
444            }
445        });
446    },
447    _createUploadHandler: function(){
448        var self = this,
449            handlerClass;
450
451        if(qq.UploadHandlerXhr.isSupported()){
452            handlerClass = 'UploadHandlerXhr';
453        } else {
454            handlerClass = 'UploadHandlerForm';
455        }
456
457        var handler = new qq[handlerClass]({
458            debug: this._options.debug,
459            action: this._options.action,
460            maxConnections: this._options.maxConnections,
461            onProgress: function(id, fileName, loaded, total){
462                self._onProgress(id, fileName, loaded, total);
463                self._options.onProgress(id, fileName, loaded, total);
464            },
465            onComplete: function(id, fileName, result){
466                self._onComplete(id, fileName, result);
467                self._options.onComplete(id, fileName, result);
468            },
469            onCancel: function(id, fileName){
470                self._onCancel(id, fileName);
471                self._options.onCancel(id, fileName);
472            }
473        });
474
475        return handler;
476    },
477    _preventLeaveInProgress: function(){
478        var self = this;
479
480        qq.attach(window, 'beforeunload', function(e){
481            if (!self._filesInProgress){return;}
482
483            var e = e || window.event;
484            // for ie, ff
485            e.returnValue = self._options.messages.onLeave;
486            // for webkit
487            return self._options.messages.onLeave;
488        });
489    },
490    _onSubmit: function(id, fileName){
491        this._filesInProgress++;
492    },
493    _onProgress: function(id, fileName, loaded, total){
494    },
495    _onComplete: function(id, fileName, result){
496        this._filesInProgress--;
497        if (result.error){
498            this._options.showMessage(result.error);
499        }
500    },
501    _onCancel: function(id, fileName){
502        this._filesInProgress--;
503    },
504    _onInputChange: function(input){
505        if (this._handler instanceof qq.UploadHandlerXhr){
506            this._uploadFileList(input.files);
507        } else {
508            if (this._validateFile(input)){
509                this._uploadFile(input);
510            }
511        }
512        this._button.reset();
513    },
514    _uploadFileList: function(files){
515        for (var i=0; i<files.length; i++){
516            if ( !this._validateFile(files[i])){
517                return;
518            }
519        }
520
521        for (var i=0; i<files.length; i++){
522            this._uploadFile(files[i]);
523        }
524    },
525    _uploadFile: function(fileContainer){
526        var id = this._handler.add(fileContainer);
527        var fileName = this._handler.getName(id);
528
529        if (this._options.onSubmit(id, fileName) !== false){
530            this._onSubmit(id, fileName);
531            this._handler.upload(id, this._options.params);
532        }
533    },
534    _validateFile: function(file){
535        var name, size;
536
537        if (file.value){
538            // it is a file input
539            // get input value and remove path to normalize
540            name = file.value.replace(/.*(\/|\\)/, "");
541        } else {
542            // fix missing properties in Safari
543            name = file.fileName != null ? file.fileName : file.name;
544            size = file.fileSize != null ? file.fileSize : file.size;
545        }
546
547        if (! this._isAllowedExtension(name)){
548            this._error('typeError', name);
549            return false;
550
551        } else if (size === 0){
552            this._error('emptyError', name);
553            return false;
554
555        } else if (size && this._options.sizeLimit && size > this._options.sizeLimit){
556            this._error('sizeError', name);
557            return false;
558
559        } else if (size && size < this._options.minSizeLimit){
560            this._error('minSizeError', name);
561            return false;
562        }
563
564        return true;
565    },
566    _error: function(code, fileName){
567        var message = this._options.messages[code];
568        function r(name, replacement){ message = message.replace(name, replacement); }
569
570        r('{file}', this._formatFileName(fileName));
571        r('{extensions}', this._options.allowedExtensions.join(', '));
572        r('{sizeLimit}', this._formatSize(this._options.sizeLimit));
573        r('{minSizeLimit}', this._formatSize(this._options.minSizeLimit));
574
575        this._options.showMessage(message);
576    },
577    _formatFileName: function(name){
578        if (name.length > 33){
579            name = name.slice(0, 19) + '...' + name.slice(-13);
580        }
581        return name;
582    },
583    _isAllowedExtension: function(fileName){
584        var ext = (-1 !== fileName.indexOf('.')) ? fileName.replace(/.*[.]/, '').toLowerCase() : '';
585        var allowed = this._options.allowedExtensions;
586
587        if (!allowed.length){return true;}
588
589        for (var i=0; i<allowed.length; i++){
590            if (allowed[i].toLowerCase() == ext){ return true;}
591        }
592
593        return false;
594    },
595    _formatSize: function(bytes){
596        var i = -1;
597        do {
598            bytes = bytes / 1024;
599            i++;
600        } while (bytes > 99);
601
602        return Math.max(bytes, 0.1).toFixed(1) + ['kB', 'MB', 'GB', 'TB', 'PB', 'EB'][i];
603    }
604};
605
606
607/**
608 * Class that creates upload widget with drag-and-drop and file list
609 * @inherits qq.FileUploaderBasic
610 */
611qq.FileUploader = function(o){
612    // call parent constructor
613    qq.FileUploaderBasic.apply(this, arguments);
614
615    // additional options
616    qq.extend(this._options, {
617        element: null,
618        // if set, will be used instead of qq-upload-list in template
619        listElement: null,
620
621        template: '<div class="qq-uploader">' +
622                '<div class="qq-upload-drop-area"><span>Drop files here to upload</span></div>' +
623                '<div class="qq-upload-button">Upload a file</div>' +
624                '<ul class="qq-upload-list"></ul>' +
625             '</div>',
626
627        // template for one item in file list
628        fileTemplate: '<li>' +
629                '<span class="qq-upload-file"></span>' +
630                '<span class="qq-upload-spinner"></span>' +
631                '<span class="qq-upload-size"></span>' +
632                '<a class="qq-upload-cancel" href="#">Cancel</a>' +
633                '<span class="qq-upload-failed-text">Failed</span>' +
634            '</li>',
635
636        classes: {
637            // used to get elements from templates
638            button: 'qq-upload-button',
639            drop: 'qq-upload-drop-area',
640            dropActive: 'qq-upload-drop-area-active',
641            list: 'qq-upload-list',
642
643            file: 'qq-upload-file',
644            spinner: 'qq-upload-spinner',
645            size: 'qq-upload-size',
646            cancel: 'qq-upload-cancel',
647
648            // added to list item when upload completes
649            // used in css to hide progress spinner
650            success: 'qq-upload-success',
651            fail: 'qq-upload-fail'
652        }
653    });
654    // overwrite options with user supplied
655    qq.extend(this._options, o);
656
657    this._element = this._options.element;
658    this._element.innerHTML = this._options.template;
659    this._listElement = this._options.listElement || this._find(this._element, 'list');
660
661    this._classes = this._options.classes;
662
663    this._button = this._createUploadButton(this._find(this._element, 'button'));
664
665    this._bindCancelEvent();
666    this._setupDragDrop();
667};
668
669// inherit from Basic Uploader
670qq.extend(qq.FileUploader.prototype, qq.FileUploaderBasic.prototype);
671
672qq.extend(qq.FileUploader.prototype, {
673    /**
674     * Gets one of the elements listed in this._options.classes
675     **/
676    _find: function(parent, type){
677        var element = qq.getByClass(parent, this._options.classes[type])[0];
678        if (!element){
679            throw new Error('element not found ' + type);
680        }
681
682        return element;
683    },
684    _setupDragDrop: function(){
685        var self = this,
686            dropArea = this._find(this._element, 'drop');
687
688        var dz = new qq.UploadDropZone({
689            element: dropArea,
690            onEnter: function(e){
691                qq.addClass(dropArea, self._classes.dropActive);
692                e.stopPropagation();
693            },
694            onLeave: function(e){
695                e.stopPropagation();
696            },
697            onLeaveNotDescendants: function(e){
698                qq.removeClass(dropArea, self._classes.dropActive);
699            },
700            onDrop: function(e){
701                dropArea.style.display = 'none';
702                qq.removeClass(dropArea, self._classes.dropActive);
703                self._uploadFileList(e.dataTransfer.files);
704            }
705        });
706
707        dropArea.style.display = 'none';
708
709        qq.attach(document, 'dragenter', function(e){
710            if (!dz._isValidFileDrag(e)) return;
711
712            dropArea.style.display = 'block';
713        });
714        qq.attach(document, 'dragleave', function(e){
715            if (!dz._isValidFileDrag(e)) return;
716
717            var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);
718            // only fire when leaving document out
719            if ( ! relatedTarget || relatedTarget.nodeName == "HTML"){
720                dropArea.style.display = 'none';
721            }
722        });
723    },
724    _onSubmit: function(id, fileName){
725        qq.FileUploaderBasic.prototype._onSubmit.apply(this, arguments);
726        this._addToList(id, fileName);
727    },
728    _onProgress: function(id, fileName, loaded, total){
729        qq.FileUploaderBasic.prototype._onProgress.apply(this, arguments);
730
731        var item = this._getItemByFileId(id);
732        var size = this._find(item, 'size');
733        size.style.display = 'inline';
734
735        var text;
736        if (loaded != total){
737            text = Math.round(loaded / total * 100) + '% from ' + this._formatSize(total);
738        } else {
739            text = this._formatSize(total);
740        }
741
742        qq.setText(size, text);
743    },
744    _onComplete: function(id, fileName, result){
745        qq.FileUploaderBasic.prototype._onComplete.apply(this, arguments);
746
747        // mark completed
748        var item = this._getItemByFileId(id);
749        qq.remove(this._find(item, 'cancel'));
750        qq.remove(this._find(item, 'spinner'));
751
752        if (result.success){
753            qq.addClass(item, this._classes.success);
754        } else {
755            qq.addClass(item, this._classes.fail);
756        }
757    },
758    _addToList: function(id, fileName){
759        var item = qq.toElement(this._options.fileTemplate);
760        item.qqFileId = id;
761
762        var fileElement = this._find(item, 'file');
763        qq.setText(fileElement, this._formatFileName(fileName));
764        this._find(item, 'size').style.display = 'none';
765
766        this._listElement.appendChild(item);
767    },
768    _getItemByFileId: function(id){
769        var item = this._listElement.firstChild;
770
771        // there can't be txt nodes in dynamically created list
772        // and we can  use nextSibling
773        while (item){
774            if (item.qqFileId == id) return item;
775            item = item.nextSibling;
776        }
777    },
778    /**
779     * delegate click event for cancel link
780     **/
781    _bindCancelEvent: function(){
782        var self = this,
783            list = this._listElement;
784
785        qq.attach(list, 'click', function(e){
786            e = e || window.event;
787            var target = e.target || e.srcElement;
788
789            if (qq.hasClass(target, self._classes.cancel)){
790                qq.preventDefault(e);
791
792                var item = target.parentNode;
793                self._handler.cancel(item.qqFileId);
794                qq.remove(item);
795            }
796        });
797    }
798});
799
800qq.UploadDropZone = function(o){
801    this._options = {
802        element: null,
803        onEnter: function(e){},
804        onLeave: function(e){},
805        // is not fired when leaving element by hovering descendants
806        onLeaveNotDescendants: function(e){},
807        onDrop: function(e){}
808    };
809    qq.extend(this._options, o);
810
811    this._element = this._options.element;
812
813    this._disableDropOutside();
814    this._attachEvents();
815};
816
817qq.UploadDropZone.prototype = {
818    _disableDropOutside: function(e){
819        // run only once for all instances
820        if (!qq.UploadDropZone.dropOutsideDisabled ){
821
822            qq.attach(document, 'dragover', function(e){
823                if (e.dataTransfer){
824                    e.dataTransfer.dropEffect = 'none';
825                    e.preventDefault();
826                }
827            });
828
829            qq.UploadDropZone.dropOutsideDisabled = true;
830        }
831    },
832    _attachEvents: function(){
833        var self = this;
834
835        qq.attach(self._element, 'dragover', function(e){
836            if (!self._isValidFileDrag(e)) return;
837
838            var effect = e.dataTransfer.effectAllowed;
839            if (effect == 'move' || effect == 'linkMove'){
840                e.dataTransfer.dropEffect = 'move'; // for FF (only move allowed)
841            } else {
842                e.dataTransfer.dropEffect = 'copy'; // for Chrome
843            }
844
845            e.stopPropagation();
846            e.preventDefault();
847        });
848
849        qq.attach(self._element, 'dragenter', function(e){
850            if (!self._isValidFileDrag(e)) return;
851
852            self._options.onEnter(e);
853        });
854
855        qq.attach(self._element, 'dragleave', function(e){
856            if (!self._isValidFileDrag(e)) return;
857
858            self._options.onLeave(e);
859
860            var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);
861            // do not fire when moving a mouse over a descendant
862            if (qq.contains(this, relatedTarget)) return;
863
864            self._options.onLeaveNotDescendants(e);
865        });
866
867        qq.attach(self._element, 'drop', function(e){
868            if (!self._isValidFileDrag(e)) return;
869
870            e.preventDefault();
871            self._options.onDrop(e);
872        });
873    },
874    _isValidFileDrag: function(e){
875        var dt = e.dataTransfer,
876            // do not check dt.types.contains in webkit, because it crashes safari 4
877            isWebkit = navigator.userAgent.indexOf("AppleWebKit") > -1;
878
879        // dt.effectAllowed is none in Safari 5
880        // dt.types.contains check is for firefox
881        return dt && dt.effectAllowed != 'none' &&
882            (dt.files || (!isWebkit && dt.types.contains && dt.types.contains('Files')));
883
884    }
885};
886
887qq.UploadButton = function(o){
888    this._options = {
889        element: null,
890        // if set to true adds multiple attribute to file input
891        multiple: false,
892        // name attribute of file input
893        name: 'file',
894        onChange: function(input){},
895        hoverClass: 'qq-upload-button-hover',
896        focusClass: 'qq-upload-button-focus'
897    };
898
899    qq.extend(this._options, o);
900
901    this._element = this._options.element;
902
903    // make button suitable container for input
904    qq.css(this._element, {
905        position: 'relative',
906        overflow: 'hidden',
907        // Make sure browse button is in the right side
908        // in Internet Explorer
909        direction: 'ltr'
910    });
911
912    this._input = this._createInput();
913};
914
915qq.UploadButton.prototype = {
916    /* returns file input element */
917    getInput: function(){
918        return this._input;
919    },
920    /* cleans/recreates the file input */
921    reset: function(){
922        if (this._input.parentNode){
923            qq.remove(this._input);
924        }
925
926        qq.removeClass(this._element, this._options.focusClass);
927        this._input = this._createInput();
928    },
929    _createInput: function(){
930        var input = document.createElement("input");
931
932        if (this._options.multiple){
933            input.setAttribute("multiple", "multiple");
934        }
935
936        input.setAttribute("type", "file");
937        input.setAttribute("name", this._options.name);
938
939        qq.css(input, {
940            position: 'absolute',
941            // in Opera only 'browse' button
942            // is clickable and it is located at
943            // the right side of the input
944            right: 0,
945            top: 0,
946            fontFamily: 'Arial',
947            // 4 persons reported this, the max values that worked for them were 243, 236, 236, 118
948            fontSize: '118px',
949            margin: 0,
950            padding: 0,
951            cursor: 'pointer',
952            opacity: 0
953        });
954
955        this._element.appendChild(input);
956
957        var self = this;
958        qq.attach(input, 'change', function(){
959            self._options.onChange(input);
960        });
961
962        qq.attach(input, 'mouseover', function(){
963            qq.addClass(self._element, self._options.hoverClass);
964        });
965        qq.attach(input, 'mouseout', function(){
966            qq.removeClass(self._element, self._options.hoverClass);
967        });
968        qq.attach(input, 'focus', function(){
969            qq.addClass(self._element, self._options.focusClass);
970        });
971        qq.attach(input, 'blur', function(){
972            qq.removeClass(self._element, self._options.focusClass);
973        });
974
975        // IE and Opera, unfortunately have 2 tab stops on file input
976        // which is unacceptable in our case, disable keyboard access
977        if (window.attachEvent){
978            // it is IE or Opera
979            input.setAttribute('tabIndex', "-1");
980        }
981
982        return input;
983    }
984};
985
986/**
987 * Class for uploading files, uploading itself is handled by child classes
988 */
989qq.UploadHandlerAbstract = function(o){
990    this._options = {
991        debug: false,
992        action: '/upload.php',
993        // maximum number of concurrent uploads
994        maxConnections: 999,
995        onProgress: function(id, fileName, loaded, total){},
996        onComplete: function(id, fileName, response){},
997        onCancel: function(id, fileName){}
998    };
999    qq.extend(this._options, o);
1000
1001    this._queue = [];
1002    // params for files in queue
1003    this._params = [];
1004};
1005qq.UploadHandlerAbstract.prototype = {
1006    log: function(str){
1007        if (this._options.debug && window.console) console.log('[uploader] ' + str);
1008    },
1009    /**
1010     * Adds file or file input to the queue
1011     * @returns id
1012     **/
1013    add: function(file){},
1014    /**
1015     * Sends the file identified by id and additional query params to the server
1016     */
1017    upload: function(id, params){
1018        var len = this._queue.push(id);
1019
1020        var copy = {};
1021        qq.extend(copy, params);
1022        this._params[id] = copy;
1023
1024        // if too many active uploads, wait...
1025        if (len <= this._options.maxConnections){
1026            this._upload(id, this._params[id]);
1027        }
1028    },
1029    /**
1030     * Cancels file upload by id
1031     */
1032    cancel: function(id){
1033        this._cancel(id);
1034        this._dequeue(id);
1035    },
1036    /**
1037     * Cancells all uploads
1038     */
1039    cancelAll: function(){
1040        for (var i=0; i<this._queue.length; i++){
1041            this._cancel(this._queue[i]);
1042        }
1043        this._queue = [];
1044    },
1045    /**
1046     * Returns name of the file identified by id
1047     */
1048    getName: function(id){},
1049    /**
1050     * Returns size of the file identified by id
1051     */
1052    getSize: function(id){},
1053    /**
1054     * Returns id of files being uploaded or
1055     * waiting for their turn
1056     */
1057    getQueue: function(){
1058        return this._queue;
1059    },
1060    /**
1061     * Actual upload method
1062     */
1063    _upload: function(id){},
1064    /**
1065     * Actual cancel method
1066     */
1067    _cancel: function(id){},
1068    /**
1069     * Removes element from queue, starts upload of next
1070     */
1071    _dequeue: function(id){
1072        var i = qq.indexOf(this._queue, id);
1073        this._queue.splice(i, 1);
1074
1075        var max = this._options.maxConnections;
1076
1077        if (this._queue.length >= max && i < max){
1078            var nextId = this._queue[max-1];
1079            this._upload(nextId, this._params[nextId]);
1080        }
1081    }
1082};
1083
1084/**
1085 * Class for uploading files using form and iframe
1086 * @inherits qq.UploadHandlerAbstract
1087 */
1088qq.UploadHandlerForm = function(o){
1089    qq.UploadHandlerAbstract.apply(this, arguments);
1090
1091    this._inputs = {};
1092};
1093// @inherits qq.UploadHandlerAbstract
1094qq.extend(qq.UploadHandlerForm.prototype, qq.UploadHandlerAbstract.prototype);
1095
1096qq.extend(qq.UploadHandlerForm.prototype, {
1097    add: function(fileInput){
1098        fileInput.setAttribute('name', 'qqfile');
1099        var id = 'qq-upload-handler-iframe' + qq.getUniqueId();
1100
1101        this._inputs[id] = fileInput;
1102
1103        // remove file input from DOM
1104        if (fileInput.parentNode){
1105            qq.remove(fileInput);
1106        }
1107
1108        return id;
1109    },
1110    getName: function(id){
1111        // get input value and remove path to normalize
1112        return this._inputs[id].value.replace(/.*(\/|\\)/, "");
1113    },
1114    _cancel: function(id){
1115        this._options.onCancel(id, this.getName(id));
1116
1117        delete this._inputs[id];
1118
1119        var iframe = document.getElementById(id);
1120        if (iframe){
1121            // to cancel request set src to something else
1122            // we use src="javascript:false;" because it doesn't
1123            // trigger ie6 prompt on https
1124            iframe.setAttribute('src', 'javascript:false;');
1125
1126            qq.remove(iframe);
1127        }
1128    },
1129    _upload: function(id, params){
1130        var input = this._inputs[id];
1131
1132        if (!input){
1133            throw new Error('file with passed id was not added, or already uploaded or cancelled');
1134        }
1135
1136        var fileName = this.getName(id);
1137
1138        var iframe = this._createIframe(id);
1139        var form = this._createForm(iframe, params);
1140        form.appendChild(input);
1141
1142        var self = this;
1143        this._attachLoadEvent(iframe, function(){
1144            self.log('iframe loaded');
1145
1146            var response = self._getIframeContentJSON(iframe);
1147
1148            self._options.onComplete(id, fileName, response);
1149            self._dequeue(id);
1150
1151            delete self._inputs[id];
1152            // timeout added to fix busy state in FF3.6
1153            setTimeout(function(){
1154                qq.remove(iframe);
1155            }, 1);
1156        });
1157
1158        form.submit();
1159        qq.remove(form);
1160
1161        return id;
1162    },
1163    _attachLoadEvent: function(iframe, callback){
1164        qq.attach(iframe, 'load', function(){
1165            // when we remove iframe from dom
1166            // the request stops, but in IE load
1167            // event fires
1168            if (!iframe.parentNode){
1169                return;
1170            }
1171
1172            // fixing Opera 10.53
1173            if (iframe.contentDocument &&
1174                iframe.contentDocument.body &&
1175                iframe.contentDocument.body.innerHTML == "false"){
1176                // In Opera event is fired second time
1177                // when body.innerHTML changed from false
1178                // to server response approx. after 1 sec
1179                // when we upload file with iframe
1180                return;
1181            }
1182
1183            callback();
1184        });
1185    },
1186    /**
1187     * Returns json object received by iframe from server.
1188     */
1189    _getIframeContentJSON: function(iframe){
1190        // iframe.contentWindow.document - for IE<7
1191        var doc = iframe.contentDocument ? iframe.contentDocument: iframe.contentWindow.document,
1192            response;
1193
1194        this.log("converting iframe's innerHTML to JSON");
1195        this.log("innerHTML = " + doc.body.innerHTML);
1196
1197        try {
1198            response = eval("(" + doc.body.innerHTML + ")");
1199        } catch(err){
1200            response = {};
1201        }
1202
1203        return response;
1204    },
1205    /**
1206     * Creates iframe with unique name
1207     */
1208    _createIframe: function(id){
1209        // We can't use following code as the name attribute
1210        // won't be properly registered in IE6, and new window
1211        // on form submit will open
1212        // var iframe = document.createElement('iframe');
1213        // iframe.setAttribute('name', id);
1214
1215        var iframe = qq.toElement('<iframe src="javascript:false;" name="' + id + '" />');
1216        // src="javascript:false;" removes ie6 prompt on https
1217
1218        iframe.setAttribute('id', id);
1219
1220        iframe.style.display = 'none';
1221        document.body.appendChild(iframe);
1222
1223        return iframe;
1224    },
1225    /**
1226     * Creates form, that will be submitted to iframe
1227     */
1228    _createForm: function(iframe, params){
1229        // We can't use the following code in IE6
1230        // var form = document.createElement('form');
1231        // form.setAttribute('method', 'post');
1232        // form.setAttribute('enctype', 'multipart/form-data');
1233        // Because in this case file won't be attached to request
1234        var form = qq.toElement('<form method="post" enctype="multipart/form-data"></form>');
1235
1236        var queryString = qq.obj2url(params, this._options.action);
1237
1238        form.setAttribute('action', queryString);
1239        form.setAttribute('target', iframe.name);
1240        form.style.display = 'none';
1241        document.body.appendChild(form);
1242
1243        return form;
1244    }
1245});
1246
1247/**
1248 * Class for uploading files using xhr
1249 * @inherits qq.UploadHandlerAbstract
1250 */
1251qq.UploadHandlerXhr = function(o){
1252    qq.UploadHandlerAbstract.apply(this, arguments);
1253
1254    this._files = [];
1255    this._xhrs = [];
1256
1257    // current loaded size in bytes for each file
1258    this._loaded = [];
1259};
1260
1261// static method
1262qq.UploadHandlerXhr.isSupported = function(){
1263    var input = document.createElement('input');
1264    input.type = 'file';
1265
1266    return (
1267        'multiple' in input &&
1268        typeof File != "undefined" &&
1269        typeof (new XMLHttpRequest()).upload != "undefined" );
1270};
1271
1272// @inherits qq.UploadHandlerAbstract
1273qq.extend(qq.UploadHandlerXhr.prototype, qq.UploadHandlerAbstract.prototype);
1274
1275qq.extend(qq.UploadHandlerXhr.prototype, {
1276    /**
1277     * Adds file to the queue
1278     * Returns id to use with upload, cancel
1279     **/
1280    add: function(file){
1281        if (!(file instanceof File)){
1282            throw new Error('Passed obj in not a File (in qq.UploadHandlerXhr)');
1283        }
1284
1285        return this._files.push(file) - 1;
1286    },
1287    getName: function(id){
1288        var file = this._files[id];
1289        // fix missing name in Safari 4
1290        return file.fileName != null ? file.fileName : file.name;
1291    },
1292    getSize: function(id){
1293        var file = this._files[id];
1294        return file.fileSize != null ? file.fileSize : file.size;
1295    },
1296    /**
1297     * Returns uploaded bytes for file identified by id
1298     */
1299    getLoaded: function(id){
1300        return this._loaded[id] || 0;
1301    },
1302    /**
1303     * Sends the file identified by id and additional query params to the server
1304     * @param {Object} params name-value string pairs
1305     */
1306    _upload: function(id, params){
1307        var file = this._files[id],
1308            name = this.getName(id),
1309            size = this.getSize(id);
1310
1311        this._loaded[id] = 0;
1312
1313        var xhr = this._xhrs[id] = new XMLHttpRequest();
1314        var self = this;
1315
1316        xhr.upload.onprogress = function(e){
1317            if (e.lengthComputable){
1318                self._loaded[id] = e.loaded;
1319                self._options.onProgress(id, name, e.loaded, e.total);
1320            }
1321        };
1322
1323        xhr.onreadystatechange = function(){
1324            if (xhr.readyState == 4){
1325                self._onComplete(id, xhr);
1326            }
1327        };
1328
1329        // build query string
1330        params = params || {};
1331        params['qqfile'] = name;
1332        var queryString = qq.obj2url(params, this._options.action);
1333
1334        xhr.open("POST", queryString, true);
1335        xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
1336        xhr.setRequestHeader("X-File-Name", encodeURIComponent(name));
1337        xhr.setRequestHeader("Content-Type", "application/octet-stream");
1338        xhr.send(file);
1339    },
1340    _onComplete: function(id, xhr){
1341        // the request was aborted/cancelled
1342        if (!this._files[id]) return;
1343
1344        var name = this.getName(id);
1345        var size = this.getSize(id);
1346
1347        this._options.onProgress(id, name, size, size);
1348
1349        if (xhr.status == 200){
1350            this.log("xhr - server response received");
1351            this.log("responseText = " + xhr.responseText);
1352
1353            var response;
1354
1355            try {
1356                response = eval("(" + xhr.responseText + ")");
1357            } catch(err){
1358                response = {};
1359            }
1360
1361            this._options.onComplete(id, name, response);
1362
1363        } else {
1364            this._options.onComplete(id, name, {});
1365        }
1366
1367        this._files[id] = null;
1368        this._xhrs[id] = null;
1369        this._dequeue(id);
1370    },
1371    _cancel: function(id){
1372        this._options.onCancel(id, this.getName(id));
1373
1374        this._files[id] = null;
1375
1376        if (this._xhrs[id]){
1377            this._xhrs[id].abort();
1378            this._xhrs[id] = null;
1379        }
1380    }
1381});
1382
1383
1384/* XXXXXXXXXX end of lib/scripts/fileuploader.js XXXXXXXXXX */
1385
1386
1387
1388/* XXXXXXXXXX begin of lib/scripts/fileuploaderextended.js XXXXXXXXXX */
1389
1390qq.extend(qq.FileUploader.prototype, {
1391    _createUploadHandler: function(){
1392        var self = this,
1393            handlerClass;
1394
1395        if(qq.UploadHandlerXhr.isSupported()){
1396            handlerClass = 'UploadHandlerXhr';
1397            //handlerClass = 'UploadHandlerForm';
1398        } else {
1399            handlerClass = 'UploadHandlerForm';
1400        }
1401
1402        var handler = new qq[handlerClass]({
1403            debug: this._options.debug,
1404            action: this._options.action,
1405            maxConnections: this._options.maxConnections,
1406            onProgress: function(id, fileName, loaded, total){
1407                self._onProgress(id, fileName, loaded, total);
1408                self._options.onProgress(id, fileName, loaded, total);
1409            },
1410            onComplete: function(id, fileName, result){
1411                self._onComplete(id, fileName, result);
1412                self._options.onComplete(id, fileName, result);
1413            },
1414            onCancel: function(id, fileName){
1415                self._onCancel(id, fileName);
1416                self._options.onCancel(id, fileName);
1417            },
1418            onUpload: function(){
1419                self._onUpload();
1420            }
1421        });
1422
1423        return handler;
1424    },
1425
1426    _onUpload: function(){
1427        this._handler.uploadAll(this._options.params);
1428    },
1429
1430    _uploadFile: function(fileContainer){
1431        var id = this._handler.add(fileContainer);
1432        var fileName = this._handler.getName(id);
1433
1434        if (this._options.onSubmit(id, fileName) !== false){
1435            this._onSubmit(id, fileName);
1436        }
1437    },
1438
1439    _addToList: function(id, fileName){
1440        var item = qq.toElement(this._options.fileTemplate);
1441        item.qqFileId = id;
1442
1443        var fileElement = this._find(item, 'file');
1444        qq.setText(fileElement, fileName);
1445        this._find(item, 'size').style.display = 'none';
1446
1447        // name suggestion (simplified cleanID)
1448        var nameElement = this._find(item, 'nameInput');
1449        fileName = fileName.toLowerCase();
1450        fileName = fileName.replace(/([ !"#$%&\'()+,\/;<=>?@[\]^`{|}~:]+)/g, '_');
1451        fileName = fileName.replace(/^_+/,'');
1452        nameElement.value = fileName;
1453        nameElement.id = 'mediamanager__upload_item'+id;
1454
1455        this._listElement.appendChild(item);
1456    }
1457
1458});
1459
1460qq.FileUploaderExtended = function(o){
1461    // call parent constructor
1462    qq.FileUploaderBasic.apply(this, arguments);
1463
1464    qq.extend(this._options, {
1465        element: null,
1466        // if set, will be used instead of qq-upload-list in template
1467        listElement: null,
1468
1469        template: '<div class="qq-uploader">' +
1470            '<div class="qq-upload-drop-area"><span>' + LANG.media_drop + '</span></div>' +
1471            '<div class="qq-upload-button">' + LANG.media_select + '</div>' +
1472            '<ul class="qq-upload-list"></ul>' +
1473            '<div class="qq-action-container">' +
1474            '  <button class="qq-upload-action" type="submit" id="mediamanager__upload_button">' + LANG.media_upload_btn + '</button>' +
1475            '  <label class="qq-overwrite-check"><input type="checkbox" value="1" name="ow" class="dw__ow"> <span>' + LANG.media_overwrt + '</span></label>' +
1476            '</div>' +
1477            '</div>',
1478
1479        // template for one item in file list
1480        fileTemplate: '<li>' +
1481              '<span class="qq-upload-file hidden"></span>' +
1482            '  <input class="qq-upload-name-input edit" type="text" value="" />' +
1483            '  <span class="qq-upload-spinner hidden"></span>' +
1484            '  <span class="qq-upload-size"></span>' +
1485            '  <a class="qq-upload-cancel" href="#">
1485' + LANG.media_cancel + '</a>' +
1486            '  <span class="qq-upload-failed-text error">Failed</span>' +
1487            '</li>',
1488
1489        classes: {
1490            // used to get elements from templates
1491            button: 'qq-upload-button',
1492            drop: 'qq-upload-drop-area',
1493            dropActive: 'qq-upload-drop-area-active',
1494            list: 'qq-upload-list',
1495            nameInput: 'qq-upload-name-input',
1496            overwriteInput: 'qq-overwrite-check',
1497            uploadButton: 'qq-upload-action',
1498            file: 'qq-upload-file',
1499
1500            spinner: 'qq-upload-spinner',
1501            size: 'qq-upload-size',
1502            cancel: 'qq-upload-cancel',
1503
1504            // added to list item when upload completes
1505            // used in css to hide progress spinner
1506            success: 'qq-upload-success',
1507            fail: 'qq-upload-fail',
1508            failedText: 'qq-upload-failed-text'
1509        }
1510    });
1511
1512    qq.extend(this._options, o);
1513
1514    this._element = this._options.element;
1515    this._element.innerHTML = this._options.template;
1516    this._listElement = this._options.listElement || this._find(this._element, 'list');
1517
1518    this._classes = this._options.classes;
1519
1520    this._button = this._createUploadButton(this._find(this._element, 'button'));
1521
1522    this._bindCancelEvent();
1523    this._bindUploadEvent();
1524    this._setupDragDrop();
1525};
1526
1527qq.extend(qq.FileUploaderExtended.prototype, qq.FileUploader.prototype);
1528
1529qq.extend(qq.FileUploaderExtended.prototype, {
1530    _bindUploadEvent: function(){
1531        var self = this,
1532            list = this._listElement;
1533
1534        qq.attach(document.getElementById('mediamanager__upload_button'), 'click', function(e){
1535            e = e || window.event;
1536            var target = e.target || e.srcElement;
1537            qq.preventDefault(e);
1538            self._handler._options.onUpload();
1539
1540            jQuery(".qq-upload-name-input").each(function (i) {
1541                jQuery(this).prop('disabled', true);
1542            });
1543        });
1544    },
1545
1546    _onComplete: function(id, fileName, result){
1547        this._filesInProgress--;
1548
1549        // mark completed
1550        var item = this._getItemByFileId(id);
1551        qq.remove(this._find(item, 'cancel'));
1552        qq.remove(this._find(item, 'spinner'));
1553
1554        var nameInput = this._find(item, 'nameInput');
1555        var fileElement = this._find(item, 'file');
1556        qq.setText(fileElement, nameInput.value);
1557        qq.removeClass(fileElement, 'hidden');
1558        qq.remove(nameInput);
1559        jQuery('.qq-upload-button, #mediamanager__upload_button').remove();
1560        jQuery('.dw__ow').parent().hide();
1561        jQuery('.qq-upload-drop-area').remove();
1562
1563        if (result.success){
1564            qq.addClass(item, this._classes.success);
1565            $link = '<a href="' + result.link + '" id="h_:' + result.id + '" class="select">' + nameInput.value + '</a>';
1566            jQuery(fileElement).html($link);
1567
1568        } else {
1569            qq.addClass(item, this._classes.fail);
1570            var fail = this._find(item, 'failedText');
1571            if (result.error) qq.setText(fail, result.error);
1572        }
1573
1574        if (document.getElementById('media__content') && !document.getElementById('mediamanager__done_form')) {
1575            var action = document.location.href;
1576            var i = action.indexOf('?');
1577            if (i) action = action.substr(0, i);
1578            var button = '<form method="post" action="' + action + '" id="mediamanager__done_form"><div>';
1579            button += '<input type="hidden" value="' + result.ns + '" name="ns">';
1580            button += '<input type="hidden" value="1" name="recent">';
1581            button += '<button type="submit">' + LANG.media_done_btn + '</button></div></form>';
1582            jQuery('#mediamanager__uploader').append(button);
1583        }
1584    }
1585
1586});
1587
1588qq.extend(qq.UploadHandlerForm.prototype, {
1589    uploadAll: function(params){
1590        this._uploadAll(params);
1591    },
1592
1593    getName: function(id){
1594        var file = this._inputs[id];
1595        var name = document.getElementById('mediamanager__upload_item'+id);
1596        if (name != null) {
1597            return name.value;
1598        } else {
1599            if (file != null) {
1600                // get input value and remove path to normalize
1601                return file.value.replace(/.*(\/|\\)/, "");
1602            } else {
1603                return null;
1604            }
1605        }
1606    },
1607
1608    _uploadAll: function(params){
1609         jQuery(".qq-upload-spinner").each(function (i) {
1610            jQuery(this).removeClass('hidden');
1611        });
1612        for (key in this._inputs) {
1613            this.upload(key, params);
1614        }
1615
1616    },
1617
1618    _upload: function(id, params){
1619        var input = this._inputs[id];
1620
1621        if (!input){
1622            throw new Error('file with passed id was not added, or already uploaded or cancelled');
1623        }
1624
1625        var fileName = this.getName(id);
1626
1627        var iframe = this._createIframe(id);
1628        var form = this._createForm(iframe, params);
1629        form.appendChild(input);
1630
1631        var nameInput = qq.toElement('<input name="mediaid" value="' + fileName + '" type="text">');
1632        form.appendChild(nameInput);
1633
1634        var checked = jQuery('.dw__ow').is(':checked');
1635        var owCheckbox = jQuery('.dw__ow').clone();
1636        owCheckbox.attr('checked', checked);
1637        jQuery(form).append(owCheckbox);
1638
1639        var self = this;
1640        this._attachLoadEvent(iframe, function(){
1641            self.log('iframe loaded');
1642
1643            var response = self._getIframeContentJSON(iframe);
1644
1645            self._options.onComplete(id, fileName, response);
1646            self._dequeue(id);
1647
1648            delete self._inputs[id];
1649            // timeout added to fix busy state in FF3.6
1650            setTimeout(function(){
1651                qq.remove(iframe);
1652            }, 1);
1653        });
1654
1655        form.submit();
1656        qq.remove(form);
1657
1658        return id;
1659    }
1660});
1661
1662qq.extend(qq.UploadHandlerXhr.prototype, {
1663    uploadAll: function(params){
1664        this._uploadAll(params);
1665    },
1666
1667    getName: function(id){
1668        var file = this._files[id];
1669        var name = document.getElementById('mediamanager__upload_item'+id);
1670        if (name != null) {
1671            return name.value;
1672        } else {
1673            if (file != null) {
1674                // fix missing name in Safari 4
1675                return file.fileName != null ? file.fileName : file.name;
1676            } else {
1677                return null;
1678            }
1679        }
1680    },
1681
1682    getSize: function(id){
1683        var file = this._files[id];
1684        if (file == null) return null;
1685        return file.fileSize != null ? file.fileSize : file.size;
1686    },
1687
1688    _upload: function(id, params){
1689        var file = this._files[id],
1690            name = this.getName(id),
1691            size = this.getSize(id);
1692        if (name == null || size == null) return;
1693
1694        this._loaded[id] = 0;
1695
1696        var xhr = this._xhrs[id] = new XMLHttpRequest();
1697        var self = this;
1698
1699        xhr.upload.onprogress = function(e){
1700            if (e.lengthComputable){
1701                self._loaded[id] = e.loaded;
1702                self._options.onProgress(id, name, e.loaded, e.total);
1703            }
1704        };
1705
1706        xhr.onreadystatechange = function(){
1707            if (xhr.readyState == 4){
1708                self._onComplete(id, xhr);
1709            }
1710        };
1711
1712        // build query string
1713        params = params || {};
1714        params['qqfile'] = name;
1715        params['ow'] = jQuery('.dw__ow').is(':checked');
1716        var queryString = qq.obj2url(params, this._options.action);
1717
1718        xhr.open("POST", queryString, true);
1719        xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
1720        xhr.setRequestHeader("X-File-Name", encodeURIComponent(name));
1721        xhr.setRequestHeader("Content-Type", "application/octet-stream");
1722        xhr.send(file);
1723    },
1724
1725    _uploadAll: function(params){
1726        jQuery(".qq-upload-spinner").each(function (i) {
1727            jQuery(this).removeClass('hidden');
1728        });
1729        for (key in this._files) {
1730            this.upload(key, params);
1731        }
1732
1733    }
1734});
1735
1736
1737
1738/* XXXXXXXXXX end of lib/scripts/fileuploaderextended.js XXXXXXXXXX */
1739
1740
1741
1742/* XXXXXXXXXX begin of lib/scripts/helpers.js XXXXXXXXXX */
1743
1744/**
1745 * Various helper functions
1746 */
1747
1748/**
1749 * A PHP-style substr_replace
1750 *
1751 * Supports negative start and length and omitting length, but not
1752 * str and replace arrays.
1753 * See http://php.net/substr-replace for further documentation.
1754 */
1755function substr_replace(str, replace, start, length) {
1756    var a2, b1;
1757    a2 = (start < 0 ? str.length : 0) + start;
1758    if (typeof length === 'undefined') {
1759        length = str.length - a2;
1760    } else if (length < 0 && start < 0 && length <= start) {
1761        length = 0;
1762    }
1763    b1 = (length < 0 ? str.length : a2) + length;
1764    return str.substring(0, a2) + replace + str.substring(b1);
1765}
1766
1767/**
1768 * Bind variables to a function call creating a closure
1769 *
1770 * Use this to circumvent variable scope problems when creating closures
1771 * inside a loop
1772 *
1773 * @author  Adrian Lang <[email protected]>
1774 * @link    http://www.cosmocode.de/en/blog/gohr/2009-10/15-javascript-fixing-the-closure-scope-in-loops
1775 * @param   functionref fnc - the function to be called
1776 * @param   mixed - any arguments to be passed to the function
1777 * @returns functionref
1778 */
1779function bind(fnc/*, ... */) {
1780    var Aps = Array.prototype.slice,
1781    // Store passed arguments in this scope.
1782    // Since arguments is no Array nor has an own slice method,
1783    // we have to apply the slice method from the Array.prototype
1784        static_args = Aps.call(arguments, 1);
1785
1786    // Return a function evaluating the passed function with the
1787    // given args and optional arguments passed on invocation.
1788    return function (/* ... */) {
1789        // Same here, but we use Array.prototype.slice solely for
1790        // converting arguments to an Array.
1791        return fnc.apply(this,
1792                         static_args.concat(Aps.call(arguments, 0)));
1793    };
1794}
1795
1796/**
1797 * Report an error from a JS file to the console
1798 *
1799 * @param e    The error object
1800 * @param file The file in which the error occurred
1801 */
1802function logError(e, file) {
1803    if (window.console && console.error) {
1804        console.error('The error "%s: %s" occurred in file "%s". ' +
1805            'If this is in a plugin try updating or disabling the plugin, ' +
1806            'if this is in a template try updating the template or switching to the "dokuwiki" template.',
1807            e.name, e.message, file);
1808        if(e.stack) {
1809            console.error(e.stack);
1810        }
1811    }
1812}
1813
1814
1815
1816/* XXXXXXXXXX end of lib/scripts/helpers.js XXXXXXXXXX */
1817
1818
1819
1820/* XXXXXXXXXX begin of lib/scripts/delay.js XXXXXXXXXX */
1821
1822/**
1823 * Manage delayed and timed actions
1824 *
1825 * @license GPL2 (http://www.gnu.org/licenses/gpl.html)
1826 * @author  Adrian Lang <[email protected]>
1827 */
1828
1829/**
1830 * Provide a global callback for window.setTimeout
1831 *
1832 * To get a timeout for non-global functions, just call
1833 * delay.add(func, timeout).
1834 */
1835var timer = {
1836    _cur_id: 0,
1837    _handlers: {},
1838
1839    execDispatch: function (id) {
1840        timer._handlers[id]();
1841    },
1842
1843    add: function (func, timeout) {
1844        var id = ++timer._cur_id;
1845        timer._handlers[id] = func;
1846        return window.setTimeout('timer.execDispatch(' + id + ')', timeout);
1847    }
1848};
1849
1850/**
1851 * Provide a delayed start
1852 *
1853 * To call a function with a delay, just create a new Delay(func, timeout) and
1854 * call that object’s method “start”.
1855 */
1856function Delay (func, timeout) {
1857    this.func = func;
1858    if (timeout) {
1859        this.timeout = timeout;
1860    }
1861}
1862
1863Delay.prototype = {
1864    func: null,
1865    timeout: 500,
1866
1867    delTimer: function () {
1868        if (this.timer !== null) {
1869            window.clearTimeout(this.timer);
1870            this.timer = null;
1871        }
1872    },
1873
1874    start: function () {
1875        DEPRECATED('don\'t use the Delay object, use window.timeout with a callback instead');
1876        this.delTimer();
1877        var _this = this;
1878        this.timer = timer.add(function () { _this.exec.call(_this); },
1879                               this.timeout);
1880
1881        this._data = {
1882            _this: arguments[0],
1883            _params: Array.prototype.slice.call(arguments, 2)
1884        };
1885    },
1886
1887    exec: function () {
1888        this.delTimer();
1889        this.func.call(this._data._this, this._data._params);
1890    }
1891};
1892
1893
1894
1895/* XXXXXXXXXX end of lib/scripts/delay.js XXXXXXXXXX */
1896
1897
1898
1899/* XXXXXXXXXX begin of lib/scripts/cookie.js XXXXXXXXXX */
1900
1901/**
1902* Handles the cookie used by several JavaScript functions
1903*
1904* Only a single cookie is written and read. You may only save
1905* simple name-value pairs - no complex types!
1906*
1907* You should only use the getValue and setValue methods
1908*
1909* @author Andreas Gohr <[email protected]>
1910* @author Michal Rezler <[email protected]>
1911*/
1912var DokuCookie = {
1913    data: {},
1914    name: 'DOKU_PREFS',
1915
1916    /**
1917     * Save a value to the cookie
1918     *
1919     * @author Andreas Gohr <[email protected]>
1920     */
1921    setValue: function(key,val){
1922        var text = [],
1923            _this = this;
1924        this.init();
1925        if (val === false){
1926            delete this.data[key];
1927        }else{
1928            val = val + "";
1929            this.data[key] = val;
1930        }
1931
1932
1933        //save the whole data array
1934        jQuery.each(_this.data, function (key, val) {
1935            if (_this.data.hasOwnProperty(key)) {
1936                text.push(encodeURIComponent(key)+'#'+encodeURIComponent(val));
1937            }
1938        });
1939        jQuery.cookie(this.name, text.join('#'), {expires: 365, path: DOKU_COOKIE_PARAM.path, secure: DOKU_COOKIE_PARAM.secure});
1940    },
1941
1942    /**
1943     * Get a Value from the Cookie
1944     *
1945     * @author Andreas Gohr <[email protected]>
1946     * @param def default value if key does not exist; if not set, returns undefined by default
1947     */
1948    getValue: function(key, def){
1949        this.init();
1950        return this.data.hasOwnProperty(key) ? this.data[key] : def;
1951    },
1952
1953    /**
1954     * Loads the current set cookie
1955     *
1956     * @author Andreas Gohr <[email protected]>
1957     */
1958    init: function(){
1959        var text, parts, i;
1960        if(!jQuery.isEmptyObject(this.data)) {
1961            return;
1962        }
1963        text = jQuery.cookie(this.name);
1964        if(text){
1965            parts = text.split('#');
1966            for(i = 0; i < parts.length; i += 2){
1967                this.data[decodeURIComponent(parts[i])] = decodeURIComponent(parts[i+1]);
1968            }
1969        }
1970    }
1971};
1972
1973
1974
1975/* XXXXXXXXXX end of lib/scripts/cookie.js XXXXXXXXXX */
1976
1977
1978
1979/* XXXXXXXXXX begin of lib/scripts/script.js XXXXXXXXXX */
1980
1981// if jQuery was loaded, let's make it noConflict here.
1982if ('function' === typeof jQuery && 'function' === typeof jQuery.noConflict) {
1983    jQuery.noConflict();
1984}
1985
1986/**
1987 * Some browser detection
1988 */
1989var clientPC  = navigator.userAgent.toLowerCase(); // Get client info
1990var is_macos  = navigator.appVersion.indexOf('Mac') != -1;
1991var is_gecko  = ((clientPC.indexOf('gecko')!=-1) && (clientPC.indexOf('spoofer')==-1) &&
1992                (clientPC.indexOf('khtml') == -1) && (clientPC.indexOf('netscape/7.0')==-1));
1993var is_safari = ((clientPC.indexOf('applewebkit')!=-1) && (clientPC.indexOf('spoofer')==-1));
1994var is_khtml  = (navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled ));
1995if (clientPC.indexOf('opera')!=-1) {
1996    var is_opera = true;
1997    var is_opera_preseven = (window.opera && !document.childNodes);
1998    var is_opera_seven = (window.opera && document.childNodes);
1999}
2000
2001/**
2002 * Handler to close all open Popups
2003 */
2004function closePopups(){
2005    jQuery('div.JSpopup').hide();
2006}
2007
2008jQuery(function () {
2009    jQuery(document).on('click', closePopups);
2010});
2011
2012
2013
2014/* XXXXXXXXXX end of lib/scripts/script.js XXXXXXXXXX */
2015
2016
2017
2018/* XXXXXXXXXX begin of lib/scripts/qsearch.js XXXXXXXXXX */
2019
2020/**
2021 * AJAX functions for the pagename quicksearch
2022 *
2023 * @license  GPL2 (http://www.gnu.org/licenses/gpl.html)
2024 * @author   Andreas Gohr <[email protected]>
2025 * @author   Adrian Lang <[email protected]>
2026 * @author   Michal Rezler <[email protected]>
2027 */
2028jQuery.fn.dw_qsearch = function (overrides) {
2029
2030    var dw_qsearch = {
2031
2032        output: '#qsearch__out',
2033
2034        $inObj: this,
2035        $outObj: null,
2036        timer: null,
2037        curRequest: null,
2038
2039        /**
2040         * initialize the quick search
2041         *
2042         * Attaches the event handlers
2043         *
2044         */
2045        init: function () {
2046            var do_qsearch;
2047
2048            dw_qsearch.$outObj = jQuery(dw_qsearch.output);
2049
2050            // objects found?
2051            if (dw_qsearch.$inObj.length === 0 ||
2052                dw_qsearch.$outObj.length === 0) {
2053                return;
2054            }
2055
2056            // attach eventhandler to search field
2057            do_qsearch = function () {
2058                // abort any previous request
2059                if (dw_qsearch.curRequest != null) {
2060                    dw_qsearch.curRequest.abort();
2061                }
2062                var value = dw_qsearch.getSearchterm();
2063                if (value === '') {
2064                    dw_qsearch.clear_results();
2065                    return;
2066                }
2067                dw_qsearch.$inObj.parents('form').addClass('searching');
2068                dw_qsearch.curRequest = jQuery.post(
2069                    DOKU_BASE + 'lib/exe/ajax.php',
2070                    {
2071                        call: 'qsearch',
2072                        q: encodeURI(value)
2073                    },
2074                    dw_qsearch.onCompletion,
2075                    'html'
2076                );
2077            };
2078
2079            dw_qsearch.$inObj.on('keyup',
2080                function () {
2081                    if (dw_qsearch.timer) {
2082                        window.clearTimeout(dw_qsearch.timer);
2083                        dw_qsearch.timer = null;
2084                    }
2085                    dw_qsearch.timer = window.setTimeout(do_qsearch, 500);
2086                }
2087            );
2088
2089            // attach eventhandler to output field
2090            dw_qsearch.$outObj.on('click', dw_qsearch.clear_results);
2091        },
2092
2093        /**
2094         * Read search term from input
2095         */
2096        getSearchterm: function() {
2097            return dw_qsearch.$inObj.val();
2098        },
2099
2100        /**
2101         * Empty and hide the output div
2102         */
2103        clear_results: function () {
2104            dw_qsearch.$inObj.parents('form').removeClass('searching');
2105            dw_qsearch.$outObj.hide();
2106            dw_qsearch.$outObj.text('');
2107        },
2108
2109        /**
2110         * Callback. Reformat and display the results.
2111         *
2112         * Namespaces are shortened here to keep the results from overflowing
2113         * or wrapping
2114         *
2115         * @param data The result HTML
2116         */
2117        onCompletion: function (data) {
2118            var max, $links, too_big;
2119            dw_qsearch.$inObj.parents('form').removeClass('searching');
2120
2121            dw_qsearch.curRequest = null;
2122
2123            if (data === '') {
2124                dw_qsearch.clear_results();
2125                return;
2126            }
2127
2128            dw_qsearch.$outObj
2129                .html(data)
2130                .show()
2131                .css('white-space', 'nowrap');
2132
2133            // disable overflow during shortening
2134            dw_qsearch.$outObj.find('li').css('overflow', 'visible');
2135
2136            $links = dw_qsearch.$outObj.find('a');
2137            max = dw_qsearch.$outObj[0].clientWidth; // maximum width allowed (but take away paddings below)
2138            if (document.documentElement.dir === 'rtl') {
2139                max -= parseInt(dw_qsearch.$outObj.css('padding-left'));
2140                too_big = function (l) {
2141                    return l.offsetLeft < 0;
2142                };
2143            } else {
2144                max -= parseInt(dw_qsearch.$outObj.css('padding-right'));
2145                too_big = function (l) {
2146                    return l.offsetWidth + l.offsetLeft > max;
2147                };
2148            }
2149
2150            $links.each(function () {
2151                var start, length, replace, nsL, nsR, eli, runaway;
2152
2153                if (!too_big(this)) {
2154                    return;
2155                }
2156
2157                nsL = this.textContent.indexOf('(');
2158                nsR = this.textContent.indexOf(')');
2159                eli = 0;
2160                runaway = 0;
2161
2162                while ((nsR - nsL > 3) && too_big(this) && runaway++ < 500) {
2163                    if (eli !== 0) {
2164                        // elipsis already inserted
2165                        if ((eli - nsL) > (nsR - eli)) {
2166                            // cut left
2167                            start = eli - 2;
2168                            length = 2;
2169                        } else {
2170                            // cut right
2171                            start = eli + 1;
2172                            length = 1;
2173                        }
2174                        replace = '';
2175                    } else {
2176                        // replace middle with ellipsis
2177                        start = Math.floor(nsL + ((nsR - nsL) / 2));
2178                        length = 1;
2179                        replace = '…';
2180                    }
2181                    this.textContent = substr_replace(this.textContent,
2182                        replace, start, length);
2183
2184                    eli = this.textContent.indexOf('…');
2185                    nsL = this.textContent.indexOf('(');
2186                    nsR = this.textContent.indexOf(')');
2187                }
2188            });
2189
2190            // reenable overflow
2191            dw_qsearch.$outObj.find('li').css('overflow', 'hidden').css('text-overflow', 'ellipsis');
2192        }
2193
2194
2195    };
2196
2197    jQuery.extend(dw_qsearch, overrides);
2198
2199    if (!overrides.deferInit) {
2200        dw_qsearch.init();
2201    }
2202
2203    return dw_qsearch;
2204};
2205
2206jQuery(function () {
2207    jQuery('#qsearch__in').dw_qsearch({
2208        output: '#qsearch__out'
2209    });
2210});
2211
2212
2213
2214/* XXXXXXXXXX end of lib/scripts/qsearch.js XXXXXXXXXX */
2215
2216
2217
2218/* XXXXXXXXXX begin of lib/scripts/search.js XXXXXXXXXX */
2219
2220jQuery(function () {
2221    'use strict';
2222
2223    var $searchForm = jQuery('.search-results-form');
2224    if (!$searchForm.length) {
2225        return;
2226    }
2227
2228    var $toggleAssistanceButton = jQuery('<button>')
2229        .addClass('toggleAssistant')
2230        .attr('type', 'button')
2231        .attr('aria-expanded', 'false')
2232        .text(LANG.search_toggle_tools)
2233        .prependTo($searchForm.find('fieldset'))
2234    ;
2235
2236    $toggleAssistanceButton.on('click', function () {
2237        jQuery('.advancedOptions').toggle(0, function () {
2238            var $me = jQuery(this);
2239            if ($me.attr('aria-hidden')) {
2240                $me.removeAttr('aria-hidden');
2241                $toggleAssistanceButton.attr('aria-expanded', 'true');
2242                DokuCookie.setValue('sa', 'on');
2243            } else {
2244                $me.attr('aria-hidden', 'true');
2245                $toggleAssistanceButton.attr('aria-expanded', 'false');
2246                DokuCookie.setValue('sa', 'off');
2247            }
2248        });
2249    });
2250
2251    if (DokuCookie.getValue('sa') === 'on') {
2252        $toggleAssistanceButton.trigger('click');
2253    }
2254
2255    $searchForm.find('.advancedOptions .toggle div.current').on('click', function () {
2256        var $me = jQuery(this);
2257        $me.parent().siblings().removeClass('open');
2258        $me.parent().siblings().find('ul:first').attr('aria-expanded', 'false');
2259        $me.parent().toggleClass('open');
2260        if ($me.parent().hasClass('open')) {
2261            $me.parent().find('ul:first').attr('aria-expanded', 'true');
2262        } else {
2263            $me.parent().find('ul:first').attr('aria-expanded', 'false');
2264        }
2265    });
2266
2267});
2268
2269
2270
2271/* XXXXXXXXXX end of lib/scripts/search.js XXXXXXXXXX */
2272
2273
2274
2275/* XXXXXXXXXX begin of lib/scripts/tree.js XXXXXXXXXX */
2276
2277jQuery.fn.dw_tree = function(overrides) {
2278    var dw_tree = {
2279
2280        /**
2281         * Delay in ms before showing the throbber.
2282         * Used to skip the throbber for fast AJAX calls.
2283         */
2284        throbber_delay: 500,
2285
2286        $obj: this,
2287
2288        toggle_selector: 'a.idx_dir',
2289
2290        init: function () {
2291            this.$obj.on('click', this.toggle_selector, this,
2292                               this.toggle);
2293            jQuery('ul:first', this.$obj).attr('role', 'tree');
2294            jQuery('ul', this.$obj).not(':first').attr('role', 'group');
2295            jQuery('li', this.$obj).attr('role', 'treeitem');
2296            jQuery('li.open > ul', this.$obj).attr('aria-expanded', 'true');
2297            jQuery('li.closed > ul', this.$obj).attr('aria-expanded', 'false');
2298            jQuery('li.closed', this.$obj).attr('aria-live', 'assertive');
2299        },
2300
2301        /**
2302         * Open or close a subtree using AJAX
2303         * The contents of subtrees are "cached" until the page is reloaded.
2304         * A "loading" indicator is shown only when the AJAX call is slow.
2305         *
2306         * @author Andreas Gohr <[email protected]>
2307         * @author Ben Coburn <[email protected]>
2308         * @author Pierre Spring <[email protected]>
2309         */
2310        toggle: function (e) {
2311            var $listitem, $sublist, timeout, $clicky, show_sublist, dw_tree, opening;
2312
2313            e.preventDefault();
2314
2315            dw_tree = e.data;
2316            $clicky = jQuery(this);
2317            $listitem = $clicky.closest('li');
2318            $sublist = $listitem.find('ul').first();
2319            opening = $listitem.hasClass('closed');
2320            dw_tree.toggle_display($clicky, opening);
2321            if ($sublist.is(':visible')) {
2322                $listitem.removeClass('open').addClass('closed');
2323                $sublist.attr('aria-expanded', 'false');
2324            } else {
2325                $listitem.removeClass('closed').addClass('open');
2326                $sublist.attr('aria-expanded', 'true');
2327            }
2328
2329            // if already open, close by hiding the sublist
2330            if (!opening) {
2331                $sublist.dw_hide();
2332                return;
2333            }
2334
2335            show_sublist = function (data) {
2336                $sublist.hide();
2337                if (typeof data !== 'undefined') {
2338                    $sublist.html(data);
2339                    $sublist.parent().attr('aria-busy', 'false').removeAttr('aria-live');
2340                    jQuery('li.closed', $sublist).attr('aria-live', 'assertive');
2341                }
2342                if ($listitem.hasClass('open')) {
2343                    // Only show if user didn’t close the list since starting
2344                    // to load the content
2345                    $sublist.dw_show();
2346                }
2347            };
2348
2349            // just show if already loaded
2350            if ($sublist.length > 0) {
2351                show_sublist();
2352                return;
2353            }
2354
2355            //prepare the new ul
2356            $sublist = jQuery('<ul class="idx" role="group"/>');
2357            $listitem.append($sublist);
2358
2359            timeout = window.setTimeout(
2360                bind(show_sublist, '<li aria-busy="true"><img src="' + DOKU_BASE + 'lib/images/throbber.gif" alt="loading..." title="loading..." /></li>'), dw_tree.throbber_delay);
2361
2362            dw_tree.load_data(function (data) {
2363                                  window.clearTimeout(timeout);
2364                                  show_sublist(data);
2365                              }, $clicky);
2366        },
2367
2368        toggle_display: function ($clicky, opening) {
2369        },
2370
2371        load_data: function (show_data, $clicky) {
2372            show_data();
2373        }
2374    };
2375
2376    jQuery.extend(dw_tree, overrides);
2377
2378    if (!overrides.deferInit) {
2379        dw_tree.init();
2380    }
2381
2382    return dw_tree;
2383};
2384
2385
2386
2387/* XXXXXXXXXX end of lib/scripts/tree.js XXXXXXXXXX */
2388
2389
2390
2391/* XXXXXXXXXX begin of lib/scripts/index.js XXXXXXXXXX */
2392
2393var dw_index = jQuery('#index__tree').dw_tree({deferInit: true,
2394    load_data: function  (show_sublist, $clicky) {
2395        jQuery.post(
2396            DOKU_BASE + 'lib/exe/ajax.php',
2397            $clicky[0].search.substr(1) + '&call=index',
2398            show_sublist, 'html'
2399        );
2400    }
2401});
2402jQuery(function () {
2403    var $tree = jQuery('#index__tree');
2404
2405    dw_index.$obj = $tree;
2406
2407    dw_index.init();
2408});
2409
2410
2411
2412/* XXXXXXXXXX end of lib/scripts/index.js XXXXXXXXXX */
2413
2414
2415
2416/* XXXXXXXXXX begin of lib/scripts/textselection.js XXXXXXXXXX */
2417
2418/**
2419 * Text selection related functions.
2420 */
2421
2422/**
2423 * selection prototype
2424 *
2425 * Object that capsulates the selection in a textarea. Returned by DWgetSelection.
2426 *
2427 * @author Andreas Gohr <[email protected]>
2428 */
2429function selection_class(){
2430    this.start     = 0;
2431    this.end       = 0;
2432    this.obj       = null;
2433    this.scroll    = 0;
2434    this.fix       = 0;
2435
2436    this.getLength = function(){
2437        return this.end - this.start;
2438    };
2439
2440    this.getText = function(){
2441        return (!this.obj) ? '' : this.obj.value.substring(this.start,this.end);
2442    };
2443}
2444
2445/**
2446 * Get current selection/cursor position in a given textArea
2447 *
2448 * @link   http://groups.drupal.org/node/1210
2449 * @author Andreas Gohr <[email protected]>
2450 * @link   http://linebyline.blogspot.com/2006/11/textarea-cursor-position-in-internet.html
2451 * @returns object - a selection object
2452 */
2453function DWgetSelection(textArea) {
2454    var sel = new selection_class();
2455
2456    textArea.focus();
2457    sel.obj   = textArea;
2458    sel.start  = textArea.selectionStart;
2459    sel.end    = textArea.selectionEnd;
2460    sel.scroll = textArea.scrollTop;
2461    return sel;
2462}
2463
2464/**
2465 * Set the selection
2466 *
2467 * You need to get a selection object via DWgetSelection() first, then modify the
2468 * start and end properties and pass it back to this function.
2469 *
2470 * @link http://groups.drupal.org/node/1210
2471 * @author Andreas Gohr <[email protected]>
2472 * @param {selection_class} selection  a selection object as returned by DWgetSelection()
2473 */
2474function DWsetSelection(selection){
2475    selection.obj.setSelectionRange(selection.start, selection.end);
2476    if(selection.scroll) selection.obj.scrollTop = selection.scroll;
2477}
2478
2479/**
2480 * Inserts the given text at the current cursor position or replaces the current
2481 * selection
2482 *
2483 * @author Andreas Gohr <[email protected]>
2484 * @param {string}  text           the new text to be pasted
2485 * @param {selection_class}  selection     selection object returned by DWgetSelection
2486 * @param {int}     opts.startofs  number of charcters at the start to skip from new selection
2487 * @param {int}     opts.endofs    number of characters at the end to skip from new selection
2488 * @param {boolean} opts.nosel     set true if new text should not be selected
2489 */
2490function pasteText(selection,text,opts){
2491    if(!opts) opts = {};
2492    // replace the content
2493
2494    selection.obj.value =
2495        selection.obj.value.substring(0, selection.start) + text +
2496        selection.obj.value.substring(selection.end, selection.obj.value.length);
2497
2498    // set new selection
2499    if (is_opera) {
2500        // Opera replaces \n by \r\n when inserting text.
2501        selection.end = selection.start + text.replace(/\r?\n/g, '\r\n').length;
2502    } else {
2503        selection.end = selection.start + text.length;
2504    }
2505
2506
2507    // modify the new selection if wanted
2508    if(opts.startofs) selection.start += opts.startofs;
2509    if(opts.endofs)   selection.end   -= opts.endofs;
2510
2511    // no selection wanted? set cursor to end position
2512    if(opts.nosel) selection.start = selection.end;
2513
2514    DWsetSelection(selection);
2515}
2516
2517
2518/**
2519 * Format selection
2520 *
2521 * Apply tagOpen/tagClose to selection in textarea, use sampleText instead
2522 * of selection if there is none.
2523 *
2524 * @author Andreas Gohr <[email protected]>
2525 */
2526function insertTags(textAreaID, tagOpen, tagClose, sampleText){
2527    var txtarea = jQuery('#' + textAreaID)[0];
2528
2529    var selection = DWgetSelection(txtarea);
2530    var text = selection.getText();
2531    var opts;
2532
2533    // don't include trailing space in selection
2534    if(text.charAt(text.length - 1) == ' '){
2535        selection.end--;
2536        text = selection.getText();
2537    }
2538
2539    if(!text){
2540        // nothing selected, use the sample text and select it
2541        text = sampleText;
2542        opts = {
2543            startofs: tagOpen.length,
2544            endofs: tagClose.length
2545        };
2546    }else{
2547        // place cursor at the end
2548        opts = {
2549            nosel: true
2550        };
2551    }
2552
2553    // surround with tags
2554    text = tagOpen + text + tagClose;
2555
2556    // do it
2557    pasteText(selection,text,opts);
2558}
2559
2560/**
2561 * Wraps around pasteText() for backward compatibility
2562 *
2563 * @author Andreas Gohr <[email protected]>
2564 */
2565function insertAtCarret(textAreaID, text){
2566    var txtarea = jQuery('#' + textAreaID)[0];
2567    var selection = DWgetSelection(txtarea);
2568    pasteText(selection,text,{nosel: true});
2569}
2570
2571
2572
2573/* XXXXXXXXXX end of lib/scripts/textselection.js XXXXXXXXXX */
2574
2575
2576
2577/* XXXXXXXXXX begin of lib/scripts/toolbar.js XXXXXXXXXX */
2578
2579// used to identify pickers
2580var pickercounter=0;
2581
2582/**
2583 * Create a toolbar
2584 *
2585 * @param  string tbid       ID of the element where to insert the toolbar
2586 * @param  string edid       ID of the editor textarea
2587 * @param  array  tb         Associative array defining the buttons
2588 * @param  bool   allowblock Allow buttons creating multiline content
2589 * @author Andreas Gohr <[email protected]>
2590 */
2591function initToolbar(tbid,edid,tb, allowblock){
2592    var $toolbar, $edit;
2593    if (typeof tbid == 'string') {
2594        $toolbar = jQuery('#' + tbid);
2595    } else {
2596        $toolbar = jQuery(tbid);
2597    }
2598
2599    $edit = jQuery('#' + edid);
2600
2601    if ($toolbar.length == 0 || $edit.length == 0 || $edit.attr('readOnly')) {
2602        return;
2603    }
2604
2605    if (typeof allowblock === 'undefined') {
2606        allowblock = true;
2607    }
2608
2609    //empty the toolbar area:
2610    $toolbar.html('');
2611
2612    jQuery.each(tb, function (k, val) {
2613        if (!tb.hasOwnProperty(k) || (!allowblock && val.block === true)) {
2614            return;
2615        }
2616        var actionFunc, $btn;
2617
2618        // create new button (jQuery object)
2619        $btn = jQuery(createToolButton(val.icon, val.title, val.key, val.id,
2620                                       val['class']));
2621
2622        // type is a tb function -> assign it as onclick
2623        actionFunc = 'tb_'+val.type;
2624        if( jQuery.isFunction(window[actionFunc]) ){
2625            $btn.on('click', bind(window[actionFunc],$btn,val,edid) );
2626            $toolbar.append($btn);
2627            return;
2628        }
2629
2630        // type is a init function -> execute it
2631        actionFunc = 'addBtnAction'+val.type.charAt(0).toUpperCase()+val.type.substring(1);
2632        if( jQuery.isFunction(window[actionFunc]) ){
2633            var pickerid = window[actionFunc]($btn, val, edid);
2634            if(pickerid !== ''){
2635                $toolbar.append($btn);
2636                $btn.attr('aria-controls', pickerid);
2637                if (actionFunc === 'addBtnActionPicker') {
2638                    $btn.attr('aria-haspopup', 'true');
2639                }
2640            }
2641            return;
2642        }
2643
2644        alert('unknown toolbar type: '+val.type+'  '+actionFunc);
2645    });
2646}
2647
2648/**
2649 * Button action for format buttons
2650 *
2651 * @param  DOMElement btn   Button element to add the action to
2652 * @param  array      props Associative array of button properties
2653 * @param  string     edid  ID of the editor textarea
2654 * @author Gabriel Birke <[email protected]>
2655 * @author Andreas Gohr <[email protected]>
2656 */
2657function tb_format(btn, props, edid) {
2658    var sample = props.sample || props.title;
2659    insertTags(edid,
2660               fixtxt(props.open),
2661               fixtxt(props.close),
2662               fixtxt(sample));
2663    pickerClose();
2664    return false;
2665}
2666
2667/**
2668 * Button action for format buttons
2669 *
2670 * This works exactly as tb_format() except that, if multiple lines
2671 * are selected, each line will be formatted seperately
2672 *
2673 * @param  DOMElement btn   Button element to add the action to
2674 * @param  array      props Associative array of button properties
2675 * @param  string     edid  ID of the editor textarea
2676 * @author Gabriel Birke <[email protected]>
2677 * @author Andreas Gohr <[email protected]>
2678 */
2679function tb_formatln(btn, props, edid) {
2680    var sample = props.sample || props.title,
2681        opts,
2682        selection = DWgetSelection(jQuery('#'+edid)[0]);
2683
2684    sample = fixtxt(sample);
2685    props.open  = fixtxt(props.open);
2686    props.close = fixtxt(props.close);
2687
2688    // is something selected?
2689    if(selection.getLength()){
2690        sample = selection.getText();
2691        opts = {nosel: true};
2692    }else{
2693        opts = {
2694            startofs: props.open.length,
2695            endofs: props.close.length
2696        };
2697    }
2698
2699    sample = sample.split("\n").join(props.close+"\n"+props.open);
2700    sample = props.open+sample+props.close;
2701
2702    pasteText(selection,sample,opts);
2703
2704    pickerClose();
2705    return false;
2706}
2707
2708/**
2709 * Button action for insert buttons
2710 *
2711 * @param  DOMElement btn   Button element to add the action to
2712 * @param  array      props Associative array of button properties
2713 * @param  string     edid  ID of the editor textarea
2714 * @author Gabriel Birke <[email protected]>
2715 * @author Andreas Gohr <[email protected]>
2716 */
2717function tb_insert(btn, props, edid) {
2718    insertAtCarret(edid,fixtxt(props.insert));
2719    pickerClose();
2720    return false;
2721}
2722
2723/**
2724 * Button action for the media popup
2725 *
2726 * @param  DOMElement btn   Button element to add the action to
2727 * @param  array      props Associative array of button properties
2728 * @param  string     edid  ID of the editor textarea
2729 * @author Andreas Gohr <[email protected]>
2730 */
2731function tb_mediapopup(btn, props, edid) {
2732    window.open(
2733        DOKU_BASE+props.url+encodeURIComponent(NS)+'&edid='+encodeURIComponent(edid),
2734        props.name,
2735        props.options);
2736    return false;
2737}
2738
2739/**
2740 * Button action for automatic headlines
2741 *
2742 * Insert a new headline based on the current section level
2743 *
2744 * @param  DOMElement btn   Button element to add the action to
2745 * @param  array      props Associative array of button properties
2746 * @param  string     edid  ID of the editor textarea
2747 * @author Andreas Gohr <[email protected]>
2748 */
2749function tb_autohead(btn, props, edid){
2750    var lvl = currentHeadlineLevel(edid),
2751        tags;
2752
2753    // determine new level
2754    lvl += props.mod;
2755    if(lvl < 1) lvl = 1;
2756    if(lvl > 5) lvl = 5;
2757
2758    tags = (new Array(8 - lvl)).join('=');
2759    insertTags(edid, tags+' ', ' '+tags+"\n", props.text);
2760    pickerClose();
2761    return false;
2762}
2763
2764
2765/**
2766 * Add button action for picker buttons and create picker element
2767 *
2768 * @param  jQuery      btn   Button element to add the action to
2769 * @param  array      props Associative array of button properties
2770 * @param  string     edid  ID of the editor textarea
2771 * @return boolean    If button should be appended
2772 * @author Gabriel Birke <[email protected]>
2773 */
2774function addBtnActionPicker($btn, props, edid) {
2775    var pickerid = 'picker'+(pickercounter++);
2776    var picker = createPicker(pickerid, props, edid);
2777    jQuery(picker).attr('aria-hidden', 'true');
2778
2779    $btn.click(
2780        function(e) {
2781            pickerToggle(pickerid,$btn);
2782            e.preventDefault();
2783            return '';
2784        }
2785    );
2786
2787    return pickerid;
2788}
2789
2790/**
2791 * Add button action for the link wizard button
2792 *
2793 * @param  DOMElement btn   Button element to add the action to
2794 * @param  array      props Associative array of button properties
2795 * @param  string     edid  ID of the editor textarea
2796 * @return boolean    If button should be appended
2797 * @author Andreas Gohr <[email protected]>
2798 */
2799function addBtnActionLinkwiz($btn, props, edid) {
2800    dw_linkwiz.init(jQuery('#'+edid));
2801    jQuery($btn).click(function(e){
2802        dw_linkwiz.val = props;
2803        dw_linkwiz.toggle();
2804        e.preventDefault();
2805        return '';
2806    });
2807    return 'link__wiz';
2808}
2809
2810
2811/**
2812 * Show/Hide a previously created picker window
2813 *
2814 * @author Andreas Gohr <[email protected]>
2815 */
2816function pickerToggle(pickerid,$btn){
2817    var $picker = jQuery('#' + pickerid),
2818        pos = $btn.offset();
2819    if ($picker.hasClass('a11y')) {
2820        $picker.removeClass('a11y').attr('aria-hidden', 'false');
2821    } else {
2822        $picker.addClass('a11y').attr('aria-hidden', 'true');
2823    }
2824    var picker_left = pos.left + 3,
2825        picker_width = $picker.width(),
2826        window_width = jQuery(window).width();
2827    if (picker_width > 300) {
2828        $picker.css("max-width", "300");
2829        picker_width = 300;
2830    }
2831    if ((picker_left + picker_width + 40) > window_width) {
2832        picker_left = window_width - picker_width - 40;
2833    }
2834    if (picker_left < 0) {
2835        picker_left = 0;
2836    }
2837    $picker.offset({left: picker_left, top: pos.top+$btn[0].offsetHeight+3});
2838}
2839
2840/**
2841 * Close all open pickers
2842 *
2843 * @author Andreas Gohr <[email protected]>
2844 */
2845function pickerClose(){
2846    jQuery('.picker').addClass('a11y');
2847}
2848
2849
2850/**
2851 * Replaces \n with linebreaks
2852 */
2853function fixtxt(str){
2854    return str.replace(/\\n/g,"\n");
2855}
2856
2857jQuery(function () {
2858    initToolbar('tool__bar','wiki__text',toolbar);
2859    jQuery('#tool__bar').attr('role', 'toolbar');
2860});
2861
2862
2863
2864/* XXXXXXXXXX end of lib/scripts/toolbar.js XXXXXXXXXX */
2865
2866
2867
2868/* XXXXXXXXXX begin of lib/scripts/edit.js XXXXXXXXXX */
2869
2870/**
2871 * Functions for text editing (toolbar stuff)
2872 *
2873 * @todo most of the stuff in here should be revamped and then moved to toolbar.js
2874 * @author Andreas Gohr <[email protected]>
2875 */
2876
2877/**
2878 * Creates a toolbar button through the DOM
2879 * Called for each entry of toolbar definition array (built by inc/toolbar.php and extended via js)
2880 *
2881 * Style the buttons through the toolbutton class
2882 *
2883 * @param {string} icon      image filename, relative to folder lib/images/toolbar/
2884 * @param {string} label     title of button, show on mouseover
2885 * @param {string} key       hint in title of button for access key
2886 * @param {string} id        id of button, and '<id>_ico' of icon
2887 * @param {string} classname for styling buttons
2888 *
2889 * @author Andreas Gohr <[email protected]>
2890 * @author Michal Rezler <[email protected]>
2891 */
2892function createToolButton(icon,label,key,id,classname){
2893    var $btn = jQuery(document.createElement('button')),
2894        $ico = jQuery(document.createElement('img'));
2895
2896    // prepare the basic button stuff
2897    $btn.addClass('toolbutton');
2898    if(classname){
2899        $btn.addClass(classname);
2900    }
2901
2902    $btn.attr('title', label).attr('aria-controls', 'wiki__text');
2903    if(key){
2904        $btn.attr('title', label + ' ['+key.toUpperCase()+']')
2905            .attr('accessKey', key);
2906    }
2907
2908    // set IDs if given
2909    if(id){
2910        $btn.attr('id', id);
2911        $ico.attr('id', id+'_ico');
2912    }
2913
2914    // create the icon and add it to the button
2915    if(icon.substr(0,1) !== '/'){
2916        icon = DOKU_BASE + 'lib/images/toolbar/' + icon;
2917    }
2918    $ico.attr('src', icon);
2919    $ico.attr('alt', '');
2920    $ico.attr('width', 16);
2921    $ico.attr('height', 16);
2922    $btn.append($ico);
2923
2924    // we have to return a DOM object (for compatibility reasons)
2925    return $btn[0];
2926}
2927
2928/**
2929 * Creates a picker window for inserting text
2930 *
2931 * The given list can be an associative array with text,icon pairs
2932 * or a simple list of text. Style the picker window through the picker
2933 * class or the picker buttons with the pickerbutton class. Picker
2934 * windows are appended to the body and created invisible.
2935 *
2936 * @param  {string} id    the ID to assign to the picker
2937 * @param  {Array}  props the properties for the picker
2938 * @param  {string} edid  the ID of the textarea
2939 * @return DOMobject    the created picker
2940 * @author Andreas Gohr <[email protected]>
2941 */
2942function createPicker(id,props,edid){
2943    // create the wrapping div
2944    var $picker = jQuery(document.createElement('div'));
2945
2946    $picker.addClass('picker a11y');
2947    if(props['class']){
2948        $picker.addClass(props['class']);
2949    }
2950
2951    $picker.attr('id', id).css('position', 'absolute');
2952
2953    function $makebutton(title) {
2954        var $btn = jQuery(document.createElement('button'))
2955            .addClass('pickerbutton').attr('title', title)
2956            .attr('aria-controls', edid)
2957            .on('click', bind(pickerInsert, title, edid))
2958            .appendTo($picker);
2959        return $btn;
2960    }
2961
2962    jQuery.each(props.list, function (key, item) {
2963        if (!props.list.hasOwnProperty(key)) {
2964            return;
2965        }
2966
2967        if(isNaN(key)){
2968            // associative array -> treat as text => image pairs
2969            if (item.substr(0,1) !== '/') {
2970                item = DOKU_BASE+'lib/images/'+props.icobase+'/'+item;
2971            }
2972            jQuery(document.createElement('img'))
2973                .attr('src', item)
2974                .attr('alt', '')
2975                .css('height', '16')
2976                .appendTo($makebutton(key));
2977        }else if (typeof item == 'string'){
2978            // a list of text -> treat as text picker
2979            $makebutton(item).text(item);
2980        }else{
2981            // a list of lists -> treat it as subtoolbar
2982            initToolbar($picker,edid,props.list);
2983            return false; // all buttons handled already
2984        }
2985
2986    });
2987    jQuery('body').append($picker);
2988
2989    // we have to return a DOM object (for compatibility reasons)
2990    return $picker[0];
2991}
2992
2993/**
2994 * Called by picker buttons to insert Text and close the picker again
2995 *
2996 * @author Andreas Gohr <[email protected]>
2997 */
2998function pickerInsert(text,edid){
2999    insertAtCarret(edid,text);
3000    pickerClose();
3001}
3002
3003/**
3004 * Add button action for signature button
3005 *
3006 * @param  {jQuery} $btn   Button element to add the action to
3007 * @param  {Array}  props  Associative array of button properties
3008 * @param  {string} edid   ID of the editor textarea
3009 * @return {string} picker id for aria-controls attribute
3010 * @author Gabriel Birke <[email protected]>
3011 */
3012function addBtnActionSignature($btn, props, edid) {
3013    if(typeof SIG != 'undefined' && SIG != ''){
3014        $btn.on('click', function (e) {
3015            insertAtCarret(edid,SIG);
3016            e.preventDefault();
3017        });
3018        return edid;
3019    }
3020    return '';
3021}
3022
3023/**
3024 * Determine the current section level while editing
3025 *
3026 * @param {string} textboxId   ID of the text field
3027 *
3028 * @author Andreas Gohr <[email protected]>
3029 */
3030function currentHeadlineLevel(textboxId){
3031    var field = jQuery('#' + textboxId)[0],
3032        s = false,
3033        opts = [field.value.substr(0,DWgetSelection(field).start)];
3034    if (field.form && field.form.prefix) {
3035        // we need to look in prefix context
3036        opts.push(field.form.prefix.value);
3037    }
3038
3039    jQuery.each(opts, function (_, opt) {
3040        // Check whether there is a headline in the given string
3041        var str = "\n" + opt,
3042            lasthl = str.lastIndexOf("\n==");
3043        if (lasthl !== -1) {
3044            s = str.substr(lasthl+1,6);
3045            return false;
3046        }
3047    });
3048    if (s === false) {
3049        return 0;
3050    }
3051    return 7 - s.match(/^={2,6}/)[0].length;
3052}
3053
3054
3055/**
3056 * global var used for not saved yet warning
3057 */
3058window.textChanged = false;
3059
3060/**
3061 * global var which stores original editor content
3062 */
3063window.doku_edit_text_content = '';
3064/**
3065 * Delete the draft before leaving the page
3066 */
3067function deleteDraft() {
3068    if (is_opera || window.keepDraft) {
3069        return;
3070    }
3071
3072    var $dwform = jQuery('#dw__editform');
3073
3074    if($dwform.length === 0) {
3075        return;
3076    }
3077
3078    // remove a possibly saved draft using ajax
3079    jQuery.post(DOKU_BASE + 'lib/exe/ajax.php',
3080        {
3081            call: 'draftdel',
3082            id: $dwform.find('input[name=id]').val(),
3083            sectok: $dwform.find('input[name=sectok]').val()
3084        }
3085    );
3086}
3087
3088/**
3089 * Activate "not saved" dialog, add draft deletion to page unload,
3090 * add handlers to monitor changes
3091 * Note: textChanged could be set by e.g. html_edit() as well
3092 *
3093 * Sets focus to the editbox as well
3094 */
3095jQuery(function () {
3096    var $editform = jQuery('#dw__editform');
3097    if ($editform.length == 0) {
3098        return;
3099    }
3100
3101    var $edit_text = jQuery('#wiki__text');
3102    if ($edit_text.length > 0) {
3103        if($edit_text.attr('readOnly')) {
3104            return;
3105        }
3106
3107        // set focus and place cursor at the start
3108        var sel = DWgetSelection($edit_text[0]);
3109        sel.start = 0;
3110        sel.end   = 0;
3111        DWsetSelection(sel);
3112        $edit_text.trigger('focus');
3113
3114        doku_edit_text_content = $edit_text.val();
3115    }
3116
3117    var changeHandler = function() {
3118        doku_hasTextBeenModified();
3119
3120        doku_summaryCheck();
3121    };
3122
3123    $editform.change(changeHandler);
3124    $editform.keydown(changeHandler);
3125
3126    window.onbeforeunload = function(){
3127        if(window.textChanged) {
3128            return LANG.notsavedyet;
3129        }
3130    };
3131    window.onunload = deleteDraft;
3132
3133    // reset change memory var on submit
3134    jQuery('#edbtn__save').on('click',
3135        function() {
3136            window.onbeforeunload = '';
3137            textChanged = false;
3138        }
3139    );
3140    jQuery('#edbtn__preview').on('click',
3141        function() {
3142            window.onbeforeunload = '';
3143            textChanged = false;
3144            window.keepDraft = true; // needed to keep draft on page unload
3145        }
3146    );
3147
3148    var $summary = jQuery('#edit__summary');
3149    $summary.on('change keyup', doku_summaryCheck);
3150
3151    if (textChanged) doku_summaryCheck();
3152});
3153
3154/**
3155 * Updates textChanged variable if content of the editor has been modified
3156 */
3157function doku_hasTextBeenModified() {
3158    if (!textChanged) {
3159        var $edit_text = jQuery('#wiki__text');
3160
3161        if ($edit_text.length > 0) {
3162            textChanged = doku_edit_text_content != $edit_text.val();
3163        } else {
3164            textChanged = true;
3165        }
3166    }
3167}
3168
3169/**
3170 * Checks if a summary was entered - if not the style is changed
3171 *
3172 * @author Andreas Gohr <[email protected]>
3173 */
3174function doku_summaryCheck(){
3175    var $sum = jQuery('#edit__summary'),
3176        missing = $sum.val() === '';
3177    $sum.toggleClass('missing', missing).toggleClass('edit', !missing);
3178}
3179
3180
3181
3182/* XXXXXXXXXX end of lib/scripts/edit.js XXXXXXXXXX */
3183
3184
3185
3186/* XXXXXXXXXX begin of lib/scripts/editor.js XXXXXXXXXX */
3187
3188/**
3189 * The DokuWiki editor features
3190 *
3191 * These are the advanced features of the editor. It does NOT contain any
3192 * code for the toolbar buttons and it functions. See toolbar.js for that.
3193 */
3194
3195var dw_editor = {
3196
3197    /**
3198     * initialize the default editor functionality
3199     *
3200     * All other functions can also be called separately for non-default
3201     * textareas
3202     */
3203    init: function(){
3204        var $editor = jQuery('#wiki__text');
3205        if($editor.length === 0) {
3206            return;
3207        }
3208
3209        dw_editor.initSizeCtl('#size__ctl',$editor);
3210
3211        if($editor.attr('readOnly')) {
3212            return;
3213        }
3214
3215        $editor.keydown(dw_editor.keyHandler);
3216
3217    },
3218
3219    /**
3220     * Add the edit window size and wrap controls
3221     *
3222     * Initial values are read from cookie if it exists
3223     *
3224     * @param selector ctlarea the div to place the controls
3225     * @param selector editor  the textarea to control
3226     */
3227    initSizeCtl: function(ctlarea,editor){
3228        var $ctl      = jQuery(ctlarea),
3229            $textarea = jQuery(editor);
3230
3231        if($ctl.length === 0 || $textarea.length === 0) {
3232            return;
3233        }
3234
3235        $textarea.css('height', DokuCookie.getValue('sizeCtl') || '300px');
3236
3237        var wrp = DokuCookie.getValue('wrapCtl');
3238        if(wrp){
3239            dw_editor.setWrap($textarea[0], wrp);
3240        } // else use default value
3241
3242        jQuery.each([
3243            ['larger', function(){dw_editor.sizeCtl(editor,100);}],
3244            ['smaller', function(){dw_editor.sizeCtl(editor,-100);}],
3245            ['wrap', function(){dw_editor.toggleWrap(editor);}]
3246        ], function (_, img) {
3247            jQuery(document.createElement('img'))
3248                .attr('src', DOKU_BASE+'lib/images/' + img[0] + '.gif')
3249                .attr('alt', '')
3250                .on('click', img[1])
3251                .appendTo($ctl);
3252        });
3253    },
3254
3255    /**
3256     * This sets the vertical size of the editbox and adjusts the cookie
3257     *
3258     * @param selector editor  the textarea to control
3259     * @param int val          the relative value to resize in pixel
3260     */
3261    sizeCtl: function(editor,val){
3262        var $textarea = jQuery(editor),
3263            height = parseInt($textarea.css('height')) + val;
3264        $textarea.css('height', height+'px');
3265        DokuCookie.setValue('sizeCtl',$textarea.css('height'));
3266    },
3267
3268    /**
3269     * Toggle the wrapping mode of the editor textarea and adjusts the
3270     * cookie
3271     *
3272     * @param selector editor  the textarea to control
3273     */
3274    toggleWrap: function(editor){
3275        var $textarea = jQuery(editor),
3276            wrap = $textarea.attr('wrap');
3277        dw_editor.setWrap($textarea[0],
3278                          (wrap && wrap.toLowerCase() == 'off') ? 'soft' : 'off');
3279        DokuCookie.setValue('wrapCtl',$textarea.attr('wrap'));
3280    },
3281
3282    /**
3283     * Set the wrapping mode of a textarea
3284     *
3285     * @author Fluffy Convict <[email protected]>
3286     * @author <[email protected]>
3287     * @link   http://news.hping.org/comp.lang.javascript.archive/12265.html
3288     * @link   https://bugzilla.mozilla.org/show_bug.cgi?id=41464
3289     * @param  DomObject textarea
3290     * @param  string wrapAttrValue
3291     */
3292    setWrap: function(textarea, wrapAttrValue){
3293        textarea.setAttribute('wrap', wrapAttrValue);
3294
3295        // Fix display for mozilla
3296        var parNod = textarea.parentNode;
3297        var nxtSib = textarea.nextSibling;
3298        parNod.removeChild(textarea);
3299        parNod.insertBefore(textarea, nxtSib);
3300    },
3301
3302    /**
3303     * Make intended formattings easier to handle
3304     *
3305     * Listens to all key inputs and handle indentions
3306     * of lists and code blocks
3307     *
3308     * Currently handles space, backspace, enter and
3309     * ctrl-enter presses
3310     *
3311     * @author Andreas Gohr <[email protected]>
3312     * @fixme handle tabs
3313     * @param event e - the key press event object
3314     */
3315    keyHandler: function(e){
3316        if(jQuery.inArray(e.keyCode,[8, 10, 13, 32]) === -1) {
3317            return;
3318        }
3319        var selection = DWgetSelection(this);
3320        if(selection.getLength() > 0) {
3321            return; //there was text selected, keep standard behavior
3322        }
3323        var search    = "\n"+this.value.substr(0,selection.start);
3324        var linestart = Math.max(search.lastIndexOf("\n"),
3325                                 search.lastIndexOf("\r")); //IE workaround
3326        search = search.substr(linestart);
3327
3328        if((e.keyCode == 13 || e.keyCode == 10) && e.ctrlKey) { // Ctrl-Enter (With Chrome workaround)
3329            // Submit current edit
3330            jQuery('#edbtn__save').trigger('click');
3331            e.preventDefault(); // prevent enter key
3332            return false;
3333        }else if(e.keyCode == 13){ // Enter
3334            // keep current indention for lists and code
3335            var match = search.match(/(\n  +([\*-] ?)?)/);
3336            if(match){
3337                var scroll = this.scrollHeight;
3338                var match2 = search.match(/^\n  +[\*-]\s*$/);
3339                // Cancel list if the last item is empty (i. e. two times enter)
3340                if (match2 && this.value.substr(selection.start).match(/^($|\r?\n)/)) {
3341                    this.value = this.value.substr(0, linestart) + "\n" +
3342                                 this.value.substr(selection.start);
3343                    selection.start = linestart + 1;
3344                    selection.end = linestart + 1;
3345                    DWsetSelection(selection);
3346                } else {
3347                    insertAtCarret(this.id,match[1]);
3348                }
3349                this.scrollTop += (this.scrollHeight - scroll);
3350                e.preventDefault(); // prevent enter key
3351                return false;
3352            }
3353        }else if(e.keyCode == 8){ // Backspace
3354            // unindent lists
3355            var match = search.match(/(\n  +)([*-] ?)$/);
3356            if(match){
3357                var spaces = match[1].length-1;
3358
3359                if(spaces > 3){ // unindent one level
3360                    this.value = this.value.substr(0,linestart)+
3361                                 this.value.substr(linestart+2);
3362                    selection.start = selection.start - 2;
3363                    selection.end   = selection.start;
3364                }else{ // delete list point
3365                    this.value = this.value.substr(0,linestart)+
3366                                 this.value.substr(selection.start);
3367                    selection.start = linestart;
3368                    selection.end   = linestart;
3369                }
3370                DWsetSelection(selection);
3371                e.preventDefault(); // prevent backspace
3372                return false;
3373            }
3374        }else if(e.keyCode == 32){ // Space
3375            // intend list item
3376            var match = search.match(/(\n  +)([*-] )$/);
3377            if(match){
3378                this.value = this.value.substr(0,linestart)+'  '+
3379                             this.value.substr(linestart);
3380                selection.start = selection.start + 2;
3381                selection.end   = selection.start;
3382                DWsetSelection(selection);
3383                e.preventDefault(); // prevent space
3384                return false;
3385            }
3386        }
3387    }
3388
3389
3390};
3391
3392jQuery(dw_editor.init);
3393
3394
3395
3396/* XXXXXXXXXX end of lib/scripts/editor.js XXXXXXXXXX */
3397
3398
3399
3400/* XXXXXXXXXX begin of lib/scripts/locktimer.js XXXXXXXXXX */
3401
3402/**
3403 * Class managing the timer to display a warning on a expiring lock
3404 */
3405var dw_locktimer = {
3406    timeout: 0,
3407    draft: false,
3408    timerID: null,
3409    lasttime: null,
3410    msg: LANG.willexpire,
3411    pageid: '',
3412    fieldsToSaveAsDraft: [
3413        'input[name=prefix]',
3414        'textarea[name=wikitext]',
3415        'input[name=suffix]',
3416        'input[name=date]',
3417    ],
3418    callbacks: [],
3419
3420    /**
3421     * Initialize the lock timer
3422     *
3423     * @param {int}    timeout Length of timeout in seconds
3424     * @param {bool}   draft   Whether to save drafts
3425     * @param {string} edid    Optional; ID of an edit object which has to be present
3426     */
3427    init: function(timeout,draft,edid){
3428        var $edit;
3429
3430        edid = edid || 'wiki__text';
3431
3432        $edit = jQuery('#' + edid);
3433        if($edit.length === 0 || $edit.attr('readonly')) {
3434            return;
3435        }
3436
3437        // init values
3438        dw_locktimer.timeout  = timeout*1000;
3439        dw_locktimer.draft    = draft;
3440        dw_locktimer.lasttime = new Date();
3441
3442        dw_locktimer.pageid   = jQuery('#dw__editform').find('input[name=id]').val();
3443        if(!dw_locktimer.pageid) {
3444            return;
3445        }
3446
3447        // register refresh event
3448        $edit.keypress(dw_locktimer.refresh);
3449        // start timer
3450        dw_locktimer.reset();
3451    },
3452
3453    /**
3454     * Add another field of the editform to be posted to the server when a draft is saved
3455     */
3456    addField: function(selector) {
3457        dw_locktimer.fieldsToSaveAsDraft.push(selector);
3458    },
3459
3460    /**
3461     * Add a callback that is executed when the post request to renew the lock and save the draft returns successfully
3462     *
3463     * If the user types into the edit-area, then dw_locktimer will regularly send a post request to the DokuWiki server
3464     * to extend the page's lock and update the draft. When this request returns successfully, then the draft__status
3465     * is updated. This method can be used to add further callbacks to be executed at that moment.
3466     *
3467     * @param {function} callback the only param is the data returned by the server
3468     */
3469    addRefreshCallback: function(callback) {
3470        dw_locktimer.callbacks.push(callback);
3471    },
3472
3473    /**
3474     * (Re)start the warning timer
3475     */
3476    reset: function(){
3477        dw_locktimer.clear();
3478        dw_locktimer.timerID = window.setTimeout(dw_locktimer.warning, dw_locktimer.timeout);
3479    },
3480
3481    /**
3482     * Display the warning about the expiring lock
3483     */
3484    warning: function(){
3485        dw_locktimer.clear();
3486        alert(fixtxt(dw_locktimer.msg));
3487    },
3488
3489    /**
3490     * Remove the current warning timer
3491     */
3492    clear: function(){
3493        if(dw_locktimer.timerID !== null){
3494            window.clearTimeout(dw_locktimer.timerID);
3495            dw_locktimer.timerID = null;
3496        }
3497    },
3498
3499    /**
3500     * Refresh the lock via AJAX
3501     *
3502     * Called on keypresses in the edit area
3503     */
3504    refresh: function(){
3505        var now = new Date(),
3506            params = 'call=lock&id=' + dw_locktimer.pageid + '&';
3507
3508        // refresh every half minute only
3509        if(now.getTime() - dw_locktimer.lasttime.getTime() <= 30*1000) {
3510            return;
3511        }
3512
3513        // POST everything necessary for draft saving
3514        if(dw_locktimer.draft && jQuery('#dw__editform').find('textarea[name=wikitext]').length > 0){
3515            params += jQuery('#dw__editform').find(dw_locktimer.fieldsToSaveAsDraft.join(', ')).serialize();
3516        }
3517
3518        jQuery.post(
3519            DOKU_BASE + 'lib/exe/ajax.php',
3520            params,
3521            null,
3522            'json'
3523        ).done(function dwLocktimerRefreshDoneHandler(data) {
3524            dw_locktimer.callbacks.forEach(
3525                function (callback) {
3526                    callback(data);
3527                }
3528            );
3529        });
3530        dw_locktimer.lasttime = now;
3531    },
3532
3533    /**
3534     * Callback. Resets the warning timer
3535     */
3536    refreshed: function(data){
3537        if (data.errors.length) {
3538            data.errors.forEach(function(error) {
3539                jQuery('#draft__status').after(
3540                    jQuery('<div class="error"></div>').text(error)
3541                );
3542            })
3543        }
3544
3545        jQuery('#draft__status').html(data.draft);
3546        if(data.lock !== '1') {
3547            return; // locking failed
3548        }
3549        dw_locktimer.reset();
3550    }
3551};
3552dw_locktimer.callbacks.push(dw_locktimer.refreshed);
3553
3554
3555
3556/* XXXXXXXXXX end of lib/scripts/locktimer.js XXXXXXXXXX */
3557
3558
3559
3560/* XXXXXXXXXX begin of lib/scripts/linkwiz.js XXXXXXXXXX */
3561
3562/**
3563 * The Link Wizard
3564 *
3565 * @author Andreas Gohr <[email protected]>
3566 * @author Pierre Spring <[email protected]>
3567 */
3568var dw_linkwiz = {
3569    $wiz: null,
3570    $entry: null,
3571    result: null,
3572    timer: null,
3573    textArea: null,
3574    selected: null,
3575    selection: null,
3576
3577    /**
3578     * Initialize the dw_linkwizard by creating the needed HTML
3579     * and attaching the eventhandlers
3580     */
3581    init: function($editor){
3582        // position relative to the text area
3583        var pos = $editor.position();
3584
3585        // create HTML Structure
3586        if(dw_linkwiz.$wiz)
3587            return;
3588        dw_linkwiz.$wiz = jQuery(document.createElement('div'))
3589               .dialog({
3590                   autoOpen: false,
3591                   draggable: true,
3592                   title: LANG.linkwiz,
3593                   resizable: false
3594               })
3595               .html(
3596                    '<div>'+LANG.linkto+' <input type="text" class="edit" id="link__wiz_entry" autocomplete="off" /></div>'+
3597                    '<div id="link__wiz_result"></div>'
3598                    )
3599               .parent()
3600               .attr('id','link__wiz')
3601               .css({
3602                    'position':    'absolute',
3603                    'top':         (pos.top+20)+'px',
3604                    'left':        (pos.left+80)+'px'
3605                   })
3606               .hide()
3607               .appendTo('.dokuwiki:first');
3608
3609        dw_linkwiz.textArea = $editor[0];
3610        dw_linkwiz.result = jQuery('#link__wiz_result')[0];
3611
3612        // scrollview correction on arrow up/down gets easier
3613        jQuery(dw_linkwiz.result).css('position', 'relative');
3614
3615        dw_linkwiz.$entry = jQuery('#link__wiz_entry');
3616        if(JSINFO.namespace){
3617            dw_linkwiz.$entry.val(JSINFO.namespace+':');
3618        }
3619
3620        // attach event handlers
3621        jQuery('#link__wiz .ui-dialog-titlebar-close').on('click', dw_linkwiz.hide);
3622        dw_linkwiz.$entry.keyup(dw_linkwiz.onEntry);
3623        jQuery(dw_linkwiz.result).on('click', 'a', dw_linkwiz.onResultClick);
3624    },
3625
3626    /**
3627     * handle all keyup events in the entry field
3628     */
3629    onEntry: function(e){
3630        if(e.keyCode == 37 || e.keyCode == 39){ //left/right
3631            return true; //ignore
3632        }
3633        if(e.keyCode == 27){ //Escape
3634            dw_linkwiz.hide();
3635            e.preventDefault();
3636            e.stopPropagation();
3637            return false;
3638        }
3639        if(e.keyCode == 38){ //Up
3640            dw_linkwiz.select(dw_linkwiz.selected -1);
3641            e.preventDefault();
3642            e.stopPropagation();
3643            return false;
3644        }
3645        if(e.keyCode == 40){ //Down
3646            dw_linkwiz.select(dw_linkwiz.selected +1);
3647            e.preventDefault();
3648            e.stopPropagation();
3649            return false;
3650        }
3651        if(e.keyCode == 13){ //Enter
3652            if(dw_linkwiz.selected > -1){
3653                var $obj = dw_linkwiz.$getResult(dw_linkwiz.selected);
3654                if($obj.length > 0){
3655                    dw_linkwiz.resultClick($obj.find('a')[0]);
3656                }
3657            }else if(dw_linkwiz.$entry.val()){
3658                dw_linkwiz.insertLink(dw_linkwiz.$entry.val());
3659            }
3660
3661            e.preventDefault();
3662            e.stopPropagation();
3663            return false;
3664        }
3665        dw_linkwiz.autocomplete();
3666    },
3667
3668    /**
3669     * Get one of the results by index
3670     *
3671     * @param   num int result div to return
3672     * @returns DOMObject or null
3673     */
3674    getResult: function(num){
3675        DEPRECATED('use dw_linkwiz.$getResult()[0] instead');
3676        return dw_linkwiz.$getResult()[0] || null;
3677    },
3678
3679    /**
3680     * Get one of the results by index
3681     *
3682     * @param   num int result div to return
3683     * @returns jQuery object
3684     */
3685    $getResult: function(num) {
3686        return jQuery(dw_linkwiz.result).find('div').eq(num);
3687    },
3688
3689    /**
3690     * Select the given result
3691     */
3692    select: function(num){
3693        if(num < 0){
3694            dw_linkwiz.deselect();
3695            return;
3696        }
3697
3698        var $obj = dw_linkwiz.$getResult(num);
3699        if ($obj.length === 0) {
3700            return;
3701        }
3702
3703        dw_linkwiz.deselect();
3704        $obj.addClass('selected');
3705
3706        // make sure the item is viewable in the scroll view
3707
3708        //getting child position within the parent
3709        var childPos = $obj.position().top;
3710        //getting difference between the childs top and parents viewable area
3711        var yDiff = childPos + $obj.outerHeight() - jQuery(dw_linkwiz.result).innerHeight();
3712
3713        if (childPos < 0) {
3714            //if childPos is above viewable area (that's why it goes negative)
3715            jQuery(dw_linkwiz.result)[0].scrollTop += childPos;
3716        } else if(yDiff > 0) {
3717            // if difference between childs top and parents viewable area is
3718            // greater than the height of a childDiv
3719            jQuery(dw_linkwiz.result)[0].scrollTop += yDiff;
3720        }
3721
3722        dw_linkwiz.selected = num;
3723    },
3724
3725    /**
3726     * deselect a result if any is selected
3727     */
3728    deselect: function(){
3729        if(dw_linkwiz.selected > -1){
3730            dw_linkwiz.$getResult(dw_linkwiz.selected).removeClass('selected');
3731        }
3732        dw_linkwiz.selected = -1;
3733    },
3734
3735    /**
3736     * Handle clicks in the result set an dispatch them to
3737     * resultClick()
3738     */
3739    onResultClick: function(e){
3740        if(!jQuery(this).is('a')) {
3741            return;
3742        }
3743        e.stopPropagation();
3744        e.preventDefault();
3745        dw_linkwiz.resultClick(this);
3746        return false;
3747    },
3748
3749    /**
3750     * Handles the "click" on a given result anchor
3751     */
3752    resultClick: function(a){
3753        dw_linkwiz.$entry.val(a.title);
3754        if(a.title == '' || a.title.substr(a.title.length-1) == ':'){
3755            dw_linkwiz.autocomplete_exec();
3756        }else{
3757            if (jQuery(a.nextSibling).is('span')) {
3758                dw_linkwiz.insertLink(a.nextSibling.innerHTML);
3759            }else{
3760                dw_linkwiz.insertLink('');
3761            }
3762        }
3763    },
3764
3765    /**
3766     * Insert the id currently in the entry box to the textarea,
3767     * replacing the current selection or at the cursor position.
3768     * When no selection is available the given title will be used
3769     * as link title instead
3770     */
3771    insertLink: function(title){
3772        var link = dw_linkwiz.$entry.val(),
3773            sel, stxt;
3774        if(!link) {
3775            return;
3776        }
3777
3778        sel = DWgetSelection(dw_linkwiz.textArea);
3779        if(sel.start == 0 && sel.end == 0) {
3780            sel = dw_linkwiz.selection;
3781        }
3782
3783        stxt = sel.getText();
3784
3785        // don't include trailing space in selection
3786        if(stxt.charAt(stxt.length - 1) == ' '){
3787            sel.end--;
3788            stxt = sel.getText();
3789        }
3790
3791        if(!stxt && !DOKU_UHC) {
3792            stxt=title;
3793        }
3794
3795        // prepend colon inside namespaces for non namespace pages
3796        if(dw_linkwiz.textArea.form.id.value.indexOf(':') != -1 &&
3797           link.indexOf(':') == -1){
3798           link = ':' + link;
3799        }
3800
3801        var so = link.length;
3802        var eo = 0;
3803        if(dw_linkwiz.val){
3804            if(dw_linkwiz.val.open) {
3805                so += dw_linkwiz.val.open.length;
3806                link = dw_linkwiz.val.open+link;
3807            }
3808            link += '|';
3809            so += 1;
3810            if(stxt) {
3811                link += stxt;
3812            }
3813            if(dw_linkwiz.val.close) {
3814                link += dw_linkwiz.val.close;
3815                eo = dw_linkwiz.val.close.length;
3816            }
3817        }
3818
3819        pasteText(sel,link,{startofs: so, endofs: eo});
3820        dw_linkwiz.hide();
3821
3822        // reset the entry to the parent namespace
3823        var externallinkpattern = new RegExp('^((f|ht)tps?:)?//', 'i'),
3824            entry_value;
3825        if (externallinkpattern.test(dw_linkwiz.$entry.val())) {
3826            if (JSINFO.namespace) {
3827                entry_value = JSINFO.namespace + ':';
3828            } else {
3829                entry_value = ''; //reset whole external links
3830            }
3831        } else {
3832            entry_value = dw_linkwiz.$entry.val().replace(/[^:]*$/, '')
3833        }
3834        dw_linkwiz.$entry.val(entry_value);
3835    },
3836
3837    /**
3838     * Start the page/namespace lookup timer
3839     *
3840     * Calls autocomplete_exec when the timer runs out
3841     */
3842    autocomplete: function(){
3843        if(dw_linkwiz.timer !== null){
3844            window.clearTimeout(dw_linkwiz.timer);
3845            dw_linkwiz.timer = null;
3846        }
3847
3848        dw_linkwiz.timer = window.setTimeout(dw_linkwiz.autocomplete_exec,350);
3849    },
3850
3851    /**
3852     * Executes the AJAX call for the page/namespace lookup
3853     */
3854    autocomplete_exec: function(){
3855        var $res = jQuery(dw_linkwiz.result);
3856        dw_linkwiz.deselect();
3857        $res.html('<img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="" width="16" height="16" />')
3858            .load(
3859            DOKU_BASE + 'lib/exe/ajax.php',
3860            {
3861                call: 'linkwiz',
3862                q: dw_linkwiz.$entry.val()
3863            }
3864        );
3865    },
3866
3867    /**
3868     * Show the link wizard
3869     */
3870    show: function(){
3871        dw_linkwiz.selection  = DWgetSelection(dw_linkwiz.textArea);
3872        dw_linkwiz.$wiz.show();
3873        dw_linkwiz.$entry.focus();
3874        dw_linkwiz.autocomplete();
3875
3876        // Move the cursor to the end of the input
3877        var temp = dw_linkwiz.$entry.val();
3878        dw_linkwiz.$entry.val('');
3879        dw_linkwiz.$entry.val(temp);
3880    },
3881
3882    /**
3883     * Hide the link wizard
3884     */
3885    hide: function(){
3886        dw_linkwiz.$wiz.hide();
3887        dw_linkwiz.textArea.focus();
3888    },
3889
3890    /**
3891     * Toggle the link wizard
3892     */
3893    toggle: function(){
3894        if(dw_linkwiz.$wiz.css('display') == 'none'){
3895            dw_linkwiz.show();
3896        }else{
3897            dw_linkwiz.hide();
3898        }
3899    }
3900};
3901
3902
3903
3904/* XXXXXXXXXX end of lib/scripts/linkwiz.js XXXXXXXXXX */
3905
3906
3907
3908/* XXXXXXXXXX begin of lib/scripts/media.js XXXXXXXXXX */
3909
3910/**
3911 * JavaScript functionality for the media management popup
3912 *
3913 * @author Andreas Gohr <[email protected]>
3914 * @author Pierre Spring <[email protected]>
3915 */
3916
3917var dw_mediamanager = {
3918    keepopen: false,
3919    hide: false,
3920    popup: false,
3921    display: false,
3922    ext: false,
3923    $popup: null,
3924
3925    // Image insertion opts
3926    align: false,
3927    link: false,
3928    size: false,
3929    forbidden_opts: {},
3930
3931    // File list options
3932    view_opts: {list: false, sort: false},
3933
3934    layout_width: 0,
3935
3936    // The minimum height of the full-screen mediamanager in px
3937    minHeights: {thumbs: 200, rows: 100},
3938
3939    init: function () {
3940        var $content, $tree;
3941        $content = jQuery('#media__content');
3942        $tree = jQuery('#media__tree');
3943        if (!$tree.length) return;
3944
3945        dw_mediamanager.prepare_content($content);
3946
3947        dw_mediamanager.attachoptions();
3948        dw_mediamanager.initpopup();
3949
3950        // add the action to autofill the "upload as" field
3951        $content
3952            .on('change', '#upload__file', dw_mediamanager.suggest)
3953            // Attach the image selector action to all links
3954            .on('click', 'a.select', dw_mediamanager.select)
3955            // Attach deletion confirmation dialog to the delete buttons
3956            .on('click', '#media__content a.btn_media_delete', dw_mediamanager.confirmattach)
3957            .on('submit', '#mediamanager__done_form', dw_mediamanager.list);
3958
3959        $tree.dw_tree({
3960            toggle_selector: 'img',
3961            load_data: function (show_sublist, $clicky) {
3962                // get the enclosed link (is always the first one)
3963                var $link = $clicky.parent().find('div.li a.idx_dir');
3964
3965                jQuery.post(
3966                    DOKU_BASE + 'lib/exe/ajax.php',
3967                    $link[0].search.substr(1) + '&call=medians',
3968                    show_sublist,
3969                    'html'
3970                );
3971            },
3972
3973            toggle_display: function ($clicky, opening) {
3974                $clicky.attr('src', DOKU_BASE + 'lib/images/' + (opening ? 'minus' : 'plus') + '.g
3974if');
3975            }
3976        });
3977        $tree.on('click', 'a', dw_mediamanager.list);
3978
3979        // Init view property
3980        dw_mediamanager.set_fileview_list();
3981
3982        dw_mediamanager.init_options();
3983
3984        dw_mediamanager.image_diff();
3985        dw_mediamanager.init_ajax_uploader();
3986
3987        // changing opened tab in the file list panel
3988        var $page = jQuery('#mediamanager__page');
3989        $page.find('div.filelist')
3990            .on('click', 'ul.tabs a', dw_mediamanager.list)
3991            // loading file details
3992            .on('click', 'div.panelContent a', dw_mediamanager.details)
3993            // search form
3994            .on('submit', '#dw__mediasearch', dw_mediamanager.list)
3995            // "upload as" field autofill
3996            .on('change', '#upload__file', dw_mediamanager.suggest)
3997            // uploaded images
3998            .on('click', '.qq-upload-file a', dw_mediamanager.details);
3999
4000        // changing opened tab in the file details panel
4001        $page.find('div.file')
4002            .on('click', 'ul.tabs a', dw_mediamanager.details)
4003            // "update new version" button
4004            .on('submit', '#mediamanager__btn_update', dw_mediamanager.list)
4005            // revisions form
4006            .on('submit', '#page__revisions', dw_mediamanager.details)
4007            .on('click', '#page__revisions a', dw_mediamanager.details)
4008            // meta edit form
4009            .on('submit', '#mediamanager__save_meta', dw_mediamanager.details)
4010            // delete button
4011            .on('submit', '#mediamanager__btn_delete', dw_mediamanager.details)
4012            // "restore this version" button
4013            .on('submit', '#mediamanager__btn_restore', dw_mediamanager.details)
4014            // less/more recent buttons in media revisions form
4015            .on('submit', '.btn_newer, .btn_older', dw_mediamanager.details);
4016
4017        dw_mediamanager.update_resizable();
4018        dw_mediamanager.layout_width = $page.width();
4019        jQuery(window).on('resize', dw_mediamanager.window_resize);
4020    },
4021
4022    init_options: function () {
4023        var $options = jQuery('div.filelist div.panelHeader form.options'),
4024            $listType, $sortBy, $both;
4025        if ($options.length === 0) {
4026            return;
4027        }
4028
4029        $listType = $options.find('li.listType');
4030        $sortBy = $options.find('li.sortBy');
4031        $both = $listType.add($sortBy);
4032
4033        // Remove the submit button
4034        $options.find('button[type=submit]').parent().hide();
4035
4036        // Prepare HTML for jQuery UI buttonset
4037        $both.find('label').each(function () {
4038            var $this = jQuery(this);
4039            $this.children('input').appendTo($this.parent());
4040        });
4041
4042        // Init buttonset
4043        $both.find("input[type='radio']").checkboxradio({icon: false});
4044        $both.controlgroup();
4045
4046        // Change handlers
4047        $listType.children('input').change(function () {
4048            dw_mediamanager.set_fileview_list();
4049        });
4050        $sortBy.children('input').change(function (event) {
4051            dw_mediamanager.set_fileview_sort();
4052            dw_mediamanager.list.call(jQuery('#dw__mediasearch')[0] || this, event);
4053        });
4054    },
4055
4056    /**
4057     * build the popup window
4058     *
4059     * @author Dominik Eckelmann <[email protected]>
4060     */
4061    initpopup: function () {
4062        var opts, $insp, $insbtn;
4063
4064        dw_mediamanager.$popup = jQuery(document.createElement('div'))
4065            .attr('id', 'media__popup_content')
4066            .dialog({
4067                autoOpen: false, width: 280, modal: true,
4068                draggable: true, title: LANG.mediatitle,
4069                resizable: false
4070            });
4071
4072        opts = [
4073            {
4074                id: 'link', label: LANG.mediatarget,
4075                btns: ['lnk', 'direct', 'nolnk', 'displaylnk']
4076            },
4077            {
4078                id: 'align', label: LANG.mediaalign,
4079                btns: ['noalign', 'left', 'center', 'right']
4080            },
4081            {
4082                id: 'size', label: LANG.mediasize,
4083                btns: ['small', 'medium', 'large', 'original']
4084            }
4085        ];
4086
4087        jQuery.each(opts, function (_, opt) {
4088            var $p, $l;
4089            $p = jQuery(document.createElement('p'))
4090                .attr('id', 'media__' + opt.id);
4091
4092            if (dw_mediamanager.display === "2") {
4093                $p.hide();
4094            }
4095
4096            $l = jQuery(document.createElement('label'))
4097                .text(opt.label);
4098            $p.append($l);
4099
4100            jQuery.each(opt.btns, function (i, text) {
4101                var $btn, $img;
4102                $btn = jQuery(document.createElement('button'))
4103                    .addClass('button')
4104                    .attr('id', "media__" + opt.id + "btn" + (i + 1))
4105                    .attr('title', LANG['media' + text])
4106                    .on('click', bind(dw_mediamanager.setOpt, opt.id));
4107
4108                $img = jQuery(document.createElement('img'))
4109                    .attr('src', DOKU_BASE + 'lib/images/media_' + opt.id + '_' + text + '.png');
4110
4111                $btn.append($img);
4112                $p.append($btn);
4113            });
4114
4115            dw_mediamanager.$popup.append($p);
4116        });
4117
4118        // insert button
4119        $insp = jQuery(document.createElement('p'));
4120        dw_mediamanager.$popup.append($insp);
4121
4122        $insbtn = jQuery(document.createElement('input'))
4123            .attr('id', 'media__sendbtn')
4124            .attr('type', 'button')
4125            .addClass('button')
4126            .val(LANG.mediainsert);
4127        $insp.append($insbtn);
4128    },
4129
4130    /**
4131     * Insert the clicked image into the opener's textarea
4132     *
4133     * @author Andreas Gohr <[email protected]>
4134     * @author Dominik Eckelmann <[email protected]>
4135     * @author Pierre Spring <[email protected]>
4136     */
4137    insert: function (id) {
4138        var opts, cb, edid, s;
4139
4140        // set syntax options
4141        dw_mediamanager.$popup.dialog('close');
4142
4143        opts = '';
4144
4145        if ({img: 1, swf: 1}[dw_mediamanager.ext] === 1) {
4146
4147            if (dw_mediamanager.link === '4') {
4148                opts = '?linkonly';
4149            } else {
4150
4151                if (dw_mediamanager.link === "3" && dw_mediamanager.ext === 'img') {
4152                    opts = '?nolink';
4153                } else if (dw_mediamanager.link === "2" && dw_mediamanager.ext === 'img') {
4154                    opts = '?direct';
4155                }
4156
4157                s = parseInt(dw_mediamanager.size, 10);
4158                var size = s * 200;
4159
4160                if (s && s >= 1 && s < 4) {
4161                    opts += (opts.length) ? '&' : '?';
4162                    opts += size;
4163                    if (dw_mediamanager.ext === 'swf') {
4164                        switch (s) {
4165                            case 1:
4166                                opts += 'x62';
4167                                break;
4168                            case 2:
4169                                opts += 'x123';
4170                                break;
4171                            case 3:
4172                                opts += 'x185';
4173                                break;
4174                        }
4175                    }
4176                }
4177            }
4178        }
4179        edid = String.prototype.match.call(document.location, /&edid=([^&]+)/);
4180        edid = edid ? edid[1] : 'wiki__text';
4181        cb = String.prototype.match.call(document.location, /&onselect=([^&]+)/);
4182        cb = cb ? cb[1].replace(/[^\w]+/, '') : 'dw_mediamanager_item_select';
4183
4184        // arguments here only match the dw_mediamanager_item_select function, these will need to change if you override cb with onselect GET param
4185        opener[cb](edid, id, opts, dw_mediamanager.align, dw_mediamanager.keepopen);
4186        if (!dw_mediamanager.keepopen) {
4187            window.close();
4188        }
4189        opener.focus();
4190        return false;
4191    },
4192
4193
4194    /**
4195     * Prefills the wikiname.
4196     *
4197     * @author Andreas Gohr <[email protected]>
4198     */
4199    suggest: function () {
4200        var $file, $name, text;
4201
4202        $file = jQuery(this);
4203        $name = jQuery('#upload__name');
4204
4205        if ($name.val() != '') return;
4206
4207        if (!$file.length || !$name.length) {
4208            return;
4209        }
4210
4211        text = $file.val();
4212        text = text.substr(text.lastIndexOf('/') + 1);
4213        text = text.substr(text.lastIndexOf('\\') + 1);
4214        $name.val(text);
4215    },
4216
4217    /**
4218     * list the content of a namespace using AJAX
4219     *
4220     * @author Andreas Gohr <[email protected]>
4221     * @author Pierre Spring <[email protected]>
4222     */
4223    list: function (event) {
4224        var $link, $content, params;
4225
4226        if (event) {
4227            event.preventDefault();
4228        }
4229
4230        jQuery('div.success, div.info, div.error, div.notify').remove();
4231
4232        $link = jQuery(this);
4233
4234        //popup
4235        $content = jQuery('#media__content');
4236
4237        if ($content.length === 0) {
4238            //fullscreen media manager
4239            $content = jQuery('div.filelist');
4240
4241            if ($link.hasClass('idx_dir')) {
4242                //changing namespace
4243                jQuery('div.file').empty();
4244                jQuery('div.namespaces .selected').removeClass('selected');
4245                $link.addClass('selected');
4246            }
4247        }
4248
4249        params = 'call=medialist&';
4250
4251        if ($link[0].search) {
4252            params += $link[0].search.substr(1);
4253        } else if ($link.is('form')) {
4254            params += dw_mediamanager.form_params($link);
4255        } else if ($link.closest('form').length > 0) {
4256            params += dw_mediamanager.form_params($link.closest('form'));
4257        }
4258
4259        // fetch the subtree
4260        dw_mediamanager.update_content($content, params);
4261    },
4262
4263    /**
4264     * Returns form parameters
4265     *
4266     * @author Kate Arzamastseva <[email protected]>
4267     */
4268    form_params: function ($form) {
4269        if (!$form.length) return;
4270
4271        var action = '';
4272        var i = $form[0].action.indexOf('?');
4273        if (i >= 0) {
4274            action = $form[0].action.substr(i + 1);
4275        }
4276        return action + '&' + $form.serialize();
4277    },
4278
4279    set_fileview_list: function (new_type) {
4280        dw_mediamanager.set_fileview_opt(['list', 'listType', function (new_type) {
4281            jQuery('div.filelist div.panelContent ul')
4282                .toggleClass('rows', new_type === 'rows')
4283                .toggleClass('thumbs', new_type === 'thumbs');
4284        }], new_type);
4285
4286        // FIXME: Move to onchange handler (opt[2])?
4287        dw_mediamanager.resize();
4288    },
4289
4290    set_fileview_sort: function (new_sort) {
4291        dw_mediamanager.set_fileview_opt(['sort', 'sortBy', function (new_sort) {
4292            // FIXME
4293        }], new_sort);
4294    },
4295
4296    set_fileview_opt: function (opt, new_val) {
4297        if (typeof new_val === 'undefined') {
4298            new_val = jQuery('form.options li.' + opt[1] + ' input')
4299                .filter(':checked').val();
4300            // if new_val is still undefined (because form.options is not in active tab), set to most spacious option
4301            if (typeof new_val === 'undefined') {
4302                new_val = 'thumbs';
4303            }
4304        }
4305
4306        if (new_val !== dw_mediamanager.view_opts[opt[0]]) {
4307            opt[2](new_val);
4308
4309            DokuCookie.setValue(opt[0], new_val);
4310
4311            dw_mediamanager.view_opts[opt[0]] = new_val;
4312        }
4313    },
4314
4315    /**
4316     * Lists the content of the right column (image details) using AJAX
4317     *
4318     * @author Kate Arzamastseva <[email protected]>
4319     */
4320    details: function (event) {
4321        var $link, $content, params, update_list;
4322        $link = jQuery(this);
4323        event.preventDefault();
4324
4325        jQuery('div.success, div.info, div.error, div.notify').remove();
4326
4327        if ($link[0].id == 'mediamanager__btn_delete' && !confirm(LANG.del_confirm)) {
4328            return false;
4329        }
4330        if ($link[0].id == 'mediamanager__btn_restore' && !confirm(LANG.restore_confirm)) {
4331            return false;
4332        }
4333
4334        $content = jQuery('div.file');
4335        params = 'call=mediadetails&';
4336
4337        if ($link[0].search) {
4338            params += $link[0].search.substr(1);
4339        } else if ($link.is('form')) {
4340            params += dw_mediamanager.form_params($link);
4341        } else if ($link.closest('form').length > 0) {
4342            params += dw_mediamanager.form_params($link.closest('form'));
4343        }
4344
4345        update_list = ($link[0].id == 'mediamanager__btn_delete' ||
4346        $link[0].id == 'mediamanager__btn_restore');
4347
4348        dw_mediamanager.update_content($content, params, update_list);
4349    },
4350
4351    update_content: function ($content, params, update_list) {
4352        var $container;
4353
4354        jQuery.post(
4355            DOKU_BASE + 'lib/exe/ajax.php',
4356            params,
4357            function (data) {
4358                dw_mediamanager.$resizables().resizable('destroy');
4359
4360                if (update_list) {
4361                    dw_mediamanager.list.call(jQuery('#mediamanager__page').find('form.options button[type="submit"]')[0]);
4362                }
4363
4364                $content.html(data);
4365
4366                dw_mediamanager.prepare_content($content);
4367                dw_mediamanager.updatehide();
4368
4369                dw_mediamanager.update_resizable();
4370                dw_behaviour.revisionBoxHandler();
4371
4372                // Make sure that the list view style stays the same
4373                dw_mediamanager.set_fileview_list(dw_mediamanager.view_opts.list);
4374
4375                dw_mediamanager.image_diff();
4376                dw_mediamanager.init_ajax_uploader();
4377                dw_mediamanager.init_options();
4378
4379            },
4380            'html'
4381        );
4382        $container = $content.find('div.panelContent');
4383        if ($container.length === 0) {
4384            $container = $content;
4385        }
4386        $container.html('<img src="' + DOKU_BASE + 'lib/images/throbber.gif" alt="..." class="load" />');
4387    },
4388
4389    window_resize: function () {
4390        dw_mediamanager.resize();
4391
4392        dw_mediamanager.opacity_slider();
4393        dw_mediamanager.portions_slider();
4394    },
4395
4396    $resizables: function () {
4397        return jQuery('#mediamanager__page').find('div.namespaces, div.filelist');
4398    },
4399
4400    /**
4401     * Updates mediamanager layout
4402     *
4403     * @author Kate Arzamastseva <[email protected]>
4404     */
4405    update_resizable: function () {
4406        var $resizables = dw_mediamanager.$resizables();
4407
4408        $resizables.resizable({
4409            handles: (jQuery('html[dir=rtl]').length ? 'w' : 'e'),
4410            resize: function (event, ui) {
4411                var $page = jQuery('#mediamanager__page');
4412                var widthFull = $page.width();
4413                var widthResizables = 0;
4414                $resizables.each(function () {
4415                    widthResizables += jQuery(this).width();
4416                });
4417                var $filePanel = $page.find('div.panel.file');
4418
4419                // set max width of resizable column
4420                var widthOtherResizable = widthResizables - jQuery(this).width();
4421                var minWidthNonResizable = parseFloat($filePanel.css("min-width"));
4422                var maxWidth = widthFull - (widthOtherResizable + minWidthNonResizable) - 1;
4423                $resizables.resizable("option", "maxWidth", maxWidth);
4424
4425                // width of file panel in % = 100% - width of resizables in %
4426                // this calculates with 99.9 and not 100 to overcome rounding errors
4427                var relWidthNonResizable = 99.9 - (100 * widthResizables / widthFull);
4428                // set width of file panel
4429                $filePanel.width(relWidthNonResizable + '%');
4430
4431                dw_mediamanager.resize();
4432
4433                dw_mediamanager.opacity_slider();
4434                dw_mediamanager.portions_slider();
4435            }
4436        });
4437
4438        dw_mediamanager.resize();
4439    },
4440
4441    resize: function () {
4442        var $contents = jQuery('#mediamanager__page').find('div.panelContent'),
4443            height = jQuery(window).height() - jQuery(document.body).height() +
4444                Math.max.apply(null, jQuery.map($contents, function (v) {
4445                    return jQuery(v).height();
4446                }));
4447
4448        // If the screen is too small, don’t try to resize
4449        if (height < dw_mediamanager.minHeights[dw_mediamanager.view_opts.list]) {
4450            $contents.add(dw_mediamanager.$resizables()).height('auto');
4451        } else {
4452            $contents.height(height);
4453            dw_mediamanager.$resizables().each(function () {
4454                var $this = jQuery(this);
4455                $this.height(height + $this.find('div.panelContent').offset().top - $this.offset().top);
4456            });
4457        }
4458    },
4459
4460    /**
4461     * Prints 'select' for image difference representation type
4462     *
4463     * @author Kate Arzamastseva <[email protected]>
4464     */
4465    image_diff: function () {
4466        if (jQuery('#mediamanager__difftype').length) return;
4467
4468        var $form = jQuery('#mediamanager__form_diffview');
4469        if (!$form.length) return;
4470
4471        var $label = jQuery(document.createElement('label'));
4472        $label.append('<span>' + LANG.media_diff + '</span> ');
4473        var $select = jQuery(document.createElement('select'))
4474            .attr('id', 'mediamanager__difftype')
4475            .attr('name', 'difftype')
4476            .change(dw_mediamanager.change_diff_type);
4477        $select.append(new Option(LANG.media_diff_both, "both"));
4478        $select.append(new Option(LANG.media_diff_opacity, "opacity"));
4479        $select.append(new Option(LANG.media_diff_portions, "portions"));
4480        $label.append($select);
4481        $form.append($label);
4482
4483        // for IE
4484        var select = document.getElementById('mediamanager__difftype');
4485        select.options[0].text = LANG.media_diff_both;
4486        select.options[1].text = LANG.media_diff_opacity;
4487        select.options[2].text = LANG.media_diff_portions;
4488    },
4489
4490    /**
4491     * Handles selection of image difference representation type
4492     *
4493     * @author Kate Arzamastseva <[email protected]>
4494     */
4495    change_diff_type: function () {
4496        var $select = jQuery('#mediamanager__difftype');
4497        var $content = jQuery('#mediamanager__diff');
4498
4499        var params = dw_mediamanager.form_params($select.closest('form')) + '&call=mediadiff';
4500        jQuery.post(
4501            DOKU_BASE + 'lib/exe/ajax.php',
4502            params,
4503            function (data) {
4504                $content.html(data);
4505                dw_mediamanager.portions_slider();
4506                dw_mediamanager.opacity_slider();
4507            },
4508            'html'
4509        );
4510    },
4511
4512    /**
4513     * Sets options for opacity diff slider
4514     *
4515     * @author Kate Arzamastseva <[email protected]>
4516     */
4517    opacity_slider: function () {
4518        var $diff = jQuery("#mediamanager__diff");
4519        var $slider = $diff.find("div.slider");
4520        if (!$slider.length) return;
4521
4522        var $image = $diff.find('div.imageDiff.opacity div.image1 img');
4523        if (!$image.length) return;
4524        $slider.width($image.width() - 20);
4525
4526        $slider.slider();
4527        $slider.slider("option", "min", 0);
4528        $slider.slider("option", "max", 0.999);
4529        $slider.slider("option", "step", 0.001);
4530        $slider.slider("option", "value", 0.5);
4531        $slider.on("slide", function (event, ui) {
4532            jQuery('#mediamanager__diff').find('div.imageDiff.opacity div.image2 img').css({opacity: $slider.slider("option", "value")});
4533        });
4534    },
4535
4536    /**
4537     * Sets options for red line diff slider
4538     *
4539     * @author Kate Arzamastseva <[email protected]>
4540     */
4541    portions_slider: function () {
4542        var $diff = jQuery("#mediamanager__diff");
4543        if (!$diff.length) return;
4544
4545        var $image1 = $diff.find('div.imageDiff.portions div.image1 img');
4546        var $image2 = $diff.find('div.imageDiff.portions div.image2 img');
4547        if (!$image1.length || !$image2.length) return;
4548
4549        $diff.width('100%');
4550        $image2.parent().width('97%');
4551        $image1.width('100%');
4552        $image2.width('100%');
4553
4554        if ($image1.width() < $diff.width()) {
4555            $diff.width($image1.width());
4556        }
4557
4558        $image2.parent().width('50%');
4559        $image2.width($image1.width());
4560        $image1.width($image1.width());
4561
4562        var $slider = $diff.find("div.slider");
4563        if (!$slider.length) return;
4564        $slider.width($image1.width() - 20);
4565
4566        $slider.slider();
4567        $slider.slider("option", "min", 0);
4568        $slider.slider("option", "max", 97);
4569        $slider.slider("option", "step", 1);
4570        $slider.slider("option", "value", 50);
4571        $slider.on("slide", function (event, ui) {
4572            jQuery('#mediamanager__diff').find('div.imageDiff.portions div.image2').css({width: $slider.slider("option", "value") + '%'});
4573        });
4574    },
4575
4576    /**
4577     * Parse a URI query string to an associative array
4578     *
4579     * @author Kate Arzamastseva <[email protected]>
4580     */
4581    params_toarray: function (str) {
4582        var vars = [], hash;
4583        var hashes = str.split('&');
4584        for (var i = 0; i < hashes.length; i++) {
4585            hash = hashes[i].split('=');
4586            vars[decodeURIComponent(hash[0])] = decodeURIComponent(hash[1]);
4587        }
4588        return vars;
4589    },
4590
4591    init_ajax_uploader: function () {
4592        if (!jQuery('#mediamanager__uploader').length) return;
4593        if (jQuery('.qq-upload-list').length) return;
4594
4595        var params = dw_mediamanager.form_params(jQuery('#dw__upload')) + '&call=mediaupload';
4596        params = dw_mediamanager.params_toarray(params);
4597
4598        var uploader = new qq.FileUploaderExtended({
4599            element: document.getElementById('mediamanager__uploader'),
4600            action: DOKU_BASE + 'lib/exe/ajax.php',
4601            params: params
4602        });
4603    },
4604
4605    prepare_content: function ($content) {
4606        // hide syntax example
4607        $content.find('div.example:visible').hide();
4608        // toggle list of allowed mime types
4609        $content.find('a.allowedmime').on('click', function (event) {
4610            event.preventDefault();
4611            $toggle = jQuery(this);
4612            $list = $toggle.next('span');
4613            $list.toggle();
4614        }).next('span').hide();
4615
4616    },
4617
4618    /**
4619     * shows the popup for a image link
4620     */
4621    select: function (event) {
4622        var $link, id, dot, ext;
4623
4624        event.preventDefault();
4625
4626        $link = jQuery(this);
4627        id = $link.attr('id').substr(2);
4628
4629        if (!opener) {
4630            // if we don't run in popup display example
4631            // the id's are a bit wierd and jQuery('#ex_wiki_dokuwiki-128.png')
4632            // will not be found by Sizzle (the CSS Selector Engine
4633            // used by jQuery), hence the document.getElementById() call
4634            jQuery(document.getElementById('ex_' + id.replace(/:/g, '_').replace(/^_/, ''))).dw_toggle();
4635            return;
4636        }
4637
4638        dw_mediamanager.ext = false;
4639        dot = id.lastIndexOf(".");
4640
4641        if (-1 === dot) {
4642            dw_mediamanager.insert(id);
4643            return;
4644        }
4645
4646        ext = id.substr(dot);
4647
4648        if ({'.jpg': 1, '.jpeg': 1, '.png': 1, '.gif': 1, '.swf': 1}[ext] !== 1) {
4649            dw_mediamanager.insert(id);
4650            return;
4651        }
4652
4653        // remove old callback from the insert button and set the new one.
4654        var $sendbtn = jQuery('#media__sendbtn');
4655        $sendbtn.off().on('click', bind(dw_mediamanager.insert, id));
4656
4657        dw_mediamanager.unforbid('ext');
4658        if (ext === '.swf') {
4659            dw_mediamanager.ext = 'swf';
4660            dw_mediamanager.forbid('ext', {
4661                link: ['1', '2'],
4662                size: ['4']
4663            });
4664        } else {
4665            dw_mediamanager.ext = 'img';
4666        }
4667
4668        // Set to defaults
4669        dw_mediamanager.setOpt('link');
4670        dw_mediamanager.setOpt('align');
4671        dw_mediamanager.setOpt('size');
4672
4673        // toggle buttons for detail and linked image, original size
4674        jQuery('#media__linkbtn1, #media__linkbtn2, #media__sizebtn4')
4675            .toggle(dw_mediamanager.ext === 'img');
4676
4677        dw_mediamanager.$popup.dialog('open');
4678
4679        $sendbtn.focus();
4680    },
4681
4682    /**
4683     * Deletion confirmation dialog to the delete buttons.
4684     *
4685     * @author Michael Klier <[email protected]>
4686     * @author Pierre Spring <[email protected]>
4687     */
4688    confirmattach: function (e) {
4689        if (!confirm(LANG.del_confirm + "\n" + jQuery(this).attr('title'))) {
4690            e.preventDefault();
4691        }
4692    },
4693
4694    /**
4695     * Creates checkboxes for additional options
4696     *
4697     * @author Andreas Gohr <[email protected]>
4698     * @author Pierre Spring <[email protected]>
4699     */
4700    attachoptions: function () {
4701        var $obj, opts;
4702
4703        $obj = jQuery('#media__opts');
4704        if ($obj.length === 0) {
4705            return;
4706        }
4707
4708        opts = [];
4709        // keep open
4710        if (opener) {
4711            opts.push(['keepopen', 'keepopen']);
4712        }
4713        opts.push(['hide', 'hidedetails']);
4714
4715        jQuery.each(opts,
4716            function (_, opt) {
4717                var $box, $lbl;
4718                $box = jQuery(document.createElement('input'))
4719                    .attr('type', 'checkbox')
4720                    .attr('id', 'media__' + opt[0])
4721                    .on('click', bind(dw_mediamanager.toggleOption, opt[0]));
4722
4723                if (DokuCookie.getValue(opt[0])) {
4724                    $box.prop('checked', true);
4725                    dw_mediamanager[opt[0]] = true;
4726                }
4727
4728                $lbl = jQuery(document.createElement('label'))
4729                    .attr('for', 'media__' + opt[0])
4730                    .text(LANG[opt[1]]);
4731
4732                $obj.append($box, $lbl, document.createElement('br'));
4733            });
4734
4735        dw_mediamanager.updatehide();
4736    },
4737
4738    /**
4739     * Generalized toggler
4740     *
4741     * @author Pierre Spring <[email protected]>
4742     */
4743    toggleOption: function (variable) {
4744        if (jQuery(this).prop('checked')) {
4745            DokuCookie.setValue(variable, 1);
4746            dw_mediamanager[variable] = true;
4747        } else {
4748            DokuCookie.setValue(variable, '');
4749            dw_mediamanager[variable] = false;
4750        }
4751        if (variable === 'hide') {
4752            dw_mediamanager.updatehide();
4753        }
4754    },
4755
4756    /**
4757     * Sets the visibility of the image details accordingly to the
4758     * chosen hide state
4759     *
4760     * @author Andreas Gohr <[email protected]>
4761     */
4762    updatehide: function () {
4763        jQuery('#media__content').find('div.detail').dw_toggle(!dw_mediamanager.hide);
4764    },
4765
4766    /**
4767     * set media insertion option
4768     *
4769     * @author Dominik Eckelmann <[email protected]>
4770     */
4771    setOpt: function (opt, e) {
4772        var val, i;
4773        if (typeof e !== 'undefined') {
4774            val = this.id.substring(this.id.length - 1);
4775        } else {
4776            val = dw_mediamanager.getOpt(opt);
4777        }
4778
4779        if (val === false) {
4780            DokuCookie.setValue(opt, '');
4781            dw_mediamanager[opt] = false;
4782            return;
4783        }
4784
4785        if (opt === 'link') {
4786            if (val !== '4' && dw_mediamanager.link === '4') {
4787                dw_mediamanager.unforbid('linkonly');
4788                dw_mediamanager.setOpt('align');
4789                dw_mediamanager.setOpt('size');
4790            } else if (val === '4') {
4791                dw_mediamanager.forbid('linkonly', {align: false, size: false});
4792            }
4793
4794            jQuery("#media__size, #media__align").dw_toggle(val !== '4');
4795        }
4796
4797        DokuCookie.setValue(opt, val);
4798        dw_mediamanager[opt] = val;
4799
4800        for (i = 1; i <= 4; i++) {
4801            jQuery("#media__" + opt + "btn" + i).removeClass('selected');
4802        }
4803        jQuery('#media__' + opt + 'btn' + val).addClass('selected');
4804    },
4805
4806    unforbid: function (group) {
4807        delete dw_mediamanager.forbidden_opts[group];
4808    },
4809
4810    forbid: function (group, forbids) {
4811        dw_mediamanager.forbidden_opts[group] = forbids;
4812    },
4813
4814    allowedOpt: function (opt, val) {
4815        var ret = true;
4816        jQuery.each(dw_mediamanager.forbidden_opts,
4817            function (_, forbids) {
4818                ret = forbids[opt] !== false &&
4819                    jQuery.inArray(val, forbids[opt]) === -1;
4820                return ret;
4821            });
4822        return ret;
4823    },
4824
4825    getOpt: function (opt) {
4826        var allowed = bind(dw_mediamanager.allowedOpt, opt);
4827
4828        // Current value
4829        if (dw_mediamanager[opt] !== false && allowed(dw_mediamanager[opt])) {
4830            return dw_mediamanager[opt];
4831        }
4832
4833        // From cookie
4834        if (DokuCookie.getValue(opt) && allowed(DokuCookie.getValue(opt))) {
4835            return DokuCookie.getValue(opt);
4836        }
4837
4838        // size default
4839        if (opt === 'size' && allowed('2')) {
4840            return '2';
4841        }
4842
4843        // Whatever is allowed, and be it false
4844        return jQuery.grep(['1', '2', '3', '4'], allowed)[0] || false;
4845    }
4846};
4847
4848/**
4849 * Default implementation for the media manager's select action
4850 *
4851 * Can be overriden with the onselect URL parameter. Is called on the opener context
4852 *
4853 * @param {string} edid
4854 * @param {string} mediaid
4855 * @param {string} opts
4856 * @param {string} align [none, left, center, right]
4857 */
4858function dw_mediamanager_item_select(edid, mediaid, opts, align, keepopen) {
4859    var alignleft = '';
4860    var alignright = '';
4861
4862    // Get the 2 characters after the cursor to check if we're currently inside an image tag
4863    var cursorInImageTag = false;
4864    var textArea = jQuery('#' + edid)[0];
4865    var selection = DWgetSelection(textArea);
4866    selection.end = selection.end + 2;
4867    var charsAfterCursor = selection.getText();
4868    if (charsAfterCursor === '}}') {
4869        cursorInImageTag = true;
4870    }
4871
4872    if (align !== '1') {
4873        alignleft = align === '2' ? '' : ' ';
4874        alignright = align === '4' ? '' : ' ';
4875    }
4876    if (keepopen && cursorInImageTag) {
4877        selection.start = selection.start + 2;
4878        DWsetSelection(selection);
4879    }
4880    insertTags(edid, '{{' + alignleft + mediaid + opts + alignright + '|', '}}', '');
4881}
4882
4883jQuery(dw_mediamanager.init);
4884
4885
4886
4887/* XXXXXXXXXX end of lib/scripts/media.js XXXXXXXXXX */
4888
4889
4890
4891/* XXXXXXXXXX begin of lib/scripts/compatibility.js XXXXXXXXXX */
4892
4893/**
4894 * Mark a JavaScript function as deprecated
4895 *
4896 * This will print a warning to the JavaScript console (if available) in
4897 * Firebug and Chrome and a stack trace (if available) to easily locate the
4898 * problematic function call.
4899 *
4900 * @param msg optional message to print
4901 */
4902function DEPRECATED(msg){
4903    if(!window.console) return;
4904    if(!msg) msg = '';
4905
4906    var func;
4907    if(arguments.callee) func = arguments.callee.caller.name;
4908    if(func) func = ' '+func+'()';
4909    var line = 'DEPRECATED function call'+func+'. '+msg;
4910
4911    if(console.warn){
4912        console.warn(line);
4913    }else{
4914        console.log(line);
4915    }
4916
4917    if(console.trace) console.trace();
4918}
4919
4920/**
4921 * Construct a wrapper function for deprecated function names
4922 *
4923 * This function returns a wrapper function which just calls DEPRECATED
4924 * and the new function.
4925 *
4926 * @param func    The new function
4927 * @param context Optional; The context (`this`) of the call
4928 */
4929function DEPRECATED_WRAP(func, context) {
4930    return function () {
4931        DEPRECATED();
4932        return func.apply(context || this, arguments);
4933    };
4934}
4935
4936
4937
4938/* XXXXXXXXXX end of lib/scripts/compatibility.js XXXXXXXXXX */
4939
4940
4941
4942/* XXXXXXXXXX begin of lib/scripts/behaviour.js XXXXXXXXXX */
4943
4944/**
4945 * Hides elements with a slide animation
4946 *
4947 * @param {function} fn optional callback to run after hiding
4948 * @param {bool} noaria supress aria-expanded state setting
4949 * @author Adrian Lang <[email protected]>
4950 */
4951jQuery.fn.dw_hide = function(fn, noaria) {
4952    if(!noaria) this.attr('aria-expanded', 'false');
4953    return this.slideUp('fast', fn);
4954};
4955
4956/**
4957 * Unhides elements with a slide animation
4958 *
4959 * @param {function} fn optional callback to run after hiding
4960 * @param {bool} noaria supress aria-expanded state setting
4961 * @author Adrian Lang <[email protected]>
4962 */
4963jQuery.fn.dw_show = function(fn, noaria) {
4964    if(!noaria) this.attr('aria-expanded', 'true');
4965    return this.slideDown('fast', fn);
4966};
4967
4968/**
4969 * Toggles visibility of an element using a slide element
4970 *
4971 * @param {bool} state the current state of the element (optional)
4972 * @param {function} fn callback after the state has been toggled
4973 * @param {bool} noaria supress aria-expanded state setting
4974 */
4975jQuery.fn.dw_toggle = function(state, fn, noaria) {
4976    return this.each(function() {
4977        var $this = jQuery(this);
4978        if (typeof state === 'undefined') {
4979            state = $this.is(':hidden');
4980        }
4981        $this[state ? "dw_show" : "dw_hide" ](fn, noaria);
4982    });
4983};
4984
4985/**
4986 * Automatic behaviours
4987 *
4988 * This class wraps various JavaScript functionalities that are triggered
4989 * automatically whenever a certain object is in the DOM or a certain CSS
4990 * class was found
4991 */
4992var dw_behaviour = {
4993
4994    init: function(){
4995        dw_behaviour.focusMarker();
4996        dw_behaviour.scrollToMarker();
4997        dw_behaviour.removeHighlightOnClick();
4998        dw_behaviour.quickSelect();
4999        dw_behaviour.checkWindowsShares();
5000        dw_behaviour.subscription();
5001        dw_behaviour.pageRestoreConfirm();
5002        dw_behaviour.securityCheck();
5003
5004        dw_behaviour.revisionBoxHandler();
5005        jQuery(document).on('click','#page__revisions input[type=checkbox]',
5006            dw_behaviour.revisionBoxHandler
5007        );
5008
5009        jQuery('.bounce').effect('bounce', {times:10}, 2000 );
5010    },
5011
5012    /**
5013     * Looks for an element with the ID scroll__here at scrolls to it
5014     */
5015    scrollToMarker: function(){
5016        var $obj = jQuery('#scroll__here');
5017        if($obj.length) {
5018            if($obj.offset().top != 0) {
5019                jQuery('html, body').animate({
5020                    scrollTop: $obj.offset().top - 100
5021                }, 500);
5022            } else {
5023                // hidden object have no offset but can still be scrolled into view
5024                $obj[0].scrollIntoView();
5025            }
5026        }
5027    },
5028
5029    /**
5030     * Display confirm dialog on page restore action
5031     */
5032    pageRestoreConfirm: function(){
5033        jQuery('#dokuwiki__pagetools li.revert a').on('click',
5034            function() {
5035                return confirm(LANG.restore_confirm);
5036            }
5037        );
5038    },
5039
5040    /**
5041     * Looks for an element with the ID focus__this at sets focus to it
5042     */
5043    focusMarker: function(){
5044        jQuery('#focus__this').trigger('focus');
5045    },
5046
5047    /**
5048     * Remove all search highlighting when clicking on a highlighted term
5049     */
5050    removeHighlightOnClick: function(){
5051        jQuery('span.search_hit').on('click',
5052            function(e){
5053                jQuery(e.target).removeClass('search_hit', 1000);
5054            }
5055        );
5056    },
5057
5058    /**
5059     * Autosubmit quick select forms
5060     *
5061     * When a <select> or <input> tag has the class "quickselect", this script will
5062     * automatically submit its parent form when the select value changes.
5063     * It also hides the submit button of the form.
5064     *
5065     * This includes a workaround a weird behaviour when the submit button has a name
5066     *
5067     * @link https://trackjs.com/blog/when-form-submit-is-not-a-function/
5068     * @author Andreas Gohr <[email protected]>
5069     */
5070    quickSelect: function(){
5071        jQuery('.quickselect')
5072            .change(function(e){ HTMLFormElement.prototype.submit.call(e.target.form); })
5073            .closest('form').find(':button').not('.show').hide();
5074    },
5075
5076    /**
5077     * Display error for Windows Shares on browsers other than IE
5078     *
5079     * @author Michael Klier <[email protected]>
5080     */
5081    checkWindowsShares: function() {
5082        if(!LANG.nosmblinks || navigator.userAgent.match(/(Trident|MSIE|Edge)/)) {
5083            // No warning requested or none necessary
5084            return;
5085        }
5086
5087        jQuery('a.windows').on('click', function(){
5088            alert(LANG.nosmblinks.replace(/\\n/,"\n"));
5089        });
5090    },
5091
5092    /**
5093     * Hide list subscription style if target is a page
5094     *
5095     * @author Adrian Lang <[email protected]>
5096     * @author Pierre Spring <[email protected]>
5097     */
5098    subscription: function(){
5099        var $form, $list, $digest;
5100
5101        $form = jQuery('#subscribe__form');
5102        if (0 === $form.length) return;
5103
5104        $list = $form.find("input[name='sub_style'][value='list']");
5105        $digest = $form.find("input[name='sub_style'][value='digest']");
5106
5107        $form.find("input[name='sub_target']")
5108            .on('click',
5109                function () {
5110                    var $this = jQuery(this), show_list;
5111                    if (!$this.prop('checked')) {
5112                        return;
5113                    }
5114
5115                    show_list = $this.val().match(/:$/);
5116                    $list.parent().dw_toggle(show_list);
5117                    if (!show_list && $list.prop('checked')) {
5118                        $digest.prop('checked', 'checked');
5119                    }
5120                }
5121            )
5122            .filter(':checked')
5123            .trigger('click');
5124    },
5125
5126    /**
5127     * disable multiple revisions checkboxes if two are checked
5128     *
5129     * @author Andreas Gohr <[email protected]>
5130     * @author Anika Henke <[email protected]>
5131     */
5132    revisionBoxHandler: function() {
5133        var $revisions = jQuery('#page__revisions');
5134        var $all       = jQuery('input[type="checkbox"][name="rev2[]"]', $revisions);
5135        var $checked   = $all.filter(':checked');
5136        var $button    = jQuery('button', $revisions);
5137
5138        if($checked.length < 2) {
5139            $all.prop('disabled', false);
5140            $button.prop('disabled', true);
5141        } else {
5142            $all.prop('disabled', true);
5143            $button.prop('disabled', false);
5144            $checked.each(function(i) {
5145                jQuery(this).prop('disabled', false);
5146                if(i>1) {
5147                    jQuery(this).prop('checked', false);
5148                }
5149            });
5150        }
5151    },
5152
5153    /**
5154     * Check that access to the data directory is properly secured
5155     *
5156     * A successful check (a 403 error was returned when loading the image) is saved
5157     * to session storage and not repeated again until the next browser session. This
5158     * avoids overeager security bans (see #3363)
5159     */
5160    securityCheck: function () {
5161        var $checkDiv = jQuery('#security__check');
5162        if (!$checkDiv.length) return;
5163        if (sessionStorage.getItem('dw-security-check:' + DOKU_BASE)) {
5164            // check was already executed successfully
5165            $checkDiv.remove();
5166            return;
5167        }
5168
5169        var img = new Image();
5170        img.onerror = function () {
5171            // successful check will not be repeated during session
5172            $checkDiv.remove();
5173            sessionStorage.setItem('dw-security-check:' + DOKU_BASE, true);
5174        };
5175        img.onload = function () {
5176            // check failed, display a warning message
5177            $checkDiv.html(LANG.data_insecure);
5178            $checkDiv.addClass('error');
5179        };
5180        img.src = $checkDiv.data('src') + '?t=' + Date.now();
5181    }
5182};
5183
5184jQuery(dw_behaviour.init);
5185
5186
5187
5188/* XXXXXXXXXX end of lib/scripts/behaviour.js XXXXXXXXXX */
5189
5190
5191
5192/* XXXXXXXXXX begin of lib/scripts/page.js XXXXXXXXXX */
5193
5194/**
5195 * Page behaviours
5196 *
5197 * This class adds various behaviours to the rendered page
5198 */
5199dw_page = {
5200    /**
5201     * initialize page behaviours
5202     */
5203    init: function(){
5204        dw_page.sectionHighlight();
5205        dw_page.currentIDHighlight();
5206        jQuery('a.fn_top').on('mouseover', dw_page.footnoteDisplay);
5207        dw_page.makeToggle('#dw__toc h3','#dw__toc > div');
5208    },
5209
5210    /**
5211     * Highlight the section when hovering over the appropriate section edit button
5212     *
5213     * @author Andreas Gohr <[email protected]>
5214     */
5215    sectionHighlight: function() {
5216        jQuery('form.btn_secedit')
5217            .on('mouseover', function(){
5218                var $tgt = jQuery(this).parent(),
5219                    nr = $tgt.attr('class').match(/(\s+|^)editbutton_(\d+)(\s+|$)/)[2],
5220                    $highlight = jQuery(),                                             // holder for elements in the section to be highlighted
5221                    $highlightWrap = jQuery('<div class="section_highlight"></div>');  // section highlight wrapper
5222
5223                // Walk the dom tree in reverse to find the sibling which is or contains the section edit marker
5224                while($tgt.length > 0 && !($tgt.hasClass('sectionedit' + nr) || $tgt.find('.sectionedit' + nr).length)) {
5225                    $tgt = $tgt.prev();
5226                    $highlight = $highlight.add($tgt);
5227                }
5228              // insert the section highlight wrapper before the last element added to $highlight
5229              $highlight.filter(':last').before($highlightWrap);
5230              // and move the elements to be highlighted inside the section highlight wrapper
5231              $highlight.detach().appendTo($highlightWrap);
5232            })
5233            .on('mouseout', function(){
5234                // find the section highlight wrapper...
5235                var $highlightWrap = jQuery('.section_highlight');
5236                // ...move its children in front of it (as siblings)...
5237                $highlightWrap.before($highlightWrap.children().detach());
5238                // ...and remove the section highlight wrapper
5239                $highlightWrap.detach();
5240            });
5241    },
5242
5243
5244    /**
5245     * Highlight internal link pointing to current page
5246     *
5247     * @author Henry Pan <[email protected]>
5248     */
5249    currentIDHighlight: function(){
5250        jQuery('a.wikilink1, a.wikilink2').filter('[data-wiki-id="'+JSINFO.id+'"]').wrap('<span class="curid"></div>');
5251    },
5252
5253    /**
5254     * Create/get a insitu popup used by the footnotes
5255     *
5256     * @param target - the DOM element at which the popup should be aligned at
5257     * @param popup_id - the ID of the (new) DOM popup
5258     * @return the Popup jQuery object
5259     */
5260    insituPopup: function(target, popup_id) {
5261        // get or create the popup div
5262        var $fndiv = jQuery('#' + popup_id);
5263
5264        // popup doesn't exist, yet -> create it
5265        if($fndiv.length === 0){
5266            $fndiv = jQuery(document.createElement('div'))
5267                .attr('id', popup_id)
5268                .addClass('insitu-footnote JSpopup')
5269                .attr('aria-hidden', 'true')
5270                .on('mouseleave', function () {jQuery(this).hide().attr('aria-hidden', 'true');})
5271                .attr('role', 'tooltip');
5272            jQuery('.dokuwiki:first').append($fndiv);
5273        }
5274
5275        // position() does not support hidden elements
5276        $fndiv.show().position({
5277            my: 'left top',
5278            at: 'left center',
5279            of: target
5280        }).hide();
5281
5282        return $fndiv;
5283    },
5284
5285    /**
5286     * Display an insitu footnote popup
5287     *
5288     * @author Andreas Gohr <[email protected]>
5289     * @author Chris Smith <[email protected]>
5290     * @author Anika Henke <[email protected]>
5291     */
5292    footnoteDisplay: function () {
5293        var $content = jQuery(jQuery(this).attr('href')) // Footnote text anchor
5294                      .parent().siblings('.content').clone();
5295
5296        if (!$content.length) {
5297            return;
5298        }
5299
5300        // prefix ids on any elements with "insitu__" to ensure they remain unique
5301        jQuery('[id]', $content).each(function(){
5302            var id = jQuery(this).attr('id');
5303            jQuery(this).attr('id', 'insitu__' + id);
5304        });
5305
5306        var content = $content.html().trim();
5307        // now put the content into the wrapper
5308        dw_page.insituPopup(this, 'insitu__fn').html(content)
5309        .show().attr('aria-hidden', 'false');
5310    },
5311
5312    /**
5313     * Makes an element foldable by clicking its handle
5314     *
5315     * This is used for the TOC toggling, but can be used for other elements
5316     * as well. A state indicator is inserted into the handle and can be styled
5317     * by CSS.
5318     *
5319     * To properly reserve space for the expanded element, the sliding animation is
5320     * done on the children of the content. To make that look good and to make sure aria
5321     * attributes are assigned correctly, it's recommended to make sure that the content
5322     * element contains a single child element only.
5323     *
5324     * @param {selector} handle What should be clicked to toggle
5325     * @param {selector} content This element will be toggled
5326     * @param {int} state initial state (-1 = open, 1 = closed)
5327     */
5328    makeToggle: function(handle, content, state){
5329        var $handle, $content, $clicky, $child, setClicky;
5330        $handle = jQuery(handle);
5331        if(!$handle.length) return;
5332        $content = jQuery(content);
5333        if(!$content.length) return;
5334
5335        // we animate the children
5336        $child = $content.children();
5337
5338        // class/display toggling
5339        setClicky = function(hiding){
5340            if(hiding){
5341                $clicky.html('<span>+</span>');
5342                $handle.addClass('closed');
5343                $handle.removeClass('open');
5344            }else{
5345                $clicky.html('<span>−</span>');
5346                $handle.addClass('open');
5347                $handle.removeClass('closed');
5348            }
5349        };
5350
5351        $handle[0].setState = function(state){
5352            var hidden;
5353            if(!state) state = 1;
5354
5355            // Assert that content instantly takes the whole space
5356            $content.css('min-height', $content.height()).show();
5357
5358            // stop any running animation
5359            $child.stop(true, true);
5360
5361            // was a state given or do we toggle?
5362            if(state === -1) {
5363                hidden = false;
5364            } else if(state === 1) {
5365                hidden = true;
5366            } else {
5367                hidden = $child.is(':hidden');
5368            }
5369
5370            // update the state
5371            setClicky(!hidden);
5372
5373            // Start animation and assure that $toc is hidden/visible
5374            $child.dw_toggle(hidden, function () {
5375                $content.toggle(hidden);
5376                $content.attr('aria-expanded', hidden);
5377                $content.css('min-height',''); // remove min-height again
5378            }, true);
5379        };
5380
5381        // the state indicator
5382        $clicky = jQuery(document.createElement('strong'));
5383
5384        // click function
5385        $handle.css('cursor','pointer')
5386               .on('click', $handle[0].setState)
5387               .prepend($clicky);
5388
5389        // initial state
5390        $handle[0].setState(state);
5391    }
5392};
5393
5394jQuery(dw_page.init);
5395
5396
5397
5398/* XXXXXXXXXX end of lib/scripts/page.js XXXXXXXXXX */
5399
5400
5401
5402/* XXXXXXXXXX begin of lib/plugins/acl/script.js XXXXXXXXXX */
5403
5404/**
5405 * ACL Manager AJAX enhancements
5406 *
5407 * @author Andreas Gohr <[email protected]>
5408 */
5409var dw_acl = {
5410    /**
5411     * Initialize the object and attach the event handlers
5412     */
5413    init: function () {
5414        var $tree;
5415
5416        //FIXME only one underscore!!
5417        if (jQuery('#acl_manager').length === 0) {
5418            return;
5419        }
5420
5421        jQuery('#acl__user select').on('change', dw_acl.userselhandler);
5422        jQuery('#acl__user button').on('click', dw_acl.loadinfo);
5423
5424        $tree = jQuery('#acl__tree');
5425        $tree.dw_tree({toggle_selector: 'img',
5426                       load_data: function (show_sublist, $clicky) {
5427                           // get the enclosed link and the edit form
5428                           var $frm = jQuery('#acl__detail form');
5429
5430                           jQuery.post(
5431                               DOKU_BASE + 'lib/exe/ajax.php',
5432                               jQuery.extend(dw_acl.parseatt($clicky.parent().find('a')[0].search),
5433                                             {call: 'plugin_acl',
5434                                              ajax: 'tree',
5435                                              current_ns: $frm.find('input[name=ns]').val(),
5436                                              current_id: $frm.find('input[name=id]').val()}),
5437                               show_sublist,
5438                               'html'
5439                           );
5440                       },
5441
5442                       toggle_display: function ($clicky, opening) {
5443                           $clicky.attr('src',
5444                                        DOKU_BASE + 'lib/images/' +
5445                                        (opening ? 'minus' : 'plus') + '.g
5445if');
5446                       }});
5447        $tree.delegate('a', 'click', dw_acl.treehandler);
5448    },
5449
5450    /**
5451     * Handle user dropdown
5452     *
5453     * Hides or shows the user/group entry box depending on what was selected in the
5454     * dropdown element
5455     */
5456    userselhandler: function () {
5457        // make entry field visible/invisible
5458        jQuery('#acl__user input').toggle(this.value === '__g__' ||
5459                                          this.value === '__u__');
5460        dw_acl.loadinfo();
5461    },
5462
5463    /**
5464     * Load the current permission info and edit form
5465     */
5466    loadinfo: function () {
5467        jQuery('#acl__info')
5468            .attr('role', 'alert')
5469            .html('<img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="..." />')
5470            .load(
5471                DOKU_BASE + 'lib/exe/ajax.php',
5472                jQuery('#acl__detail form').serialize() + '&call=plugin_acl&ajax=info'
5473            );
5474        return false;
5475    },
5476
5477    /**
5478     * parse URL attributes into a associative array
5479     *
5480     * @todo put into global script lib?
5481     */
5482    parseatt: function (str) {
5483        if (str[0] === '?') {
5484            str = str.substr(1);
5485        }
5486        var attributes = {};
5487        var all = str.split('&');
5488        for (var i = 0; i < all.length; i++) {
5489            var att = all[i].split('=');
5490            attributes[att[0]] = decodeURIComponent(att[1]);
5491        }
5492        return attributes;
5493    },
5494
5495    /**
5496     * Handles clicks to the tree nodes
5497     */
5498    treehandler: function () {
5499        var $link, $frm;
5500
5501        $link = jQuery(this);
5502
5503            // remove highlighting
5504            jQuery('#acl__tree a.cur').removeClass('cur');
5505
5506            // add new highlighting
5507        $link.addClass('cur');
5508
5509            // set new page to detail form
5510        $frm = jQuery('#acl__detail form');
5511        if ($link.hasClass('wikilink1')) {
5512            $frm.find('input[name=ns]').val('');
5513            $frm.find('input[name=id]').val(dw_acl.parseatt($link[0].search).id);
5514        } else if ($link.hasClass('idx_dir')) {
5515            $frm.find('input[name=ns]').val(dw_acl.parseatt($link[0].search).ns);
5516            $frm.find('input[name=id]').val('');
5517            }
5518        dw_acl.loadinfo();
5519
5520        return false;
5521    }
5522};
5523
5524jQuery(dw_acl.init);
5525
5526
5527
5528/* XXXXXXXXXX end of lib/plugins/acl/script.js XXXXXXXXXX */
5529
5530
5531
5532/* XXXXXXXXXX begin of lib/plugins/cellbg/script.js XXXXXXXXXX */
5533
5534/* JavaScript function to create cellbg toolbar in DokuwKki */
5535/* see http:// for more info */
5536 
5537var plugin_cellbg_colors = {
5538 
5539  "Yellow":      "yellow",
5540  "Red":         "red",
5541  "Orange":      "orange",
5542  "Salmon":      "salmon",
5543  "Pink":        "pink",
5544  "Plum":        "plum",
5545  "Purple":      "purple",
5546  "Fuchsia":     "fuchsia",
5547  "Silver":      "silver",
5548  "Aqua":        "aqua",
5549  "Teal":        "teal",
5550  "Cornflower":  "#6495ed",
5551  "Sky Blue":    "skyblue",
5552  "Aquamarine":  "aquamarine",
5553  "Pale Green":  "palegreen",
5554  "Lime":        "lime",
5555  "Green":       "green",
5556  "Olive":       "olive"
5557  //"Yellow":      "#ffff00",
5558  //"Red":         "#ff0000",
5559  //"Orange":      "#ffa500",
5560  //"Salmon":      "#fa8072",
5561  //"Pink":        "#ffc0cb",
5562  //"Plum":        "#dda0dd",
5563  //"Purple":      "#800080",
5564  //"Fuchsia":     "#ff00ff",
5565  //"Silver":      "#c0c0c0",
5566  //"Aqua":        "#00ffff",
5567  //"Teal":        "#008080",
5568  //"Cornflower":  "#6495ed",
5569  //"Sky Blue":    "#87ceeb",
5570  //"Aquamarine":  "#7fffd4",
5571  //"Pale Green":  "#98fb98",
5572  //"Lime":        "#00ff00",
5573  //"Green":       "#008000",
5574  //"Olive":       "#808000"
5575 
5576};
5577 
5578function plugin_cellbg_make_color_button(name, value) {
5579 
5580  var btn = document.createElement('button');
5581 
5582  btn.className = 'pickerbutton';
5583  btn.value = '';
5584  btn.title = name;
5585  btn.style.height = '2em';
5586  btn.style.padding = '1em';
5587  btn.style.backgroundColor = value;
5588 
5589  var open = "@" + value + ":";
5590  eval("btn.onclick = function(){ insertAtCarret( '"
5591    + jsEscape('wiki__text') + "','"
5592    + jsEscape(open) + "','"
5593    + "'); return false; } "
5594  );
5595 
5596  return(btn);
5597 
5598}
5599 
5600function plugin_cellbg_toolbar_picker() {
5601 
5602  if (!document.getElementById('spell__action')) return; 
5603
5604  var toolbar = document.getElementById('tool__bar');
5605  if (!toolbar) return;
5606 
5607  // Create the picker button
5608  var p_id = 'picker_plugin_cellbg'; // picker id that we're creating
5609  var p_ico = document.createElement('img');
5610  p_ico.src = DOKU_BASE + 'lib/plugins/cellbg/images/cellbg.png';
5611  var p_btn = document.createElement('button');
5612  p_btn.className = 'toolbutton';
5613  p_btn.title = 'Cell background';
5614  p_btn.appendChild(p_ico);
5615  eval("p_btn.onclick = function() { showPicker('"
5616    + p_id + "',this); return false; }");
5617 
5618  // Create the picker <div>
5619  var picker = document.createElement('div');
5620  picker.className = 'picker';
5621  picker.id = p_id;
5622  picker.style.position = 'absolute';
5623  picker.style.display = 'none';
5624 
5625  // Add a button to the picker <div> for each of the colors
5626  for( var color in plugin_cellbg_colors ) {
5627    var btn = plugin_cellbg_make_color_button(color,
5628        plugin_cellbg_colors[color]);
5629    picker.appendChild(btn);
5630  }
5631  if (typeof user_cellbg_colors != 'undefined') {
5632    for( var color in user_cellbg_colors ) {
5633      var btn = plugin_cellbg_make_color_button(color,
5634          user_cellbg_colors[color]);
5635      picker.appendChild(btn);
5636    }
5637  }
5638 
5639  var body = document.getElementsByTagName('body')[0];
5640  body.appendChild(picker);     // attach the picker <div> to the page body
5641  toolbar.appendChild(p_btn);   // attach the picker button to the toolbar
5642}
5643jQuery(plugin_cellbg_toolbar_picker);
5644 
5645//Setup VIM: ex: et ts=2 sw=2 enc=utf-8 :
5646
5647
5648
5649/* XXXXXXXXXX end of lib/plugins/cellbg/script.js XXXXXXXXXX */
5650
5651
5652
5653/* XXXXXXXXXX begin of lib/plugins/color/script.js XXXXXXXXXX */
5654
5655/* JavaScript function to create color toolbar in Dokuwiki */
5656/* see http://www.dokuwiki.org/plugin:color for more info */
5657
5658color_icobase = "../../plugins/color/images/";
5659
5660if(window.toolbar != undefined) {
5661  toolbar[toolbar.length] = {
5662    "type":"picker",
5663    "title":"Color Text",
5664    "icon":color_icobase+"toolbar_icon.png",
5665    "list":[{
5666      "type":"format",
5667      "title":"Gray Colored Text",
5668      "icon":color_icobase+"picker_light_gray.png",
5669      "open":"<color #c3c3c3>",
5670      "close":"</color>"
5671    }, {
vendor: 4,490 bytes, lines 5672-5844
5672      "type":"format",
5673      "title":"Rose Highlighted Text",
5674      "icon":color_icobase+"picker_rose.png",
5675      "open":"<color #ffaec9>",
5676      "close":"</color>"
5677    }, {
5678      "type":"format",
5679      "title":"Red Highlighted Text",
5680      "icon":color_icobase+"picker_red.png",
5681      "open":"<color #ed1c24>",
5682      "close":"</color>"
5683    }, {
5684      "type":"format",
5685      "title":"Orange Highlighted Text",
5686      "icon":color_icobase+"picker_orange.png",
5687      "open":"<color #ff7f27>",
5688      "close":"</color>"
5689    }, {
5690      "type":"format",
5691      "title":"Gold Highlighted Text",
5692      "icon":color_icobase+"picker_gold.png",
5693      "open":"<color #ffc90e>",
5694      "close":"</color>"
5695    }, {
5696      "type":"format",
5697      "title":"Yellow Highlighted Text",
5698      "icon":color_icobase+"picker_yellow.png",
5699      "open":"<color #fff200>",
5700      "close":"</color>"
5701    }, {
5702      "type":"format",
5703      "title":"Light Yellow Highlighted Text",
5704      "icon":color_icobase+"picker_light_yellow.png",
5705      "open":"<color #efe4B0>",
5706      "close":"</color>"
5707    }, {
5708      "type":"format",
5709      "title":"Green Highlighted Text",
5710      "icon":color_icobase+"picker_green.png",
5711      "open":"<color #22b14c>",
5712      "close":"</color>"
5713    }, {
5714      "type":"format",
5715      "title":"Lime Highlighted Text",
5716      "icon":color_icobase+"picker_lime.png",
5717      "open":"<color #b5e61d>",
5718      "close":"</color>"
5719    }, {
5720      "type":"format",
5721      "title":"Turquoise Highlighted Text",
5722      "icon":color_icobase+"picker_turquoise.png",
5723      "open":"<color #00a2e8>",
5724      "close":"</color>"
5725    }, {
5726      "type":"format",
5727      "title":"Light Turquoise Highlighted Text",
5728      "icon":color_icobase+"picker_light_turquoise.png",
5729      "open":"<color #99d9ea>",
5730      "close":"</color>"
5731    }, {
5732      "type":"format",
5733      "title":"Blue-Gray Highlighted Text",
5734      "icon":color_icobase+"picker_blue_gray.png",
5735      "open":"<color #7092be>",
5736      "close":"</color>"
5737    }, {
5738      "type":"format",
5739      "title":"Lavender Highlighted Text",
5740      "icon":color_icobase+"picker_lavender.png",
5741      "open":"<color #c8bfe7>",
5742      "close":"</color>"
5743    }]
5744  };
5745}
5746
5747
5748/* XXXXXXXXXX end of lib/plugins/color/script.js XXXXXXXXXX */
5749
5750
5751
5752/* XXXXXXXXXX begin of lib/plugins/davcal/script.js XXXXXXXXXX */
5753
5754//! moment.js
5755//! version : 2.20.1
5756//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
5757//! license : MIT
5758//! momentjs.com
5759
5760;(function (global, factory) {
5761    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
5762    typeof define === 'function' && define.amd ? define(factory) :
5763    global.moment = factory()
5764}(this, (function () { 'use strict';
5765
5766var hookCallback;
5767
5768function hooks () {
5769    return hookCallback.apply(null, arguments);
5770}
5771
5772// This is done to register the method called with moment()
5773// without creating circular dependencies.
5774function setHookCallback (callback) {
5775    hookCallback = callback;
5776}
5777
5778function isArray(input) {
5779    return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
5780}
5781
5782function isObject(input) {
5783    // IE8 will treat undefined and null as object if it wasn't for
5784    // input != null
5785    return input != null && Object.prototype.toString.call(input) === '[object Object]';
5786}
5787
5788function isObjectEmpty(obj) {
5789    if (Object.getOwnPropertyNames) {
5790        return (Object.getOwnPropertyNames(obj).length === 0);
5791    } else {
5792        var k;
5793        for (k in obj) {
5794            if (obj.hasOwnProperty(k)) {
5795                return false;
5796            }
5797        }
5798        return true;
5799    }
5800}
5801
5802function isUndefined(input) {
5803    return input === void 0;
5804}
5805
5806function isNumber(input) {
5807    return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
5808}
5809
5810function isDate(input) {
5811    return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
5812}
5813
5814function map(arr, fn) {
5815    var res = [], i;
5816    for (i = 0; i < arr.length; ++i) {
5817        res.push(fn(arr[i], i));
5818    }
5819    return res;
5820}
5821
5822function hasOwnProp(a, b) {
5823    return Object.prototype.hasOwnProperty.call(a, b);
5824}
5825
5826function extend(a, b) {
5827    for (var i in b) {
5828        if (hasOwnProp(b, i)) {
5829            a[i] = b[i];
5830        }
5831    }
5832
5833    if (hasOwnProp(b, 'toString')) {
5834        a.toString = b.toString;
5835    }
5836
5837    if (hasOwnProp(b, 'valueOf')) {
5838        a.valueOf = b.valueOf;
5839    }
5840
5841    return a;
5842}
5843
5844function createUTC (input, format, locale, strict) {
vendor: 64,502 bytes, lines 5845-8031
5845    return createLocalOrUTC(input, format, locale, strict, true).utc();
5846}
5847
5848function defaultParsingFlags() {
5849    // We need to deep clone this object.
5850    return {
5851        empty           : false,
5852        unusedTokens    : [],
5853        unusedInput     : [],
5854        overflow        : -2,
5855        charsLeftOver   : 0,
5856        nullInput       : false,
5857        invalidMonth    : null,
5858        invalidFormat   : false,
5859        userInvalidated : false,
5860        iso             : false,
5861        parsedDateParts : [],
5862        meridiem        : null,
5863        rfc2822         : false,
5864        weekdayMismatch : false
5865    };
5866}
5867
5868function getParsingFlags(m) {
5869    if (m._pf == null) {
5870        m._pf = defaultParsingFlags();
5871    }
5872    return m._pf;
5873}
5874
5875var some;
5876if (Array.prototype.some) {
5877    some = Array.prototype.some;
5878} else {
5879    some = function (fun) {
5880        var t = Object(this);
5881        var len = t.length >>> 0;
5882
5883        for (var i = 0; i < len; i++) {
5884            if (i in t && fun.call(this, t[i], i, t)) {
5885                return true;
5886            }
5887        }
5888
5889        return false;
5890    };
5891}
5892
5893function isValid(m) {
5894    if (m._isValid == null) {
5895        var flags = getParsingFlags(m);
5896        var parsedParts = some.call(flags.parsedDateParts, function (i) {
5897            return i != null;
5898        });
5899        var isNowValid = !isNaN(m._d.getTime()) &&
5900            flags.overflow < 0 &&
5901            !flags.empty &&
5902            !flags.invalidMonth &&
5903            !flags.invalidWeekday &&
5904            !flags.weekdayMismatch &&
5905            !flags.nullInput &&
5906            !flags.invalidFormat &&
5907            !flags.userInvalidated &&
5908            (!flags.meridiem || (flags.meridiem && parsedParts));
5909
5910        if (m._strict) {
5911            isNowValid = isNowValid &&
5912                flags.charsLeftOver === 0 &&
5913                flags.unusedTokens.length === 0 &&
5914                flags.bigHour === undefined;
5915        }
5916
5917        if (Object.isFrozen == null || !Object.isFrozen(m)) {
5918            m._isValid = isNowValid;
5919        }
5920        else {
5921            return isNowValid;
5922        }
5923    }
5924    return m._isValid;
5925}
5926
5927function createInvalid (flags) {
5928    var m = createUTC(NaN);
5929    if (flags != null) {
5930        extend(getParsingFlags(m), flags);
5931    }
5932    else {
5933        getParsingFlags(m).userInvalidated = true;
5934    }
5935
5936    return m;
5937}
5938
5939// Plugins that add properties should also add the key here (null value),
5940// so we can properly clone ourselves.
5941var momentProperties = hooks.momentProperties = [];
5942
5943function copyConfig(to, from) {
5944    var i, prop, val;
5945
5946    if (!isUndefined(from._isAMomentObject)) {
5947        to._isAMomentObject = from._isAMomentObject;
5948    }
5949    if (!isUndefined(from._i)) {
5950        to._i = from._i;
5951    }
5952    if (!isUndefined(from._f)) {
5953        to._f = from._f;
5954    }
5955    if (!isUndefined(from._l)) {
5956        to._l = from._l;
5957    }
5958    if (!isUndefined(from._strict)) {
5959        to._strict = from._strict;
5960    }
5961    if (!isUndefined(from._tzm)) {
5962        to._tzm = from._tzm;
5963    }
5964    if (!isUndefined(from._isUTC)) {
5965        to._isUTC = from._isUTC;
5966    }
5967    if (!isUndefined(from._offset)) {
5968        to._offset = from._offset;
5969    }
5970    if (!isUndefined(from._pf)) {
5971        to._pf = getParsingFlags(from);
5972    }
5973    if (!isUndefined(from._locale)) {
5974        to._locale = from._locale;
5975    }
5976
5977    if (momentProperties.length > 0) {
5978        for (i = 0; i < momentProperties.length; i++) {
5979            prop = momentProperties[i];
5980            val = from[prop];
5981            if (!isUndefined(val)) {
5982                to[prop] = val;
5983            }
5984        }
5985    }
5986
5987    return to;
5988}
5989
5990var updateInProgress = false;
5991
5992// Moment prototype object
5993function Moment(config) {
5994    copyConfig(this, config);
5995    this._d = new Date(config._d != null ? config._d.getTime() : NaN);
5996    if (!this.isValid()) {
5997        this._d = new Date(NaN);
5998    }
5999    // Prevent infinite loop in case updateOffset creates new moment
6000    // objects.
6001    if (updateInProgress === false) {
6002        updateInProgress = true;
6003        hooks.updateOffset(this);
6004        updateInProgress = false;
6005    }
6006}
6007
6008function isMoment (obj) {
6009    return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
6010}
6011
6012function absFloor (number) {
6013    if (number < 0) {
6014        // -0 -> 0
6015        return Math.ceil(number) || 0;
6016    } else {
6017        return Math.floor(number);
6018    }
6019}
6020
6021function toInt(argumentForCoercion) {
6022    var coercedNumber = +argumentForCoercion,
6023        value = 0;
6024
6025    if (coercedNumber !== 0 && isFinite(coercedNumber)) {
6026        value = absFloor(coercedNumber);
6027    }
6028
6029    return value;
6030}
6031
6032// compare two arrays, return the number of differences
6033function compareArrays(array1, array2, dontConvert) {
6034    var len = Math.min(array1.length, array2.length),
6035        lengthDiff = Math.abs(array1.length - array2.length),
6036        diffs = 0,
6037        i;
6038    for (i = 0; i < len; i++) {
6039        if ((dontConvert && array1[i] !== array2[i]) ||
6040            (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
6041            diffs++;
6042        }
6043    }
6044    return diffs + lengthDiff;
6045}
6046
6047function warn(msg) {
6048    if (hooks.suppressDeprecationWarnings === false &&
6049            (typeof console !==  'undefined') && console.warn) {
6050        console.warn('Deprecation warning: ' + msg);
6051    }
6052}
6053
6054function deprecate(msg, fn) {
6055    var firstTime = true;
6056
6057    return extend(function () {
6058        if (hooks.deprecationHandler != null) {
6059            hooks.deprecationHandler(null, msg);
6060        }
6061        if (firstTime) {
6062            var args = [];
6063            var arg;
6064            for (var i = 0; i < arguments.length; i++) {
6065                arg = '';
6066                if (typeof arguments[i] === 'object') {
6067                    arg += '\n[' + i + '] ';
6068                    for (var key in arguments[0]) {
6069                        arg += key + ': ' + arguments[0][key] + ', ';
6070                    }
6071                    arg = arg.slice(0, -2); // Remove trailing comma and space
6072                } else {
6073                    arg = arguments[i];
6074                }
6075                args.push(arg);
6076            }
6077            warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
6078            firstTime = false;
6079        }
6080        return fn.apply(this, arguments);
6081    }, fn);
6082}
6083
6084var deprecations = {};
6085
6086function deprecateSimple(name, msg) {
6087    if (hooks.deprecationHandler != null) {
6088        hooks.deprecationHandler(name, msg);
6089    }
6090    if (!deprecations[name]) {
6091        warn(msg);
6092        deprecations[name] = true;
6093    }
6094}
6095
6096hooks.suppressDeprecationWarnings = false;
6097hooks.deprecationHandler = null;
6098
6099function isFunction(input) {
6100    return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
6101}
6102
6103function set (config) {
6104    var prop, i;
6105    for (i in config) {
6106        prop = config[i];
6107        if (isFunction(prop)) {
6108            this[i] = prop;
6109        } else {
6110            this['_' + i] = prop;
6111        }
6112    }
6113    this._config = config;
6114    // Lenient ordinal parsing accepts just a number in addition to
6115    // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
6116    // TODO: Remove "ordinalParse" fallback in next major release.
6117    this._dayOfMonthOrdinalParseLenient = new RegExp(
6118        (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +
6119            '|' + (/\d{1,2}/).source);
6120}
6121
6122function mergeConfigs(parentConfig, childConfig) {
6123    var res = extend({}, parentConfig), prop;
6124    for (prop in childConfig) {
6125        if (hasOwnProp(childConfig, prop)) {
6126            if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
6127                res[prop] = {};
6128                extend(res[prop], parentConfig[prop]);
6129                extend(res[prop], childConfig[prop]);
6130            } else if (childConfig[prop] != null) {
6131                res[prop] = childConfig[prop];
6132            } else {
6133                delete res[prop];
6134            }
6135        }
6136    }
6137    for (prop in parentConfig) {
6138        if (hasOwnProp(parentConfig, prop) &&
6139                !hasOwnProp(childConfig, prop) &&
6140                isObject(parentConfig[prop])) {
6141            // make sure changes to properties don't modify parent config
6142            res[prop] = extend({}, res[prop]);
6143        }
6144    }
6145    return res;
6146}
6147
6148function Locale(config) {
6149    if (config != null) {
6150        this.set(config);
6151    }
6152}
6153
6154var keys;
6155
6156if (Object.keys) {
6157    keys = Object.keys;
6158} else {
6159    keys = function (obj) {
6160        var i, res = [];
6161        for (i in obj) {
6162            if (hasOwnProp(obj, i)) {
6163                res.push(i);
6164            }
6165        }
6166        return res;
6167    };
6168}
6169
6170var defaultCalendar = {
6171    sameDay : '[Today at] LT',
6172    nextDay : '[Tomorrow at] LT',
6173    nextWeek : 'dddd [at] LT',
6174    lastDay : '[Yesterday at] LT',
6175    lastWeek : '[Last] dddd [at] LT',
6176    sameElse : 'L'
6177};
6178
6179function calendar (key, mom, now) {
6180    var output = this._calendar[key] || this._calendar['sameElse'];
6181    return isFunction(output) ? output.call(mom, now) : output;
6182}
6183
6184var defaultLongDateFormat = {
6185    LTS  : 'h:mm:ss A',
6186    LT   : 'h:mm A',
6187    L    : 'MM/DD/YYYY',
6188    LL   : 'MMMM D, YYYY',
6189    LLL  : 'MMMM D, YYYY h:mm A',
6190    LLLL : 'dddd, MMMM D, YYYY h:mm A'
6191};
6192
6193function longDateFormat (key) {
6194    var format = this._longDateFormat[key],
6195        formatUpper = this._longDateFormat[key.toUpperCase()];
6196
6197    if (format || !formatUpper) {
6198        return format;
6199    }
6200
6201    this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
6202        return val.slice(1);
6203    });
6204
6205    return this._longDateFormat[key];
6206}
6207
6208var defaultInvalidDate = 'Invalid date';
6209
6210function invalidDate () {
6211    return this._invalidDate;
6212}
6213
6214var defaultOrdinal = '%d';
6215var defaultDayOfMonthOrdinalParse = /\d{1,2}/;
6216
6217function ordinal (number) {
6218    return this._ordinal.replace('%d', number);
6219}
6220
6221var defaultRelativeTime = {
6222    future : 'in %s',
6223    past   : '%s ago',
6224    s  : 'a few seconds',
6225    ss : '%d seconds',
6226    m  : 'a minute',
6227    mm : '%d minutes',
6228    h  : 'an hour',
6229    hh : '%d hours',
6230    d  : 'a day',
6231    dd : '%d days',
6232    M  : 'a month',
6233    MM : '%d months',
6234    y  : 'a year',
6235    yy : '%d years'
6236};
6237
6238function relativeTime (number, withoutSuffix, string, isFuture) {
6239    var output = this._relativeTime[string];
6240    return (isFunction(output)) ?
6241        output(number, withoutSuffix, string, isFuture) :
6242        output.replace(/%d/i, number);
6243}
6244
6245function pastFuture (diff, output) {
6246    var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
6247    return isFunction(format) ? format(output) : format.replace(/%s/i, output);
6248}
6249
6250var aliases = {};
6251
6252function addUnitAlias (unit, shorthand) {
6253    var lowerCase = unit.toLowerCase();
6254    aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
6255}
6256
6257function normalizeUnits(units) {
6258    return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
6259}
6260
6261function normalizeObjectUnits(inputObject) {
6262    var normalizedInput = {},
6263        normalizedProp,
6264        prop;
6265
6266    for (prop in inputObject) {
6267        if (hasOwnProp(inputObject, prop)) {
6268            normalizedProp = normalizeUnits(prop);
6269            if (normalizedProp) {
6270                normalizedInput[normalizedProp] = inputObject[prop];
6271            }
6272        }
6273    }
6274
6275    return normalizedInput;
6276}
6277
6278var priorities = {};
6279
6280function addUnitPriority(unit, priority) {
6281    priorities[unit] = priority;
6282}
6283
6284function getPrioritizedUnits(unitsObj) {
6285    var units = [];
6286    for (var u in unitsObj) {
6287        units.push({unit: u, priority: priorities[u]});
6288    }
6289    units.sort(function (a, b) {
6290        return a.priority - b.priority;
6291    });
6292    return units;
6293}
6294
6295function zeroFill(number, targetLength, forceSign) {
6296    var absNumber = '' + Math.abs(number),
6297        zerosToFill = targetLength - absNumber.length,
6298        sign = number >= 0;
6299    return (sign ? (forceSign ? '+' : '') : '-') +
6300        Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
6301}
6302
6303var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
6304
6305var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
6306
6307var formatFunctions = {};
6308
6309var formatTokenFunctions = {};
6310
6311// token:    'M'
6312// padded:   ['MM', 2]
6313// ordinal:  'Mo'
6314// callback: function () { this.month() + 1 }
6315function addFormatToken (token, padded, ordinal, callback) {
6316    var func = callback;
6317    if (typeof callback === 'string') {
6318        func = function () {
6319            return this[callback]();
6320        };
6321    }
6322    if (token) {
6323        formatTokenFunctions[token] = func;
6324    }
6325    if (padded) {
6326        formatTokenFunctions[padded[0]] = function () {
6327            return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
6328        };
6329    }
6330    if (ordinal) {
6331        formatTokenFunctions[ordinal] = function () {
6332            return this.localeData().ordinal(func.apply(this, arguments), token);
6333        };
6334    }
6335}
6336
6337function removeFormattingTokens(input) {
6338    if (input.match(/\[[\s\S]/)) {
6339        return input.replace(/^\[|\]$/g, '');
6340    }
6341    return input.replace(/\\/g, '');
6342}
6343
6344function makeFormatFunction(format) {
6345    var array = format.match(formattingTokens), i, length;
6346
6347    for (i = 0, length = array.length; i < length; i++) {
6348        if (formatTokenFunctions[array[i]]) {
6349            array[i] = formatTokenFunctions[array[i]];
6350        } else {
6351            array[i] = removeFormattingTokens(array[i]);
6352        }
6353    }
6354
6355    return function (mom) {
6356        var output = '', i;
6357        for (i = 0; i < length; i++) {
6358            output += isFunction(array[i]) ? array[i].call(mom, format) : array[i];
6359        }
6360        return output;
6361    };
6362}
6363
6364// format date using native date object
6365function formatMoment(m, format) {
6366    if (!m.isValid()) {
6367        return m.localeData().invalidDate();
6368    }
6369
6370    format = expandFormat(format, m.localeData());
6371    formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
6372
6373    return formatFunctions[format](m);
6374}
6375
6376function expandFormat(format, locale) {
6377    var i = 5;
6378
6379    function replaceLongDateFormatTokens(input) {
6380        return locale.longDateFormat(input) || input;
6381    }
6382
6383    localFormattingTokens.lastIndex = 0;
6384    while (i >= 0 && localFormattingTokens.test(format)) {
6385        format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
6386        localFormattingTokens.lastIndex = 0;
6387        i -= 1;
6388    }
6389
6390    return format;
6391}
6392
6393var match1         = /\d/;            //       0 - 9
6394var match2         = /\d\d/;          //      00 - 99
6395var match3         = /\d{3}/;         //     000 - 999
6396var match4         = /\d{4}/;         //    0000 - 9999
6397var match6         = /[+-]?\d{6}/;    // -999999 - 999999
6398var match1to2      = /\d\d?/;         //       0 - 99
6399var match3to4      = /\d\d\d\d?/;     //     999 - 9999
6400var match5to6      = /\d\d\d\d\d\d?/; //   99999 - 999999
6401var match1to3      = /\d{1,3}/;       //       0 - 999
6402var match1to4      = /\d{1,4}/;       //       0 - 9999
6403var match1to6      = /[+-]?\d{1,6}/;  // -999999 - 999999
6404
6405var matchUnsigned  = /\d+/;           //       0 - inf
6406var matchSigned    = /[+-]?\d+/;      //    -inf - inf
6407
6408var matchOffset    = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
6409var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
6410
6411var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
6412
6413// any word (or two) characters or numbers including two/three word month in arabic.
6414// includes scottish gaelic two word and hyphenated months
6415var matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i;
6416
6417
6418var regexes = {};
6419
6420function addRegexToken (token, regex, strictRegex) {
6421    regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
6422        return (isStrict && strictRegex) ? strictRegex : regex;
6423    };
6424}
6425
6426function getParseRegexForToken (token, config) {
6427    if (!hasOwnProp(regexes, token)) {
6428        return new RegExp(unescapeFormat(token));
6429    }
6430
6431    return regexes[token](config._strict, config._locale);
6432}
6433
6434// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
6435function unescapeFormat(s) {
6436    return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
6437        return p1 || p2 || p3 || p4;
6438    }));
6439}
6440
6441function regexEscape(s) {
6442    return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
6443}
6444
6445var tokens = {};
6446
6447function addParseToken (token, callback) {
6448    var i, func = callback;
6449    if (typeof token === 'string') {
6450        token = [token];
6451    }
6452    if (isNumber(callback)) {
6453        func = function (input, array) {
6454            array[callback] = toInt(input);
6455        };
6456    }
6457    for (i = 0; i < token.length; i++) {
6458        tokens[token[i]] = func;
6459    }
6460}
6461
6462function addWeekParseToken (token, callback) {
6463    addParseToken(token, function (input, array, config, token) {
6464        config._w = config._w || {};
6465        callback(input, config._w, config, token);
6466    });
6467}
6468
6469function addTimeToArrayFromToken(token, input, config) {
6470    if (input != null && hasOwnProp(tokens, token)) {
6471        tokens[token](input, config._a, config, token);
6472    }
6473}
6474
6475var YEAR = 0;
6476var MONTH = 1;
6477var DATE = 2;
6478var HOUR = 3;
6479var MINUTE = 4;
6480var SECOND = 5;
6481var MILLISECOND = 6;
6482var WEEK = 7;
6483var WEEKDAY = 8;
6484
6485// FORMATTING
6486
6487addFormatToken('Y', 0, 0, function () {
6488    var y = this.year();
6489    return y <= 9999 ? '' + y : '+' + y;
6490});
6491
6492addFormatToken(0, ['YY', 2], 0, function () {
6493    return this.year() % 100;
6494});
6495
6496addFormatToken(0, ['YYYY',   4],       0, 'year');
6497addFormatToken(0, ['YYYYY',  5],       0, 'year');
6498addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
6499
6500// ALIASES
6501
6502addUnitAlias('year', 'y');
6503
6504// PRIORITIES
6505
6506addUnitPriority('year', 1);
6507
6508// PARSING
6509
6510addRegexToken('Y',      matchSigned);
6511addRegexToken('YY',     match1to2, match2);
6512addRegexToken('YYYY',   match1to4, match4);
6513addRegexToken('YYYYY',  match1to6, match6);
6514addRegexToken('YYYYYY', match1to6, match6);
6515
6516addParseToken(['YYYYY', 'YYYYYY'], YEAR);
6517addParseToken('YYYY', function (input, array) {
6518    array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
6519});
6520addParseToken('YY', function (input, array) {
6521    array[YEAR] = hooks.parseTwoDigitYear(input);
6522});
6523addParseToken('Y', function (input, array) {
6524    array[YEAR] = parseInt(input, 10);
6525});
6526
6527// HELPERS
6528
6529function daysInYear(year) {
6530    return isLeapYear(year) ? 366 : 365;
6531}
6532
6533function isLeapYear(year) {
6534    return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
6535}
6536
6537// HOOKS
6538
6539hooks.parseTwoDigitYear = function (input) {
6540    return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
6541};
6542
6543// MOMENTS
6544
6545var getSetYear = makeGetSet('FullYear', true);
6546
6547function getIsLeapYear () {
6548    return isLeapYear(this.year());
6549}
6550
6551function makeGetSet (unit, keepTime) {
6552    return function (value) {
6553        if (value != null) {
6554            set$1(this, unit, value);
6555            hooks.updateOffset(this, keepTime);
6556            return this;
6557        } else {
6558            return get(this, unit);
6559        }
6560    };
6561}
6562
6563function get (mom, unit) {
6564    return mom.isValid() ?
6565        mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
6566}
6567
6568function set$1 (mom, unit, value) {
6569    if (mom.isValid() && !isNaN(value)) {
6570        if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) {
6571            mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month()));
6572        }
6573        else {
6574            mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
6575        }
6576    }
6577}
6578
6579// MOMENTS
6580
6581function stringGet (units) {
6582    units = normalizeUnits(units);
6583    if (isFunction(this[units])) {
6584        return this[units]();
6585    }
6586    return this;
6587}
6588
6589
6590function stringSet (units, value) {
6591    if (typeof units === 'object') {
6592        units = normalizeObjectUnits(units);
6593        var prioritized = getPrioritizedUnits(units);
6594        for (var i = 0; i < prioritized.length; i++) {
6595            this[prioritized[i].unit](units[prioritized[i].unit]);
6596        }
6597    } else {
6598        units = normalizeUnits(units);
6599        if (isFunction(this[units])) {
6600            return this[units](value);
6601        }
6602    }
6603    return this;
6604}
6605
6606function mod(n, x) {
6607    return ((n % x) + x) % x;
6608}
6609
6610var indexOf;
6611
6612if (Array.prototype.indexOf) {
6613    indexOf = Array.prototype.indexOf;
6614} else {
6615    indexOf = function (o) {
6616        // I know
6617        var i;
6618        for (i = 0; i < this.length; ++i) {
6619            if (this[i] === o) {
6620                return i;
6621            }
6622        }
6623        return -1;
6624    };
6625}
6626
6627function daysInMonth(year, month) {
6628    if (isNaN(year) || isNaN(month)) {
6629        return NaN;
6630    }
6631    var modMonth = mod(month, 12);
6632    year += (month - modMonth) / 12;
6633    return modMonth === 1 ? (isLeapYear(year) ? 29 : 28) : (31 - modMonth % 7 % 2);
6634}
6635
6636// FORMATTING
6637
6638addFormatToken('M', ['MM', 2], 'Mo', function () {
6639    return this.month() + 1;
6640});
6641
6642addFormatToken('MMM', 0, 0, function (format) {
6643    return this.localeData().monthsShort(this, format);
6644});
6645
6646addFormatToken('MMMM', 0, 0, function (format) {
6647    return this.localeData().months(this, format);
6648});
6649
6650// ALIASES
6651
6652addUnitAlias('month', 'M');
6653
6654// PRIORITY
6655
6656addUnitPriority('month', 8);
6657
6658// PARSING
6659
6660addRegexToken('M',    match1to2);
6661addRegexToken('MM',   match1to2, match2);
6662addRegexToken('MMM',  function (isStrict, locale) {
6663    return locale.monthsShortRegex(isStrict);
6664});
6665addRegexToken('MMMM', function (isStrict, locale) {
6666    return locale.monthsRegex(isStrict);
6667});
6668
6669addParseToken(['M', 'MM'], function (input, array) {
6670    array[MONTH] = toInt(input) - 1;
6671});
6672
6673addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
6674    var month = config._locale.monthsParse(input, token, config._strict);
6675    // if we didn't find a month name, mark the date as invalid.
6676    if (month != null) {
6677        array[MONTH] = month;
6678    } else {
6679        getParsingFlags(config).invalidMonth = input;
6680    }
6681});
6682
6683// LOCALES
6684
6685var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
6686var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
6687function localeMonths (m, format) {
6688    if (!m) {
6689        return isArray(this._months) ? this._months :
6690            this._months['standalone'];
6691    }
6692    return isArray(this._months) ? this._months[m.month()] :
6693        this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
6694}
6695
6696var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
6697function localeMonthsShort (m, format) {
6698    if (!m) {
6699        return isArray(this._monthsShort) ? this._monthsShort :
6700            this._monthsShort['standalone'];
6701    }
6702    return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
6703        this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
6704}
6705
6706function handleStrictParse(monthName, format, strict) {
6707    var i, ii, mom, llc = monthName.toLocaleLowerCase();
6708    if (!this._monthsParse) {
6709        // this is not used
6710        this._monthsParse = [];
6711        this._longMonthsParse = [];
6712        this._shortMonthsParse = [];
6713        for (i = 0; i < 12; ++i) {
6714            mom = createUTC([2000, i]);
6715            this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
6716            this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
6717        }
6718    }
6719
6720    if (strict) {
6721        if (format === 'MMM') {
6722            ii = indexOf.call(this._shortMonthsParse, llc);
6723            return ii !== -1 ? ii : null;
6724        } else {
6725            ii = indexOf.call(this._longMonthsParse, llc);
6726            return ii !== -1 ? ii : null;
6727        }
6728    } else {
6729        if (format === 'MMM') {
6730            ii = indexOf.call(this._shortMonthsParse, llc);
6731            if (ii !== -1) {
6732                return ii;
6733            }
6734            ii = indexOf.call(this._longMonthsParse, llc);
6735            return ii !== -1 ? ii : null;
6736        } else {
6737            ii = indexOf.call(this._longMonthsParse, llc);
6738            if (ii !== -1) {
6739                return ii;
6740            }
6741            ii = indexOf.call(this._shortMonthsParse, llc);
6742            return ii !== -1 ? ii : null;
6743        }
6744    }
6745}
6746
6747function localeMonthsParse (monthName, format, strict) {
6748    var i, mom, regex;
6749
6750    if (this._monthsParseExact) {
6751        return handleStrictParse.call(this, monthName, format, strict);
6752    }
6753
6754    if (!this._monthsParse) {
6755        this._monthsParse = [];
6756        this._longMonthsParse = [];
6757        this._shortMonthsParse = [];
6758    }
6759
6760    // TODO: add sorting
6761    // Sorting makes sure if one month (or abbr) is a prefix of another
6762    // see sorting in computeMonthsParse
6763    for (i = 0; i < 12; i++) {
6764        // make the regex if we don't have it already
6765        mom = createUTC([2000, i]);
6766        if (strict && !this._longMonthsParse[i]) {
6767            this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
6768            this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
6769        }
6770        if (!strict && !this._monthsParse[i]) {
6771            regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
6772            this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
6773        }
6774        // test the regex
6775        if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
6776            return i;
6777        } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
6778            return i;
6779        } else if (!strict && this._monthsParse[i].test(monthName)) {
6780            return i;
6781        }
6782    }
6783}
6784
6785// MOMENTS
6786
6787function setMonth (mom, value) {
6788    var dayOfMonth;
6789
6790    if (!mom.isValid()) {
6791        // No op
6792        return mom;
6793    }
6794
6795    if (typeof value === 'string') {
6796        if (/^\d+$/.test(value)) {
6797            value = toInt(value);
6798        } else {
6799            value = mom.localeData().monthsParse(value);
6800            // TODO: Another silent failure?
6801            if (!isNumber(value)) {
6802                return mom;
6803            }
6804        }
6805    }
6806
6807    dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
6808    mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
6809    return mom;
6810}
6811
6812function getSetMonth (value) {
6813    if (value != null) {
6814        setMonth(this, value);
6815        hooks.updateOffset(this, true);
6816        return this;
6817    } else {
6818        return get(this, 'Month');
6819    }
6820}
6821
6822function getDaysInMonth () {
6823    return daysInMonth(this.year(), this.month());
6824}
6825
6826var defaultMonthsShortRegex = matchWord;
6827function monthsShortRegex (isStrict) {
6828    if (this._monthsParseExact) {
6829        if (!hasOwnProp(this, '_monthsRegex')) {
6830            computeMonthsParse.call(this);
6831        }
6832        if (isStrict) {
6833            return this._monthsShortStrictRegex;
6834        } else {
6835            return this._monthsShortRegex;
6836        }
6837    } else {
6838        if (!hasOwnProp(this, '_monthsShortRegex')) {
6839            this._monthsShortRegex = defaultMonthsShortRegex;
6840        }
6841        return this._monthsShortStrictRegex && isStrict ?
6842            this._monthsShortStrictRegex : this._monthsShortRegex;
6843    }
6844}
6845
6846var defaultMonthsRegex = matchWord;
6847function monthsRegex (isStrict) {
6848    if (this._monthsParseExact) {
6849        if (!hasOwnProp(this, '_monthsRegex')) {
6850            computeMonthsParse.call(this);
6851        }
6852        if (isStrict) {
6853            return this._monthsStrictRegex;
6854        } else {
6855            return this._monthsRegex;
6856        }
6857    } else {
6858        if (!hasOwnProp(this, '_monthsRegex')) {
6859            this._monthsRegex = defaultMonthsRegex;
6860        }
6861        return this._monthsStrictRegex && isStrict ?
6862            this._monthsStrictRegex : this._monthsRegex;
6863    }
6864}
6865
6866function computeMonthsParse () {
6867    function cmpLenRev(a, b) {
6868        return b.length - a.length;
6869    }
6870
6871    var shortPieces = [], longPieces = [], mixedPieces = [],
6872        i, mom;
6873    for (i = 0; i < 12; i++) {
6874        // make the regex if we don't have it already
6875        mom = createUTC([2000, i]);
6876        shortPieces.push(this.monthsShort(mom, ''));
6877        longPieces.push(this.months(mom, ''));
6878        mixedPieces.push(this.months(mom, ''));
6879        mixedPieces.push(this.monthsShort(mom, ''));
6880    }
6881    // Sorting makes sure if one month (or abbr) is a prefix of another it
6882    // will match the longer piece.
6883    shortPieces.sort(cmpLenRev);
6884    longPieces.sort(cmpLenRev);
6885    mixedPieces.sort(cmpLenRev);
6886    for (i = 0; i < 12; i++) {
6887        shortPieces[i] = regexEscape(shortPieces[i]);
6888        longPieces[i] = regexEscape(longPieces[i]);
6889    }
6890    for (i = 0; i < 24; i++) {
6891        mixedPieces[i] = regexEscape(mixedPieces[i]);
6892    }
6893
6894    this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
6895    this._monthsShortRegex = this._monthsRegex;
6896    this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
6897    this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
6898}
6899
6900function createDate (y, m, d, h, M, s, ms) {
6901    // can't just apply() to create a date:
6902    // https://stackoverflow.com/q/181348
6903    var date = new Date(y, m, d, h, M, s, ms);
6904
6905    // the date constructor remaps years 0-99 to 1900-1999
6906    if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
6907        date.setFullYear(y);
6908    }
6909    return date;
6910}
6911
6912function createUTCDate (y) {
6913    var date = new Date(Date.UTC.apply(null, arguments));
6914
6915    // the Date.UTC function remaps years 0-99 to 1900-1999
6916    if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
6917        date.setUTCFullYear(y);
6918    }
6919    return date;
6920}
6921
6922// start-of-first-week - start-of-year
6923function firstWeekOffset(year, dow, doy) {
6924    var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
6925        fwd = 7 + dow - doy,
6926        // first-week day local weekday -- which local weekday is fwd
6927        fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
6928
6929    return -fwdlw + fwd - 1;
6930}
6931
6932// https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
6933function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
6934    var localWeekday = (7 + weekday - dow) % 7,
6935        weekOffset = firstWeekOffset(year, dow, doy),
6936        dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
6937        resYear, resDayOfYear;
6938
6939    if (dayOfYear <= 0) {
6940        resYear = year - 1;
6941        resDayOfYear = daysInYear(resYear) + dayOfYear;
6942    } else if (dayOfYear > daysInYear(year)) {
6943        resYear = year + 1;
6944        resDayOfYear = dayOfYear - daysInYear(year);
6945    } else {
6946        resYear = year;
6947        resDayOfYear = dayOfYear;
6948    }
6949
6950    return {
6951        year: resYear,
6952        dayOfYear: resDayOfYear
6953    };
6954}
6955
6956function weekOfYear(mom, dow, doy) {
6957    var weekOffset = firstWeekOffset(mom.year(), dow, doy),
6958        week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
6959        resWeek, resYear;
6960
6961    if (week < 1) {
6962        resYear = mom.year() - 1;
6963        resWeek = week + weeksInYear(resYear, dow, doy);
6964    } else if (week > weeksInYear(mom.year(), dow, doy)) {
6965        resWeek = week - weeksInYear(mom.year(), dow, doy);
6966        resYear = mom.year() + 1;
6967    } else {
6968        resYear = mom.year();
6969        resWeek = week;
6970    }
6971
6972    return {
6973        week: resWeek,
6974        year: resYear
6975    };
6976}
6977
6978function weeksInYear(year, dow, doy) {
6979    var weekOffset = firstWeekOffset(year, dow, doy),
6980        weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
6981    return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
6982}
6983
6984// FORMATTING
6985
6986addFormatToken('w', ['ww', 2], 'wo', 'week');
6987addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
6988
6989// ALIASES
6990
6991addUnitAlias('week', 'w');
6992addUnitAlias('isoWeek', 'W');
6993
6994// PRIORITIES
6995
6996addUnitPriority('week', 5);
6997addUnitPriority('isoWeek', 5);
6998
6999// PARSING
7000
7001addRegexToken('w',  match1to2);
7002addRegexToken('ww', match1to2, match2);
7003addRegexToken('W',  match1to2);
7004addRegexToken('WW', match1to2, match2);
7005
7006addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
7007    week[token.substr(0, 1)] = toInt(input);
7008});
7009
7010// HELPERS
7011
7012// LOCALES
7013
7014function localeWeek (mom) {
7015    return weekOfYear(mom, this._week.dow, this._week.doy).week;
7016}
7017
7018var defaultLocaleWeek = {
7019    dow : 0, // Sunday is the first day of the week.
7020    doy : 6  // The week that contains Jan 1st is the first week of the year.
7021};
7022
7023function localeFirstDayOfWeek () {
7024    return this._week.dow;
7025}
7026
7027function localeFirstDayOfYear () {
7028    return this._week.doy;
7029}
7030
7031// MOMENTS
7032
7033function getSetWeek (input) {
7034    var week = this.localeData().week(this);
7035    return input == null ? week : this.add((input - week) * 7, 'd');
7036}
7037
7038function getSetISOWeek (input) {
7039    var week = weekOfYear(this, 1, 4).week;
7040    return input == null ? week : this.add((input - week) * 7, 'd');
7041}
7042
7043// FORMATTING
7044
7045addFormatToken('d', 0, 'do', 'day');
7046
7047addFormatToken('dd', 0, 0, function (format) {
7048    return this.localeData().weekdaysMin(this, format);
7049});
7050
7051addFormatToken('ddd', 0, 0, function (format) {
7052    return this.localeData().weekdaysShort(this, format);
7053});
7054
7055addFormatToken('dddd', 0, 0, function (format) {
7056    return this.localeData().weekdays(this, format);
7057});
7058
7059addFormatToken('e', 0, 0, 'weekday');
7060addFormatToken('E', 0, 0, 'isoWeekday');
7061
7062// ALIASES
7063
7064addUnitAlias('day', 'd');
7065addUnitAlias('weekday', 'e');
7066addUnitAlias('isoWeekday', 'E');
7067
7068// PRIORITY
7069addUnitPriority('day', 11);
7070addUnitPriority('weekday', 11);
7071addUnitPriority('isoWeekday', 11);
7072
7073// PARSING
7074
7075addRegexToken('d',    match1to2);
7076addRegexToken('e',    match1to2);
7077addRegexToken('E',    match1to2);
7078addRegexToken('dd',   function (isStrict, locale) {
7079    return locale.weekdaysMinRegex(isStrict);
7080});
7081addRegexToken('ddd',   function (isStrict, locale) {
7082    return locale.weekdaysShortRegex(isStrict);
7083});
7084addRegexToken('dddd',   function (isStrict, locale) {
7085    return locale.weekdaysRegex(isStrict);
7086});
7087
7088addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
7089    var weekday = config._locale.weekdaysParse(input, token, config._strict);
7090    // if we didn't get a weekday name, mark the date as invalid
7091    if (weekday != null) {
7092        week.d = weekday;
7093    } else {
7094        getParsingFlags(config).invalidWeekday = input;
7095    }
7096});
7097
7098addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
7099    week[token] = toInt(input);
7100});
7101
7102// HELPERS
7103
7104function parseWeekday(input, locale) {
7105    if (typeof input !== 'string') {
7106        return input;
7107    }
7108
7109    if (!isNaN(input)) {
7110        return parseInt(input, 10);
7111    }
7112
7113    input = locale.weekdaysParse(input);
7114    if (typeof input === 'number') {
7115        return input;
7116    }
7117
7118    return null;
7119}
7120
7121function parseIsoWeekday(input, locale) {
7122    if (typeof input === 'string') {
7123        return locale.weekdaysParse(input) % 7 || 7;
7124    }
7125    return isNaN(input) ? null : input;
7126}
7127
7128// LOCALES
7129
7130var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
7131function localeWeekdays (m, format) {
7132    if (!m) {
7133        return isArray(this._weekdays) ? this._weekdays :
7134            this._weekdays['standalone'];
7135    }
7136    return isArray(this._weekdays) ? this._weekdays[m.day()] :
7137        this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
7138}
7139
7140var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
7141function localeWeekdaysShort (m) {
7142    return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
7143}
7144
7145var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
7146function localeWeekdaysMin (m) {
7147    return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
7148}
7149
7150function handleStrictParse$1(weekdayName, format, strict) {
7151    var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
7152    if (!this._weekdaysParse) {
7153        this._weekdaysParse = [];
7154        this._shortWeekdaysParse = [];
7155        this._minWeekdaysParse = [];
7156
7157        for (i = 0; i < 7; ++i) {
7158            mom = createUTC([2000, 1]).day(i);
7159            this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
7160            this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
7161            this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
7162        }
7163    }
7164
7165    if (strict) {
7166        if (format === 'dddd') {
7167            ii = indexOf.call(this._weekdaysParse, llc);
7168            return ii !== -1 ? ii : null;
7169        } else if (format === 'ddd') {
7170            ii = indexOf.call(this._shortWeekdaysParse, llc);
7171            return ii !== -1 ? ii : null;
7172        } else {
7173            ii = indexOf.call(this._minWeekdaysParse, llc);
7174            return ii !== -1 ? ii : null;
7175        }
7176    } else {
7177        if (format === 'dddd') {
7178            ii = indexOf.call(this._weekdaysParse, llc);
7179            if (ii !== -1) {
7180                return ii;
7181            }
7182            ii = indexOf.call(this._shortWeekdaysParse, llc);
7183            if (ii !== -1) {
7184                return ii;
7185            }
7186            ii = indexOf.call(this._minWeekdaysParse, llc);
7187            return ii !== -1 ? ii : null;
7188        } else if (format === 'ddd') {
7189            ii = indexOf.call(this._shortWeekdaysParse, llc);
7190            if (ii !== -1) {
7191                return ii;
7192            }
7193            ii = indexOf.call(this._weekdaysParse, llc);
7194            if (ii !== -1) {
7195                return ii;
7196            }
7197            ii = indexOf.call(this._minWeekdaysParse, llc);
7198            return ii !== -1 ? ii : null;
7199        } else {
7200            ii = indexOf.call(this._minWeekdaysParse, llc);
7201            if (ii !== -1) {
7202                return ii;
7203            }
7204            ii = indexOf.call(this._weekdaysParse, llc);
7205            if (ii !== -1) {
7206                return ii;
7207            }
7208            ii = indexOf.call(this._shortWeekdaysParse, llc);
7209            return ii !== -1 ? ii : null;
7210        }
7211    }
7212}
7213
7214function localeWeekdaysParse (weekdayName, format, strict) {
7215    var i, mom, regex;
7216
7217    if (this._weekdaysParseExact) {
7218        return handleStrictParse$1.call(this, weekdayName, format, strict);
7219    }
7220
7221    if (!this._weekdaysParse) {
7222        this._weekdaysParse = [];
7223        this._minWeekdaysParse = [];
7224        this._shortWeekdaysParse = [];
7225        this._fullWeekdaysParse = [];
7226    }
7227
7228    for (i = 0; i < 7; i++) {
7229        // make the regex if we don't have it already
7230
7231        mom = createUTC([2000, 1]).day(i);
7232        if (strict && !this._fullWeekdaysParse[i]) {
7233            this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i');
7234            this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i');
7235            this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i');
7236        }
7237        if (!this._weekdaysParse[i]) {
7238            regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
7239            this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
7240        }
7241        // test the regex
7242        if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
7243            return i;
7244        } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
7245            return i;
7246        } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
7247            return i;
7248        } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
7249            return i;
7250        }
7251    }
7252}
7253
7254// MOMENTS
7255
7256function getSetDayOfWeek (input) {
7257    if (!this.isValid()) {
7258        return input != null ? this : NaN;
7259    }
7260    var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
7261    if (input != null) {
7262        input = parseWeekday(input, this.localeData());
7263        return this.add(input - day, 'd');
7264    } else {
7265        return day;
7266    }
7267}
7268
7269function getSetLocaleDayOfWeek (input) {
7270    if (!this.isValid()) {
7271        return input != null ? this : NaN;
7272    }
7273    var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
7274    return input == null ? weekday : this.add(input - weekday, 'd');
7275}
7276
7277function getSetISODayOfWeek (input) {
7278    if (!this.isValid()) {
7279        return input != null ? this : NaN;
7280    }
7281
7282    // behaves the same as moment#day except
7283    // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
7284    // as a setter, sunday should belong to the previous week.
7285
7286    if (input != null) {
7287        var weekday = parseIsoWeekday(input, this.localeData());
7288        return this.day(this.day() % 7 ? weekday : weekday - 7);
7289    } else {
7290        return this.day() || 7;
7291    }
7292}
7293
7294var defaultWeekdaysRegex = matchWord;
7295function weekdaysRegex (isStrict) {
7296    if (this._weekdaysParseExact) {
7297        if (!hasOwnProp(this, '_weekdaysRegex')) {
7298            computeWeekdaysParse.call(this);
7299        }
7300        if (isStrict) {
7301            return this._weekdaysStrictRegex;
7302        } else {
7303            return this._weekdaysRegex;
7304        }
7305    } else {
7306        if (!hasOwnProp(this, '_weekdaysRegex')) {
7307            this._weekdaysRegex = defaultWeekdaysRegex;
7308        }
7309        return this._weekdaysStrictRegex && isStrict ?
7310            this._weekdaysStrictRegex : this._weekdaysRegex;
7311    }
7312}
7313
7314var defaultWeekdaysShortRegex = matchWord;
7315function weekdaysShortRegex (isStrict) {
7316    if (this._weekdaysParseExact) {
7317        if (!hasOwnProp(this, '_weekdaysRegex')) {
7318            computeWeekdaysParse.call(this);
7319        }
7320        if (isStrict) {
7321            return this._weekdaysShortStrictRegex;
7322        } else {
7323            return this._weekdaysShortRegex;
7324        }
7325    } else {
7326        if (!hasOwnProp(this, '_weekdaysShortRegex')) {
7327            this._weekdaysShortRegex = defaultWeekdaysShortRegex;
7328        }
7329        return this._weekdaysShortStrictRegex && isStrict ?
7330            this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
7331    }
7332}
7333
7334var defaultWeekdaysMinRegex = matchWord;
7335function weekdaysMinRegex (isStrict) {
7336    if (this._weekdaysParseExact) {
7337        if (!hasOwnProp(this, '_weekdaysRegex')) {
7338            computeWeekdaysParse.call(this);
7339        }
7340        if (isStrict) {
7341            return this._weekdaysMinStrictRegex;
7342        } else {
7343            return this._weekdaysMinRegex;
7344        }
7345    } else {
7346        if (!hasOwnProp(this, '_weekdaysMinRegex')) {
7347            this._weekdaysMinRegex = defaultWeekdaysMinRegex;
7348        }
7349        return this._weekdaysMinStrictRegex && isStrict ?
7350            this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
7351    }
7352}
7353
7354
7355function computeWeekdaysParse () {
7356    function cmpLenRev(a, b) {
7357        return b.length - a.length;
7358    }
7359
7360    var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
7361        i, mom, minp, shortp, longp;
7362    for (i = 0; i < 7; i++) {
7363        // make the regex if we don't have it already
7364        mom = createUTC([2000, 1]).day(i);
7365        minp = this.weekdaysMin(mom, '');
7366        shortp = this.weekdaysShort(mom, '');
7367        longp = this.weekdays(mom, '');
7368        minPieces.push(minp);
7369        shortPieces.push(shortp);
7370        longPieces.push(longp);
7371        mixedPieces.push(minp);
7372        mixedPieces.push(shortp);
7373        mixedPieces.push(longp);
7374    }
7375    // Sorting makes sure if one weekday (or abbr) is a prefix of another it
7376    // will match the longer piece.
7377    minPieces.sort(cmpLenRev);
7378    shortPieces.sort(cmpLenRev);
7379    longPieces.sort(cmpLenRev);
7380    mixedPieces.sort(cmpLenRev);
7381    for (i = 0; i < 7; i++) {
7382        shortPieces[i] = regexEscape(shortPieces[i]);
7383        longPieces[i] = regexEscape(longPieces[i]);
7384        mixedPieces[i] = regexEscape(mixedPieces[i]);
7385    }
7386
7387    this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
7388    this._weekdaysShortRegex = this._weekdaysRegex;
7389    this._weekdaysMinRegex = this._weekdaysRegex;
7390
7391    this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
7392    this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
7393    this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
7394}
7395
7396// FORMATTING
7397
7398function hFormat() {
7399    return this.hours() % 12 || 12;
7400}
7401
7402function kFormat() {
7403    return this.hours() || 24;
7404}
7405
7406addFormatToken('H', ['HH', 2], 0, 'hour');
7407addFormatToken('h', ['hh', 2], 0, hFormat);
7408addFormatToken('k', ['kk', 2], 0, kFormat);
7409
7410addFormatToken('hmm', 0, 0, function () {
7411    return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
7412});
7413
7414addFormatToken('hmmss', 0, 0, function () {
7415    return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
7416        zeroFill(this.seconds(), 2);
7417});
7418
7419addFormatToken('Hmm', 0, 0, function () {
7420    return '' + this.hours() + zeroFill(this.minutes(), 2);
7421});
7422
7423addFormatToken('Hmmss', 0, 0, function () {
7424    return '' + this.hours() + zeroFill(this.minutes(), 2) +
7425        zeroFill(this.seconds(), 2);
7426});
7427
7428function meridiem (token, lowercase) {
7429    addFormatToken(token, 0, 0, function () {
7430        return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
7431    });
7432}
7433
7434meridiem('a', true);
7435meridiem('A', false);
7436
7437// ALIASES
7438
7439addUnitAlias('hour', 'h');
7440
7441// PRIORITY
7442addUnitPriority('hour', 13);
7443
7444// PARSING
7445
7446function matchMeridiem (isStrict, locale) {
7447    return locale._meridiemParse;
7448}
7449
7450addRegexToken('a',  matchMeridiem);
7451addRegexToken('A',  matchMeridiem);
7452addRegexToken('H',  match1to2);
7453addRegexToken('h',  match1to2);
7454addRegexToken('k',  match1to2);
7455addRegexToken('HH', match1to2, match2);
7456addRegexToken('hh', match1to2, match2);
7457addRegexToken('kk', match1to2, match2);
7458
7459addRegexToken('hmm', match3to4);
7460addRegexToken('hmmss', match5to6);
7461addRegexToken('Hmm', match3to4);
7462addRegexToken('Hmmss', match5to6);
7463
7464addParseToken(['H', 'HH'], HOUR);
7465addParseToken(['k', 'kk'], function (input, array, config) {
7466    var kInput = toInt(input);
7467    array[HOUR] = kInput === 24 ? 0 : kInput;
7468});
7469addParseToken(['a', 'A'], function (input, array, config) {
7470    config._isPm = config._locale.isPM(input);
7471    config._meridiem = input;
7472});
7473addParseToken(['h', 'hh'], function (input, array, config) {
7474    array[HOUR] = toInt(input);
7475    getParsingFlags(config).bigHour = true;
7476});
7477addParseToken('hmm', function (input, array, config) {
7478    var pos = input.length - 2;
7479    array[HOUR] = toInt(input.substr(0, pos));
7480    array[MINUTE] = toInt(input.substr(pos));
7481    getParsingFlags(config).bigHour = true;
7482});
7483addParseToken('hmmss', function (input, array, config) {
7484    var pos1 = input.length - 4;
7485    var pos2 = input.length - 2;
7486    array[HOUR] = toInt(input.substr(0, pos1));
7487    array[MINUTE] = toInt(input.substr(pos1, 2));
7488    array[SECOND] = toInt(input.substr(pos2));
7489    getParsingFlags(config).bigHour = true;
7490});
7491addParseToken('Hmm', function (input, array, config) {
7492    var pos = input.length - 2;
7493    array[HOUR] = toInt(input.substr(0, pos));
7494    array[MINUTE] = toInt(input.substr(pos));
7495});
7496addParseToken('Hmmss', function (input, array, config) {
7497    var pos1 = input.length - 4;
7498    var pos2 = input.length - 2;
7499    array[HOUR] = toInt(input.substr(0, pos1));
7500    array[MINUTE] = toInt(input.substr(pos1, 2));
7501    array[SECOND] = toInt(input.substr(pos2));
7502});
7503
7504// LOCALES
7505
7506function localeIsPM (input) {
7507    // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
7508    // Using charAt should be more compatible.
7509    return ((input + '').toLowerCase().charAt(0) === 'p');
7510}
7511
7512var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
7513function localeMeridiem (hours, minutes, isLower) {
7514    if (hours > 11) {
7515        return isLower ? 'pm' : 'PM';
7516    } else {
7517        return isLower ? 'am' : 'AM';
7518    }
7519}
7520
7521
7522// MOMENTS
7523
7524// Setting the hour should keep the time, because the user explicitly
7525// specified which hour he wants. So trying to maintain the same hour (in
7526// a new timezone) makes sense. Adding/subtracting hours does not follow
7527// this rule.
7528var getSetHour = makeGetSet('Hours', true);
7529
7530// months
7531// week
7532// weekdays
7533// meridiem
7534var baseConfig = {
7535    calendar: defaultCalendar,
7536    longDateFormat: defaultLongDateFormat,
7537    invalidDate: defaultInvalidDate,
7538    ordinal: defaultOrdinal,
7539    dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
7540    relativeTime: defaultRelativeTime,
7541
7542    months: defaultLocaleMonths,
7543    monthsShort: defaultLocaleMonthsShort,
7544
7545    week: defaultLocaleWeek,
7546
7547    weekdays: defaultLocaleWeekdays,
7548    weekdaysMin: defaultLocaleWeekdaysMin,
7549    weekdaysShort: defaultLocaleWeekdaysShort,
7550
7551    meridiemParse: defaultLocaleMeridiemParse
7552};
7553
7554// internal storage for locale config files
7555var locales = {};
7556var localeFamilies = {};
7557var globalLocale;
7558
7559function normalizeLocale(key) {
7560    return key ? key.toLowerCase().replace('_', '-') : key;
7561}
7562
7563// pick the locale from the array
7564// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
7565// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
7566function chooseLocale(names) {
7567    var i = 0, j, next, locale, split;
7568
7569    while (i < names.length) {
7570        split = normalizeLocale(names[i]).split('-');
7571        j = split.length;
7572        next = normalizeLocale(names[i + 1]);
7573        next = next ? next.split('-') : null;
7574        while (j > 0) {
7575            locale = loadLocale(split.slice(0, j).join('-'));
7576            if (locale) {
7577                return locale;
7578            }
7579            if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
7580                //the next array item is better than a shallower substring of this one
7581                break;
7582            }
7583            j--;
7584        }
7585        i++;
7586    }
7587    return null;
7588}
7589
7590function loadLocale(name) {
7591    var oldLocale = null;
7592    // TODO: Find a better way to register and load all the locales in Node
7593    if (!locales[name] && (typeof module !== 'undefined') &&
7594            module && module.exports) {
7595        try {
7596            oldLocale = globalLocale._abbr;
7597            var aliasedRequire = require;
7598            aliasedRequire('./locale/' + name);
7599            getSetGlobalLocale(oldLocale);
7600        } catch (e) {}
7601    }
7602    return locales[name];
7603}
7604
7605// This function will load locale and then set the global locale.  If
7606// no arguments are passed in, it will simply return the current global
7607// locale key.
7608function getSetGlobalLocale (key, values) {
7609    var data;
7610    if (key) {
7611        if (isUndefined(values)) {
7612            data = getLocale(key);
7613        }
7614        else {
7615            data = defineLocale(key, values);
7616        }
7617
7618        if (data) {
7619            // moment.duration._locale = moment._locale = data;
7620            globalLocale = data;
7621        }
7622    }
7623
7624    return globalLocale._abbr;
7625}
7626
7627function defineLocale (name, config) {
7628    if (config !== null) {
7629        var parentConfig = baseConfig;
7630        config.abbr = name;
7631        if (locales[name] != null) {
7632            deprecateSimple('defineLocaleOverride',
7633                    'use moment.updateLocale(localeName, config) to change ' +
7634                    'an existing locale. moment.defineLocale(localeName, ' +
7635                    'config) should only be used for creating a new locale ' +
7636                    'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
7637            parentConfig = locales[name]._config;
7638        } else if (config.parentLocale != null) {
7639            if (locales[config.parentLocale] != null) {
7640                parentConfig = locales[config.parentLocale]._config;
7641            } else {
7642                if (!localeFamilies[config.parentLocale]) {
7643                    localeFamilies[config.parentLocale] = [];
7644                }
7645                localeFamilies[config.parentLocale].push({
7646                    name: name,
7647                    config: config
7648                });
7649                return null;
7650            }
7651        }
7652        locales[name] = new Locale(mergeConfigs(parentConfig, config));
7653
7654        if (localeFamilies[name]) {
7655            localeFamilies[name].forEach(function (x) {
7656                defineLocale(x.name, x.config);
7657            });
7658        }
7659
7660        // backwards compat for now: also set the locale
7661        // make sure we set the locale AFTER all child locales have been
7662        // created, so we won't end up with the child locale set.
7663        getSetGlobalLocale(name);
7664
7665
7666        return locales[name];
7667    } else {
7668        // useful for testing
7669        delete locales[name];
7670        return null;
7671    }
7672}
7673
7674function updateLocale(name, config) {
7675    if (config != null) {
7676        var locale, tmpLocale, parentConfig = baseConfig;
7677        // MERGE
7678        tmpLocale = loadLocale(name);
7679        if (tmpLocale != null) {
7680            parentConfig = tmpLocale._config;
7681        }
7682        config = mergeConfigs(parentConfig, config);
7683        locale = new Locale(config);
7684        locale.parentLocale = locales[name];
7685        locales[name] = locale;
7686
7687        // backwards compat for now: also set the locale
7688        getSetGlobalLocale(name);
7689    } else {
7690        // pass null for config to unupdate, useful for tests
7691        if (locales[name] != null) {
7692            if (locales[name].parentLocale != null) {
7693                locales[name] = locales[name].parentLocale;
7694            } else if (locales[name] != null) {
7695                delete locales[name];
7696            }
7697        }
7698    }
7699    return locales[name];
7700}
7701
7702// returns locale data
7703function getLocale (key) {
7704    var locale;
7705
7706    if (key && key._locale && key._locale._abbr) {
7707        key = key._locale._abbr;
7708    }
7709
7710    if (!key) {
7711        return globalLocale;
7712    }
7713
7714    if (!isArray(key)) {
7715        //short-circuit everything else
7716        locale = loadLocale(key);
7717        if (locale) {
7718            return locale;
7719        }
7720        key = [key];
7721    }
7722
7723    return chooseLocale(key);
7724}
7725
7726function listLocales() {
7727    return keys(locales);
7728}
7729
7730function checkOverflow (m) {
7731    var overflow;
7732    var a = m._a;
7733
7734    if (a && getParsingFlags(m).overflow === -2) {
7735        overflow =
7736            a[MONTH]       < 0 || a[MONTH]       > 11  ? MONTH :
7737            a[DATE]        < 1 || a[DATE]        > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
7738            a[HOUR]        < 0 || a[HOUR]        > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
7739            a[MINUTE]      < 0 || a[MINUTE]      > 59  ? MINUTE :
7740            a[SECOND]      < 0 || a[SECOND]      > 59  ? SECOND :
7741            a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
7742            -1;
7743
7744        if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
7745            overflow = DATE;
7746        }
7747        if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
7748            overflow = WEEK;
7749        }
7750        if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
7751            overflow = WEEKDAY;
7752        }
7753
7754        getParsingFlags(m).overflow = overflow;
7755    }
7756
7757    return m;
7758}
7759
7760// Pick the first defined of two or three arguments.
7761function defaults(a, b, c) {
7762    if (a != null) {
7763        return a;
7764    }
7765    if (b != null) {
7766        return b;
7767    }
7768    return c;
7769}
7770
7771function currentDateArray(config) {
7772    // hooks is actually the exported moment object
7773    var nowValue = new Date(hooks.now());
7774    if (config._useUTC) {
7775        return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
7776    }
7777    return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
7778}
7779
7780// convert an array to a date.
7781// the array should mirror the parameters below
7782// note: all values past the year are optional and will default to the lowest possible value.
7783// [year, month, day , hour, minute, second, millisecond]
7784function configFromArray (config) {
7785    var i, date, input = [], currentDate, expectedWeekday, yearToUse;
7786
7787    if (config._d) {
7788        return;
7789    }
7790
7791    currentDate = currentDateArray(config);
7792
7793    //compute day of the year from weeks and weekdays
7794    if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
7795        dayOfYearFromWeekInfo(config);
7796    }
7797
7798    //if the day of the year is set, figure out what it is
7799    if (config._dayOfYear != null) {
7800        yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
7801
7802        if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
7803            getParsingFlags(config)._overflowDayOfYear = true;
7804        }
7805
7806        date = createUTCDate(yearToUse, 0, config._dayOfYear);
7807        config._a[MONTH] = date.getUTCMonth();
7808        config._a[DATE] = date.getUTCDate();
7809    }
7810
7811    // Default to current date.
7812    // * if no year, month, day of month are given, default to today
7813    // * if day of month is given, default month and year
7814    // * if month is given, default only year
7815    // * if year is given, don't default anything
7816    for (i = 0; i < 3 && config._a[i] == null; ++i) {
7817        config._a[i] = input[i] = currentDate[i];
7818    }
7819
7820    // Zero out whatever was not defaulted, including time
7821    for (; i < 7; i++) {
7822        config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
7823    }
7824
7825    // Check for 24:00:00.000
7826    if (config._a[HOUR] === 24 &&
7827            config._a[MINUTE] === 0 &&
7828            config._a[SECOND] === 0 &&
7829            config._a[MILLISECOND] === 0) {
7830        config._nextDay = true;
7831        config._a[HOUR] = 0;
7832    }
7833
7834    config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
7835    expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay();
7836
7837    // Apply timezone offset from input. The actual utcOffset can be changed
7838    // with parseZone.
7839    if (config._tzm != null) {
7840        config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
7841    }
7842
7843    if (config._nextDay) {
7844        config._a[HOUR] = 24;
7845    }
7846
7847    // check for mismatching day of week
7848    if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== expectedWeekday) {
7849        getParsingFlags(config).weekdayMismatch = true;
7850    }
7851}
7852
7853function dayOfYearFromWeekInfo(config) {
7854    var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
7855
7856    w = config._w;
7857    if (w.GG != null || w.W != null || w.E != null) {
7858        dow = 1;
7859        doy = 4;
7860
7861        // TODO: We need to take the current isoWeekYear, but that depends on
7862        // how we interpret now (local, utc, fixed offset). So create
7863        // a now version of current config (take local/utc/offset flags, and
7864        // create now).
7865        weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
7866        week = defaults(w.W, 1);
7867        weekday = defaults(w.E, 1);
7868        if (weekday < 1 || weekday > 7) {
7869            weekdayOverflow = true;
7870        }
7871    } else {
7872        dow = config._locale._week.dow;
7873        doy = config._locale._week.doy;
7874
7875        var curWeek = weekOfYear(createLocal(), dow, doy);
7876
7877        weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);
7878
7879        // Default to current week.
7880        week = defaults(w.w, curWeek.week);
7881
7882        if (w.d != null) {
7883            // weekday -- low day numbers are considered next week
7884            weekday = w.d;
7885            if (weekday < 0 || weekday > 6) {
7886                weekdayOverflow = true;
7887            }
7888        } else if (w.e != null) {
7889            // local weekday -- counting starts from begining of week
7890            weekday = w.e + dow;
7891            if (w.e < 0 || w.e > 6) {
7892                weekdayOverflow = true;
7893            }
7894        } else {
7895            // default to begining of week
7896            weekday = dow;
7897        }
7898    }
7899    if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
7900        getParsingFlags(config)._overflowWeeks = true;
7901    } else if (weekdayOverflow != null) {
7902        getParsingFlags(config)._overflowWeekday = true;
7903    } else {
7904        temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
7905        config._a[YEAR] = temp.year;
7906        config._dayOfYear = temp.dayOfYear;
7907    }
7908}
7909
7910// iso 8601 regex
7911// 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
7912var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
7913var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
7914
7915var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
7916
7917var isoDates = [
7918    ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
7919    ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
7920    ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
7921    ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
7922    ['YYYY-DDD', /\d{4}-\d{3}/],
7923    ['YYYY-MM', /\d{4}-\d\d/, false],
7924    ['YYYYYYMMDD', /[+-]\d{10}/],
7925    ['YYYYMMDD', /\d{8}/],
7926    // YYYYMM is NOT allowed by the standard
7927    ['GGGG[W]WWE', /\d{4}W\d{3}/],
7928    ['GGGG[W]WW', /\d{4}W\d{2}/, false],
7929    ['YYYYDDD', /\d{7}/]
7930];
7931
7932// iso time formats and regexes
7933var isoTimes = [
7934    ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
7935    ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
7936    ['HH:mm:ss', /\d\d:\d\d:\d\d/],
7937    ['HH:mm', /\d\d:\d\d/],
7938    ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
7939    ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
7940    ['HHmmss', /\d\d\d\d\d\d/],
7941    ['HHmm', /\d\d\d\d/],
7942    ['HH', /\d\d/]
7943];
7944
7945var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
7946
7947// date from iso format
7948function configFromISO(config) {
7949    var i, l,
7950        string = config._i,
7951        match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
7952        allowTime, dateFormat, timeFormat, tzFormat;
7953
7954    if (match) {
7955        getParsingFlags(config).iso = true;
7956
7957        for (i = 0, l = isoDates.length; i < l; i++) {
7958            if (isoDates[i][1].exec(match[1])) {
7959                dateFormat = isoDates[i][0];
7960                allowTime = isoDates[i][2] !== false;
7961                break;
7962            }
7963        }
7964        if (dateFormat == null) {
7965            config._isValid = false;
7966            return;
7967        }
7968        if (match[3]) {
7969            for (i = 0, l = isoTimes.length; i < l; i++) {
7970                if (isoTimes[i][1].exec(match[3])) {
7971                    // match[2] should be 'T' or space
7972                    timeFormat = (match[2] || ' ') + isoTimes[i][0];
7973                    break;
7974                }
7975            }
7976            if (timeFormat == null) {
7977                config._isValid = false;
7978                return;
7979            }
7980        }
7981        if (!allowTime && timeFormat != null) {
7982            config._isValid = false;
7983            return;
7984        }
7985        if (match[4]) {
7986            if (tzRegex.exec(match[4])) {
7987                tzFormat = 'Z';
7988            } else {
7989                config._isValid = false;
7990                return;
7991            }
7992        }
7993        config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
7994        configFromStringAndFormat(config);
7995    } else {
7996        config._isValid = false;
7997    }
7998}
7999
8000// RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
8001var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;
8002
8003function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
8004    var result = [
8005        untruncateYear(yearStr),
8006        defaultLocaleMonthsShort.indexOf(monthStr),
8007        parseInt(dayStr, 10),
8008        parseInt(hourStr, 10),
8009        parseInt(minuteStr, 10)
8010    ];
8011
8012    if (secondStr) {
8013        result.push(parseInt(secondStr, 10));
8014    }
8015
8016    return result;
8017}
8018
8019function untruncateYear(yearStr) {
8020    var year = parseInt(yearStr, 10);
8021    if (year <= 49) {
8022        return 2000 + year;
8023    } else if (year <= 999) {
8024        return 1900 + year;
8025    }
8026    return year;
8027}
8028
8029function preprocessRFC2822(s) {
8030    // Remove comments and folding whitespace and replace multiple-spaces with a single space
8031    return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').trim(
vendor: 6,917 bytes, lines 8031-8260
8031);
8032}
8033
8034function checkWeekday(weekdayStr, parsedInput, config) {
8035    if (weekdayStr) {
8036        // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check.
8037        var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
8038            weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay();
8039        if (weekdayProvided !== weekdayActual) {
8040            getParsingFlags(config).weekdayMismatch = true;
8041            config._isValid = false;
8042            return false;
8043        }
8044    }
8045    return true;
8046}
8047
8048var obsOffsets = {
8049    UT: 0,
8050    GMT: 0,
8051    EDT: -4 * 60,
8052    EST: -5 * 60,
8053    CDT: -5 * 60,
8054    CST: -6 * 60,
8055    MDT: -6 * 60,
8056    MST: -7 * 60,
8057    PDT: -7 * 60,
8058    PST: -8 * 60
8059};
8060
8061function calculateOffset(obsOffset, militaryOffset, numOffset) {
8062    if (obsOffset) {
8063        return obsOffsets[obsOffset];
8064    } else if (militaryOffset) {
8065        // the only allowed military tz is Z
8066        return 0;
8067    } else {
8068        var hm = parseInt(numOffset, 10);
8069        var m = hm % 100, h = (hm - m) / 100;
8070        return h * 60 + m;
8071    }
8072}
8073
8074// date and time from ref 2822 format
8075function configFromRFC2822(config) {
8076    var match = rfc2822.exec(preprocessRFC2822(config._i));
8077    if (match) {
8078        var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]);
8079        if (!checkWeekday(match[1], parsedArray, config)) {
8080            return;
8081        }
8082
8083        config._a = parsedArray;
8084        config._tzm = calculateOffset(match[8], match[9], match[10]);
8085
8086        config._d = createUTCDate.apply(null, config._a);
8087        config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
8088
8089        getParsingFlags(config).rfc2822 = true;
8090    } else {
8091        config._isValid = false;
8092    }
8093}
8094
8095// date from iso format or fallback
8096function configFromString(config) {
8097    var matched = aspNetJsonRegex.exec(config._i);
8098
8099    if (matched !== null) {
8100        config._d = new Date(+matched[1]);
8101        return;
8102    }
8103
8104    configFromISO(config);
8105    if (config._isValid === false) {
8106        delete config._isValid;
8107    } else {
8108        return;
8109    }
8110
8111    configFromRFC2822(config);
8112    if (config._isValid === false) {
8113        delete config._isValid;
8114    } else {
8115        return;
8116    }
8117
8118    // Final attempt, use Input Fallback
8119    hooks.createFromInputFallback(config);
8120}
8121
8122hooks.createFromInputFallback = deprecate(
8123    'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
8124    'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
8125    'discouraged and will be removed in an upcoming major release. Please refer to ' +
8126    'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
8127    function (config) {
8128        config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
8129    }
8130);
8131
8132// constant that refers to the ISO standard
8133hooks.ISO_8601 = function () {};
8134
8135// constant that refers to the RFC 2822 form
8136hooks.RFC_2822 = function () {};
8137
8138// date from string and format string
8139function configFromStringAndFormat(config) {
8140    // TODO: Move this to another part of the creation flow to prevent circular deps
8141    if (config._f === hooks.ISO_8601) {
8142        configFromISO(config);
8143        return;
8144    }
8145    if (config._f === hooks.RFC_2822) {
8146        configFromRFC2822(config);
8147        return;
8148    }
8149    config._a = [];
8150    getParsingFlags(config).empty = true;
8151
8152    // This array is used to make a Date, either with `new Date` or `Date.UTC`
8153    var string = '' + config._i,
8154        i, parsedInput, tokens, token, skipped,
8155        stringLength = string.length,
8156        totalParsedInputLength = 0;
8157
8158    tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
8159
8160    for (i = 0; i < tokens.length; i++) {
8161        token = tokens[i];
8162        parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
8163        // console.log('token', token, 'parsedInput', parsedInput,
8164        //         'regex', getParseRegexForToken(token, config));
8165        if (parsedInput) {
8166            skipped = string.substr(0, string.indexOf(parsedInput));
8167            if (skipped.length > 0) {
8168                getParsingFlags(config).unusedInput.push(skipped);
8169            }
8170            string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
8171            totalParsedInputLength += parsedInput.length;
8172        }
8173        // don't parse if it's not a known token
8174        if (formatTokenFunctions[token]) {
8175            if (parsedInput) {
8176                getParsingFlags(config).empty = false;
8177            }
8178            else {
8179                getParsingFlags(config).unusedTokens.push(token);
8180            }
8181            addTimeToArrayFromToken(token, parsedInput, config);
8182        }
8183        else if (config._strict && !parsedInput) {
8184            getParsingFlags(config).unusedTokens.push(token);
8185        }
8186    }
8187
8188    // add remaining unparsed input length to the string
8189    getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
8190    if (string.length > 0) {
8191        getParsingFlags(config).unusedInput.push(string);
8192    }
8193
8194    // clear _12h flag if hour is <= 12
8195    if (config._a[HOUR] <= 12 &&
8196        getParsingFlags(config).bigHour === true &&
8197        config._a[HOUR] > 0) {
8198        getParsingFlags(config).bigHour = undefined;
8199    }
8200
8201    getParsingFlags(config).parsedDateParts = config._a.slice(0);
8202    getParsingFlags(config).meridiem = config._meridiem;
8203    // handle meridiem
8204    config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
8205
8206    configFromArray(config);
8207    checkOverflow(config);
8208}
8209
8210
8211function meridiemFixWrap (locale, hour, meridiem) {
8212    var isPm;
8213
8214    if (meridiem == null) {
8215        // nothing to do
8216        return hour;
8217    }
8218    if (locale.meridiemHour != null) {
8219        return locale.meridiemHour(hour, meridiem);
8220    } else if (locale.isPM != null) {
8221        // Fallback
8222        isPm = locale.isPM(meridiem);
8223        if (isPm && hour < 12) {
8224            hour += 12;
8225        }
8226        if (!isPm && hour === 12) {
8227            hour = 0;
8228        }
8229        return hour;
8230    } else {
8231        // this is not supposed to happen
8232        return hour;
8233    }
8234}
8235
8236// date from string and array of format strings
8237function configFromStringAndArray(config) {
8238    var tempConfig,
8239        bestMoment,
8240
8241        scoreToBeat,
8242        i,
8243        currentScore;
8244
8245    if (config._f.length === 0) {
8246        getParsingFlags(config).invalidFormat = true;
8247        config._d = new Date(NaN);
8248        return;
8249    }
8250
8251    for (i = 0; i < config._f.length; i++) {
8252        currentScore = 0;
8253        tempConfig = copyConfig({}, config);
8254        if (config._useUTC != null) {
8255            tempConfig._useUTC = config._useUTC;
8256        }
8257        tempConfig._f = config._f[i];
8258        configFromStringAndFormat(tempConfig);
8259
8260        if (!isValid
vendor: 24,711 bytes, lines 8260-9083
8260(tempConfig)) {
8261            continue;
8262        }
8263
8264        // if there is any input that was not parsed add a penalty for that format
8265        currentScore += getParsingFlags(tempConfig).charsLeftOver;
8266
8267        //or tokens
8268        currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
8269
8270        getParsingFlags(tempConfig).score = currentScore;
8271
8272        if (scoreToBeat == null || currentScore < scoreToBeat) {
8273            scoreToBeat = currentScore;
8274            bestMoment = tempConfig;
8275        }
8276    }
8277
8278    extend(config, bestMoment || tempConfig);
8279}
8280
8281function configFromObject(config) {
8282    if (config._d) {
8283        return;
8284    }
8285
8286    var i = normalizeObjectUnits(config._i);
8287    config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
8288        return obj && parseInt(obj, 10);
8289    });
8290
8291    configFromArray(config);
8292}
8293
8294function createFromConfig (config) {
8295    var res = new Moment(checkOverflow(prepareConfig(config)));
8296    if (res._nextDay) {
8297        // Adding is smart enough around DST
8298        res.add(1, 'd');
8299        res._nextDay = undefined;
8300    }
8301
8302    return res;
8303}
8304
8305function prepareConfig (config) {
8306    var input = config._i,
8307        format = config._f;
8308
8309    config._locale = config._locale || getLocale(config._l);
8310
8311    if (input === null || (format === undefined && input === '')) {
8312        return createInvalid({nullInput: true});
8313    }
8314
8315    if (typeof input === 'string') {
8316        config._i = input = config._locale.preparse(input);
8317    }
8318
8319    if (isMoment(input)) {
8320        return new Moment(checkOverflow(input));
8321    } else if (isDate(input)) {
8322        config._d = input;
8323    } else if (isArray(format)) {
8324        configFromStringAndArray(config);
8325    } else if (format) {
8326        configFromStringAndFormat(config);
8327    }  else {
8328        configFromInput(config);
8329    }
8330
8331    if (!isValid(config)) {
8332        config._d = null;
8333    }
8334
8335    return config;
8336}
8337
8338function configFromInput(config) {
8339    var input = config._i;
8340    if (isUndefined(input)) {
8341        config._d = new Date(hooks.now());
8342    } else if (isDate(input)) {
8343        config._d = new Date(input.valueOf());
8344    } else if (typeof input === 'string') {
8345        configFromString(config);
8346    } else if (isArray(input)) {
8347        config._a = map(input.slice(0), function (obj) {
8348            return parseInt(obj, 10);
8349        });
8350        configFromArray(config);
8351    } else if (isObject(input)) {
8352        configFromObject(config);
8353    } else if (isNumber(input)) {
8354        // from milliseconds
8355        config._d = new Date(input);
8356    } else {
8357        hooks.createFromInputFallback(config);
8358    }
8359}
8360
8361function createLocalOrUTC (input, format, locale, strict, isUTC) {
8362    var c = {};
8363
8364    if (locale === true || locale === false) {
8365        strict = locale;
8366        locale = undefined;
8367    }
8368
8369    if ((isObject(input) && isObjectEmpty(input)) ||
8370            (isArray(input) && input.length === 0)) {
8371        input = undefined;
8372    }
8373    // object construction must be done this way.
8374    // https://github.com/moment/moment/issues/1423
8375    c._isAMomentObject = true;
8376    c._useUTC = c._isUTC = isUTC;
8377    c._l = locale;
8378    c._i = input;
8379    c._f = format;
8380    c._strict = strict;
8381
8382    return createFromConfig(c);
8383}
8384
8385function createLocal (input, format, locale, strict) {
8386    return createLocalOrUTC(input, format, locale, strict, false);
8387}
8388
8389var prototypeMin = deprecate(
8390    'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
8391    function () {
8392        var other = createLocal.apply(null, arguments);
8393        if (this.isValid() && other.isValid()) {
8394            return other < this ? this : other;
8395        } else {
8396            return createInvalid();
8397        }
8398    }
8399);
8400
8401var prototypeMax = deprecate(
8402    'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
8403    function () {
8404        var other = createLocal.apply(null, arguments);
8405        if (this.isValid() && other.isValid()) {
8406            return other > this ? this : other;
8407        } else {
8408            return createInvalid();
8409        }
8410    }
8411);
8412
8413// Pick a moment m from moments so that m[fn](other) is true for all
8414// other. This relies on the function fn to be transitive.
8415//
8416// moments should either be an array of moment objects or an array, whose
8417// first element is an array of moment objects.
8418function pickBy(fn, moments) {
8419    var res, i;
8420    if (moments.length === 1 && isArray(moments[0])) {
8421        moments = moments[0];
8422    }
8423    if (!moments.length) {
8424        return createLocal();
8425    }
8426    res = moments[0];
8427    for (i = 1; i < moments.length; ++i) {
8428        if (!moments[i].isValid() || moments[i][fn](res)) {
8429            res = moments[i];
8430        }
8431    }
8432    return res;
8433}
8434
8435// TODO: Use [].sort instead?
8436function min () {
8437    var args = [].slice.call(arguments, 0);
8438
8439    return pickBy('isBefore', args);
8440}
8441
8442function max () {
8443    var args = [].slice.call(arguments, 0);
8444
8445    return pickBy('isAfter', args);
8446}
8447
8448var now = function () {
8449    return Date.now ? Date.now() : +(new Date());
8450};
8451
8452var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
8453
8454function isDurationValid(m) {
8455    for (var key in m) {
8456        if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
8457            return false;
8458        }
8459    }
8460
8461    var unitHasDecimal = false;
8462    for (var i = 0; i < ordering.length; ++i) {
8463        if (m[ordering[i]]) {
8464            if (unitHasDecimal) {
8465                return false; // only allow non-integers for smallest unit
8466            }
8467            if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
8468                unitHasDecimal = true;
8469            }
8470        }
8471    }
8472
8473    return true;
8474}
8475
8476function isValid$1() {
8477    return this._isValid;
8478}
8479
8480function createInvalid$1() {
8481    return createDuration(NaN);
8482}
8483
8484function Duration (duration) {
8485    var normalizedInput = normalizeObjectUnits(duration),
8486        years = normalizedInput.year || 0,
8487        quarters = normalizedInput.quarter || 0,
8488        months = normalizedInput.month || 0,
8489        weeks = normalizedInput.week || 0,
8490        days = normalizedInput.day || 0,
8491        hours = normalizedInput.hour || 0,
8492        minutes = normalizedInput.minute || 0,
8493        seconds = normalizedInput.second || 0,
8494        milliseconds = normalizedInput.millisecond || 0;
8495
8496    this._isValid = isDurationValid(normalizedInput);
8497
8498    // representation for dateAddRemove
8499    this._milliseconds = +milliseconds +
8500        seconds * 1e3 + // 1000
8501        minutes * 6e4 + // 1000 * 60
8502        hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
8503    // Because of dateAddRemove treats 24 hours as different from a
8504    // day when working around DST, we need to store them separately
8505    this._days = +days +
8506        weeks * 7;
8507    // It is impossible to translate months into days without knowing
8508    // which months you are are talking about, so we have to store
8509    // it separately.
8510    this._months = +months +
8511        quarters * 3 +
8512        years * 12;
8513
8514    this._data = {};
8515
8516    this._locale = getLocale();
8517
8518    this._bubble();
8519}
8520
8521function isDuration (obj) {
8522    return obj instanceof Duration;
8523}
8524
8525function absRound (number) {
8526    if (number < 0) {
8527        return Math.round(-1 * number) * -1;
8528    } else {
8529        return Math.round(number);
8530    }
8531}
8532
8533// FORMATTING
8534
8535function offset (token, separator) {
8536    addFormatToken(token, 0, 0, function () {
8537        var offset = this.utcOffset();
8538        var sign = '+';
8539        if (offset < 0) {
8540            offset = -offset;
8541            sign = '-';
8542        }
8543        return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
8544    });
8545}
8546
8547offset('Z', ':');
8548offset('ZZ', '');
8549
8550// PARSING
8551
8552addRegexToken('Z',  matchShortOffset);
8553addRegexToken('ZZ', matchShortOffset);
8554addParseToken(['Z', 'ZZ'], function (input, array, config) {
8555    config._useUTC = true;
8556    config._tzm = offsetFromString(matchShortOffset, input);
8557});
8558
8559// HELPERS
8560
8561// timezone chunker
8562// '+10:00' > ['10',  '00']
8563// '-1530'  > ['-15', '30']
8564var chunkOffset = /([\+\-]|\d\d)/gi;
8565
8566function offsetFromString(matcher, string) {
8567    var matches = (string || '').match(matcher);
8568
8569    if (matches === null) {
8570        return null;
8571    }
8572
8573    var chunk   = matches[matches.length - 1] || [];
8574    var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
8575    var minutes = +(parts[1] * 60) + toInt(parts[2]);
8576
8577    return minutes === 0 ?
8578      0 :
8579      parts[0] === '+' ? minutes : -minutes;
8580}
8581
8582// Return a moment from input, that is local/utc/zone equivalent to model.
8583function cloneWithOffset(input, model) {
8584    var res, diff;
8585    if (model._isUTC) {
8586        res = model.clone();
8587        diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();
8588        // Use low-level api, because this fn is low-level api.
8589        res._d.setTime(res._d.valueOf() + diff);
8590        hooks.updateOffset(res, false);
8591        return res;
8592    } else {
8593        return createLocal(input).local();
8594    }
8595}
8596
8597function getDateOffset (m) {
8598    // On Firefox.24 Date#getTimezoneOffset returns a floating point.
8599    // https://github.com/moment/moment/pull/1871
8600    return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
8601}
8602
8603// HOOKS
8604
8605// This function will be called whenever a moment is mutated.
8606// It is intended to keep the offset in sync with the timezone.
8607hooks.updateOffset = function () {};
8608
8609// MOMENTS
8610
8611// keepLocalTime = true means only change the timezone, without
8612// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
8613// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
8614// +0200, so we adjust the time as needed, to be valid.
8615//
8616// Keeping the time actually adds/subtracts (one hour)
8617// from the actual represented time. That is why we call updateOffset
8618// a second time. In case it wants us to change the offset again
8619// _changeInProgress == true case, then we have to adjust, because
8620// there is no such time in the given timezone.
8621function getSetOffset (input, keepLocalTime, keepMinutes) {
8622    var offset = this._offset || 0,
8623        localAdjust;
8624    if (!this.isValid()) {
8625        return input != null ? this : NaN;
8626    }
8627    if (input != null) {
8628        if (typeof input === 'string') {
8629            input = offsetFromString(matchShortOffset, input);
8630            if (input === null) {
8631                return this;
8632            }
8633        } else if (Math.abs(input) < 16 && !keepMinutes) {
8634            input = input * 60;
8635        }
8636        if (!this._isUTC && keepLocalTime) {
8637            localAdjust = getDateOffset(this);
8638        }
8639        this._offset = input;
8640        this._isUTC = true;
8641        if (localAdjust != null) {
8642            this.add(localAdjust, 'm');
8643        }
8644        if (offset !== input) {
8645            if (!keepLocalTime || this._changeInProgress) {
8646                addSubtract(this, createDuration(input - offset, 'm'), 1, false);
8647            } else if (!this._changeInProgress) {
8648                this._changeInProgress = true;
8649                hooks.updateOffset(this, true);
8650                this._changeInProgress = null;
8651            }
8652        }
8653        return this;
8654    } else {
8655        return this._isUTC ? offset : getDateOffset(this);
8656    }
8657}
8658
8659function getSetZone (input, keepLocalTime) {
8660    if (input != null) {
8661        if (typeof input !== 'string') {
8662            input = -input;
8663        }
8664
8665        this.utcOffset(input, keepLocalTime);
8666
8667        return this;
8668    } else {
8669        return -this.utcOffset();
8670    }
8671}
8672
8673function setOffsetToUTC (keepLocalTime) {
8674    return this.utcOffset(0, keepLocalTime);
8675}
8676
8677function setOffsetToLocal (keepLocalTime) {
8678    if (this._isUTC) {
8679        this.utcOffset(0, keepLocalTime);
8680        this._isUTC = false;
8681
8682        if (keepLocalTime) {
8683            this.subtract(getDateOffset(this), 'm');
8684        }
8685    }
8686    return this;
8687}
8688
8689function setOffsetToParsedOffset () {
8690    if (this._tzm != null) {
8691        this.utcOffset(this._tzm, false, true);
8692    } else if (typeof this._i === 'string') {
8693        var tZone = offsetFromString(matchOffset, this._i);
8694        if (tZone != null) {
8695            this.utcOffset(tZone);
8696        }
8697        else {
8698            this.utcOffset(0, true);
8699        }
8700    }
8701    return this;
8702}
8703
8704function hasAlignedHourOffset (input) {
8705    if (!this.isValid()) {
8706        return false;
8707    }
8708    input = input ? createLocal(input).utcOffset() : 0;
8709
8710    return (this.utcOffset() - input) % 60 === 0;
8711}
8712
8713function isDaylightSavingTime () {
8714    return (
8715        this.utcOffset() > this.clone().month(0).utcOffset() ||
8716        this.utcOffset() > this.clone().month(5).utcOffset()
8717    );
8718}
8719
8720function isDaylightSavingTimeShifted () {
8721    if (!isUndefined(this._isDSTShifted)) {
8722        return this._isDSTShifted;
8723    }
8724
8725    var c = {};
8726
8727    copyConfig(c, this);
8728    c = prepareConfig(c);
8729
8730    if (c._a) {
8731        var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
8732        this._isDSTShifted = this.isValid() &&
8733            compareArrays(c._a, other.toArray()) > 0;
8734    } else {
8735        this._isDSTShifted = false;
8736    }
8737
8738    return this._isDSTShifted;
8739}
8740
8741function isLocal () {
8742    return this.isValid() ? !this._isUTC : false;
8743}
8744
8745function isUtcOffset () {
8746    return this.isValid() ? this._isUTC : false;
8747}
8748
8749function isUtc () {
8750    return this.isValid() ? this._isUTC && this._offset === 0 : false;
8751}
8752
8753// ASP.NET json date format regex
8754var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;
8755
8756// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
8757// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
8758// and further modified to allow for strings containing both week and day
8759var isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
8760
8761function createDuration (input, key) {
8762    var duration = input,
8763        // matching against regexp is expensive, do it on demand
8764        match = null,
8765        sign,
8766        ret,
8767        diffRes;
8768
8769    if (isDuration(input)) {
8770        duration = {
8771            ms : input._milliseconds,
8772            d  : input._days,
8773            M  : input._months
8774        };
8775    } else if (isNumber(input)) {
8776        duration = {};
8777        if (key) {
8778            duration[key] = input;
8779        } else {
8780            duration.milliseconds = input;
8781        }
8782    } else if (!!(match = aspNetRegex.exec(input))) {
8783        sign = (match[1] === '-') ? -1 : 1;
8784        duration = {
8785            y  : 0,
8786            d  : toInt(match[DATE])                         * sign,
8787            h  : toInt(match[HOUR])                         * sign,
8788            m  : toInt(match[MINUTE])                       * sign,
8789            s  : toInt(match[SECOND])                       * sign,
8790            ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
8791        };
8792    } else if (!!(match = isoRegex.exec(input))) {
8793        sign = (match[1] === '-') ? -1 : (match[1] === '+') ? 1 : 1;
8794        duration = {
8795            y : parseIso(match[2], sign),
8796            M : parseIso(match[3], sign),
8797            w : parseIso(match[4], sign),
8798            d : parseIso(match[5], sign),
8799            h : parseIso(match[6], sign),
8800            m : parseIso(match[7], sign),
8801            s : parseIso(match[8], sign)
8802        };
8803    } else if (duration == null) {// checks for null or undefined
8804        duration = {};
8805    } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
8806        diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
8807
8808        duration = {};
8809        duration.ms = diffRes.milliseconds;
8810        duration.M = diffRes.months;
8811    }
8812
8813    ret = new Duration(duration);
8814
8815    if (isDuration(input) && hasOwnProp(input, '_locale')) {
8816        ret._locale = input._locale;
8817    }
8818
8819    return ret;
8820}
8821
8822createDuration.fn = Duration.prototype;
8823createDuration.invalid = createInvalid$1;
8824
8825function parseIso (inp, sign) {
8826    // We'd normally use ~~inp for this, but unfortunately it also
8827    // converts floats to ints.
8828    // inp may be undefined, so careful calling replace on it.
8829    var res = inp && parseFloat(inp.replace(',', '.'));
8830    // apply sign while we're at it
8831    return (isNaN(res) ? 0 : res) * sign;
8832}
8833
8834function positiveMomentsDifference(base, other) {
8835    var res = {milliseconds: 0, months: 0};
8836
8837    res.months = other.month() - base.month() +
8838        (other.year() - base.year()) * 12;
8839    if (base.clone().add(res.months, 'M').isAfter(other)) {
8840        --res.months;
8841    }
8842
8843    res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
8844
8845    return res;
8846}
8847
8848function momentsDifference(base, other) {
8849    var res;
8850    if (!(base.isValid() && other.isValid())) {
8851        return {milliseconds: 0, months: 0};
8852    }
8853
8854    other = cloneWithOffset(other, base);
8855    if (base.isBefore(other)) {
8856        res = positiveMomentsDifference(base, other);
8857    } else {
8858        res = positiveMomentsDifference(other, base);
8859        res.milliseconds = -res.milliseconds;
8860        res.months = -res.months;
8861    }
8862
8863    return res;
8864}
8865
8866// TODO: remove 'name' arg after deprecation is removed
8867function createAdder(direction, name) {
8868    return function (val, period) {
8869        var dur, tmp;
8870        //invert the arguments, but complain about it
8871        if (period !== null && !isNaN(+period)) {
8872            deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' +
8873            'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
8874            tmp = val; val = period; period = tmp;
8875        }
8876
8877        val = typeof val === 'string' ? +val : val;
8878        dur = createDuration(val, period);
8879        addSubtract(this, dur, direction);
8880        return this;
8881    };
8882}
8883
8884function addSubtract (mom, duration, isAdding, updateOffset) {
8885    var milliseconds = duration._milliseconds,
8886        days = absRound(duration._days),
8887        months = absRound(duration._months);
8888
8889    if (!mom.isValid()) {
8890        // No op
8891        return;
8892    }
8893
8894    updateOffset = updateOffset == null ? true : updateOffset;
8895
8896    if (months) {
8897        setMonth(mom, get(mom, 'Month') + months * isAdding);
8898    }
8899    if (days) {
8900        set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
8901    }
8902    if (milliseconds) {
8903        mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
8904    }
8905    if (updateOffset) {
8906        hooks.updateOffset(mom, days || months);
8907    }
8908}
8909
8910var add      = createAdder(1, 'add');
8911var subtract = createAdder(-1, 'subtract');
8912
8913function getCalendarFormat(myMoment, now) {
8914    var diff = myMoment.diff(now, 'days', true);
8915    return diff < -6 ? 'sameElse' :
8916            diff < -1 ? 'lastWeek' :
8917            diff < 0 ? 'lastDay' :
8918            diff < 1 ? 'sameDay' :
8919            diff < 2 ? 'nextDay' :
8920            diff < 7 ? 'nextWeek' : 'sameElse';
8921}
8922
8923function calendar$1 (time, formats) {
8924    // We want to compare the start of today, vs this.
8925    // Getting start-of-today depends on whether we're local/utc/offset or not.
8926    var now = time || createLocal(),
8927        sod = cloneWithOffset(now, this).startOf('day'),
8928        format = hooks.calendarFormat(this, sod) || 'sameElse';
8929
8930    var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
8931
8932    return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
8933}
8934
8935function clone () {
8936    return new Moment(this);
8937}
8938
8939function isAfter (input, units) {
8940    var localInput = isMoment(input) ? input : createLocal(input);
8941    if (!(this.isValid() && localInput.isValid())) {
8942        return false;
8943    }
8944    units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
8945    if (units === 'millisecond') {
8946        return this.valueOf() > localInput.valueOf();
8947    } else {
8948        return localInput.valueOf() < this.clone().startOf(units).valueOf();
8949    }
8950}
8951
8952function isBefore (input, units) {
8953    var localInput = isMoment(input) ? input : createLocal(input);
8954    if (!(this.isValid() && localInput.isValid())) {
8955        return false;
8956    }
8957    units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
8958    if (units === 'millisecond') {
8959        return this.valueOf() < localInput.valueOf();
8960    } else {
8961        return this.clone().endOf(units).valueOf() < localInput.valueOf();
8962    }
8963}
8964
8965function isBetween (from, to, units, inclusivity) {
8966    inclusivity = inclusivity || '()';
8967    return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
8968        (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
8969}
8970
8971function isSame (input, units) {
8972    var localInput = isMoment(input) ? input : createLocal(input),
8973        inputMs;
8974    if (!(this.isValid() && localInput.isValid())) {
8975        return false;
8976    }
8977    units = normalizeUnits(units || 'millisecond');
8978    if (units === 'millisecond') {
8979        return this.valueOf() === localInput.valueOf();
8980    } else {
8981        inputMs = localInput.valueOf();
8982        return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
8983    }
8984}
8985
8986function isSameOrAfter (input, units) {
8987    return this.isSame(input, units) || this.isAfter(input,units);
8988}
8989
8990function isSameOrBefore (input, units) {
8991    return this.isSame(input, units) || this.isBefore(input,units);
8992}
8993
8994function diff (input, units, asFloat) {
8995    var that,
8996        zoneDelta,
8997        delta, output;
8998
8999    if (!this.isValid()) {
9000        return NaN;
9001    }
9002
9003    that = cloneWithOffset(input, this);
9004
9005    if (!that.isValid()) {
9006        return NaN;
9007    }
9008
9009    zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
9010
9011    units = normalizeUnits(units);
9012
9013    switch (units) {
9014        case 'year': output = monthDiff(this, that) / 12; break;
9015        case 'month': output = monthDiff(this, that); break;
9016        case 'quarter': output = monthDiff(this, that) / 3; break;
9017        case 'second': output = (this - that) / 1e3; break; // 1000
9018        case 'minute': output = (this - that) / 6e4; break; // 1000 * 60
9019        case 'hour': output = (this - that) / 36e5; break; // 1000 * 60 * 60
9020        case 'day': output = (this - that - zoneDelta) / 864e5; break; // 1000 * 60 * 60 * 24, negate dst
9021        case 'week': output = (this - that - zoneDelta) / 6048e5; break; // 1000 * 60 * 60 * 24 * 7, negate dst
9022        default: output = this - that;
9023    }
9024
9025    return asFloat ? output : absFloor(output);
9026}
9027
9028function monthDiff (a, b) {
9029    // difference in months
9030    var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
9031        // b is in (anchor - 1 month, anchor + 1 month)
9032        anchor = a.clone().add(wholeMonthDiff, 'months'),
9033        anchor2, adjust;
9034
9035    if (b - anchor < 0) {
9036        anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
9037        // linear across the month
9038        adjust = (b - anchor) / (anchor - anchor2);
9039    } else {
9040        anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
9041        // linear across the month
9042        adjust = (b - anchor) / (anchor2 - anchor);
9043    }
9044
9045    //check for negative zero, return zero if negative zero
9046    return -(wholeMonthDiff + adjust) || 0;
9047}
9048
9049hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
9050hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
9051
9052function toString () {
9053    return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
9054}
9055
9056function toISOString(keepOffset) {
9057    if (!this.isValid()) {
9058        return null;
9059    }
9060    var utc = keepOffset !== true;
9061    var m = utc ? this.clone().utc() : this;
9062    if (m.year() < 0 || m.year() > 9999) {
9063        return formatMoment(m, utc ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ');
9064    }
9065    if (isFunction(Date.prototype.toISOString)) {
9066        // native implementation is ~50x faster, use it when we can
9067        if (utc) {
9068            return this.toDate().toISOString();
9069        } else {
9070            return new Date(this._d.valueOf()).toISOString().replace('Z', formatMoment(m, 'Z'));
9071        }
9072    }
9073    return formatMoment(m, utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ');
9074}
9075
9076/**
9077 * Return a human readable representation of a moment that can
9078 * also be evaluated to get a new moment which is the same
9079 *
9080 * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
9081 */
9082function inspect () {
9083    if (!this.isValid()) {
9084        return 'moment.invalid(/* ' + this._i + ' */)';
9085    }
9086    var func = 'moment';
9087    var zone = '';
9088    if (!this.isLocal()) {
9089        func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
9090        zone = 'Z';
9091    }
9092    var prefix = '[' + func + '("]';
9093    var year = (0 <= this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY';
9094    var datetime = '-MM-DD[T]HH:mm:ss.SSS';
9095    var suffix = zone + '[")]';
9096
9097    return this.format(prefix + year + datetime + suffix);
9098}
9099
9100function format (inputString) {
9101    if (!inputString) {
9102        inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
9103    }
9104    var output = formatMoment(this, inputString);
9105    return this.localeData().postformat(output);
9106}
9107
9108function from (time, withoutSuffix) {
9109    if (this.isValid() &&
9110            ((isMoment(time) && time.isValid()) ||
9111             createLocal(time).isValid())) {
9112        return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
9113    } else {
9114        return this.localeData().invalidDate();
9115    }
9116}
9117
9118function fromNow (withoutSuffix) {
9119    return this.from(createLocal(), withoutSuffix);
9120}
9121
9122function to (time, withoutSuffix) {
9123    if (this.isValid() &&
9124            ((isMoment(time) && time.isValid()) ||
9125             createLocal(time).isValid())) {
9126        return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
9127    } else {
9128        return this.localeData().invalidDate();
9129    }
9130}
9131
9132function toNow (withoutSuffix) {
9133    return this.to(createLocal(), withoutSuffix);
9134}
9135
9136// If passed a locale key, it will set the locale for this
9137// instance.  Otherwise, it will return the locale configuration
9138// variables for this instance.
9139function locale (key) {
9140    var newLocaleData;
9141
9142    if (key === undefined) {
9143        return this._locale._abbr;
9144    } else {
9145        newLocaleData = getLocale(key);
9146        if (newLocaleData != null) {
9147            this._locale = newLocaleData;
9148        }
9149        return this;
9150    }
9151}
9152
9153var lang = deprecate(
9154    'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
9155    function (key) {
9156        if (key === undefined) {
9157            return this.localeData();
9158        } else {
9159            return this.locale(key);
9160        }
9161    }
9162);
9163
9164function localeData () {
9165    return this._locale;
9166}
9167
9168function startOf (units) {
9169    units = normalizeUnits(units);
9170    // the following switch intentionally omits break keywords
9171    // to utilize falling through the cases.
9172    switch (units) {
9173        case 'year':
9174            this.month(0);
9175            /* falls through */
9176        case 'quarter':
9177        case 'month':
9178            this.date(1);
9179            /* falls through */
9180        case 'week':
9181        case 'isoWeek':
9182        case 'day':
9183        case 'date':
9184            this.hours(0);
9185            /* falls through */
9186        case 'hour':
9187            this.minutes(0);
9188            /* falls through */
9189        case 'minute':
9190            this.seconds(0);
9191            /* falls through */
9192        case 'second':
9193            this.milliseconds(0);
9194    }
9195
9196    // weeks are a special case
9197    if (units === 'week') {
9198        this.weekday(0);
9199    }
9200    if (units === 'isoWeek') {
9201        this.isoWeekday(1);
9202    }
9203
9204    // quarters are also special
9205    if (units === 'quarter') {
9206        this.month(Math.floor(this.month() / 3) * 3);
9207    }
9208
9209    return this;
9210}
9211
9212function endOf (units) {
9213    units = normalizeUnits(units);
9214    if (units === undefined || units === 'millisecond') {
9215        return this;
9216    }
9217
9218    // 'date' is an alias for 'day', so it should be considered as such.
9219    if (units === 'date') {
9220        units = 'day';
9221    }
9222
9223    return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
9224}
9225
9226function valueOf () {
9227    return this._d.valueOf() - ((this._offset || 0) * 60000);
9228}
9229
9230function unix () {
9231    return Math.floor(this.valueOf() / 1000);
9232}
9233
9234function toDate () {
9235    return new Date(this.valueOf());
9236}
9237
9238function toArray () {
9239    var m = this;
9240    return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
9241}
9242
9243function toObject () {
9244    var m = this;
9245    return {
9246        years: m.year(),
9247        months: m.month(),
9248        date: m.date(),
9249        hours: m.hours(),
9250        minutes: m.minutes(),
9251        seconds: m.seconds(),
9252        milliseconds: m.milliseconds()
9253    };
9254}
9255
9256function toJSON () {
9257    // new Date(NaN).toJSON() === null
9258    return this.isValid() ? this.toISOString() : null;
9259}
9260
9261function isValid$2 () {
9262    return isValid(this);
9263}
9264
9265function parsingFlags () {
9266    return extend({}, getParsingFlags(this));
9267}
9268
vendor: 26,177 bytes, lines 9269-10230
9269function invalidAt () {
9270    return getParsingFlags(this).overflow;
9271}
9272
9273function creationData() {
9274    return {
9275        input: this._i,
9276        format: this._f,
9277        locale: this._locale,
9278        isUTC: this._isUTC,
9279        strict: this._strict
9280    };
9281}
9282
9283// FORMATTING
9284
9285addFormatToken(0, ['gg', 2], 0, function () {
9286    return this.weekYear() % 100;
9287});
9288
9289addFormatToken(0, ['GG', 2], 0, function () {
9290    return this.isoWeekYear() % 100;
9291});
9292
9293function addWeekYearFormatToken (token, getter) {
9294    addFormatToken(0, [token, token.length], 0, getter);
9295}
9296
9297addWeekYearFormatToken('gggg',     'weekYear');
9298addWeekYearFormatToken('ggggg',    'weekYear');
9299addWeekYearFormatToken('GGGG',  'isoWeekYear');
9300addWeekYearFormatToken('GGGGG', 'isoWeekYear');
9301
9302// ALIASES
9303
9304addUnitAlias('weekYear', 'gg');
9305addUnitAlias('isoWeekYear', 'GG');
9306
9307// PRIORITY
9308
9309addUnitPriority('weekYear', 1);
9310addUnitPriority('isoWeekYear', 1);
9311
9312
9313// PARSING
9314
9315addRegexToken('G',      matchSigned);
9316addRegexToken('g',      matchSigned);
9317addRegexToken('GG',     match1to2, match2);
9318addRegexToken('gg',     match1to2, match2);
9319addRegexToken('GGGG',   match1to4, match4);
9320addRegexToken('gggg',   match1to4, match4);
9321addRegexToken('GGGGG',  match1to6, match6);
9322addRegexToken('ggggg',  match1to6, match6);
9323
9324addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
9325    week[token.substr(0, 2)] = toInt(input);
9326});
9327
9328addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
9329    week[token] = hooks.parseTwoDigitYear(input);
9330});
9331
9332// MOMENTS
9333
9334function getSetWeekYear (input) {
9335    return getSetWeekYearHelper.call(this,
9336            input,
9337            this.week(),
9338            this.weekday(),
9339            this.localeData()._week.dow,
9340            this.localeData()._week.doy);
9341}
9342
9343function getSetISOWeekYear (input) {
9344    return getSetWeekYearHelper.call(this,
9345            input, this.isoWeek(), this.isoWeekday(), 1, 4);
9346}
9347
9348function getISOWeeksInYear () {
9349    return weeksInYear(this.year(), 1, 4);
9350}
9351
9352function getWeeksInYear () {
9353    var weekInfo = this.localeData()._week;
9354    return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
9355}
9356
9357function getSetWeekYearHelper(input, week, weekday, dow, doy) {
9358    var weeksTarget;
9359    if (input == null) {
9360        return weekOfYear(this, dow, doy).year;
9361    } else {
9362        weeksTarget = weeksInYear(input, dow, doy);
9363        if (week > weeksTarget) {
9364            week = weeksTarget;
9365        }
9366        return setWeekAll.call(this, input, week, weekday, dow, doy);
9367    }
9368}
9369
9370function setWeekAll(weekYear, week, weekday, dow, doy) {
9371    var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
9372        date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
9373
9374    this.year(date.getUTCFullYear());
9375    this.month(date.getUTCMonth());
9376    this.date(date.getUTCDate());
9377    return this;
9378}
9379
9380// FORMATTING
9381
9382addFormatToken('Q', 0, 'Qo', 'quarter');
9383
9384// ALIASES
9385
9386addUnitAlias('quarter', 'Q');
9387
9388// PRIORITY
9389
9390addUnitPriority('quarter', 7);
9391
9392// PARSING
9393
9394addRegexToken('Q', match1);
9395addParseToken('Q', function (input, array) {
9396    array[MONTH] = (toInt(input) - 1) * 3;
9397});
9398
9399// MOMENTS
9400
9401function getSetQuarter (input) {
9402    return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
9403}
9404
9405// FORMATTING
9406
9407addFormatToken('D', ['DD', 2], 'Do', 'date');
9408
9409// ALIASES
9410
9411addUnitAlias('date', 'D');
9412
9413// PRIOROITY
9414addUnitPriority('date', 9);
9415
9416// PARSING
9417
9418addRegexToken('D',  match1to2);
9419addRegexToken('DD', match1to2, match2);
9420addRegexToken('Do', function (isStrict, locale) {
9421    // TODO: Remove "ordinalParse" fallback in next major release.
9422    return isStrict ?
9423      (locale._dayOfMonthOrdinalParse || locale._ordinalParse) :
9424      locale._dayOfMonthOrdinalParseLenient;
9425});
9426
9427addParseToken(['D', 'DD'], DATE);
9428addParseToken('Do', function (input, array) {
9429    array[DATE] = toInt(input.match(match1to2)[0]);
9430});
9431
9432// MOMENTS
9433
9434var getSetDayOfMonth = makeGetSet('Date', true);
9435
9436// FORMATTING
9437
9438addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
9439
9440// ALIASES
9441
9442addUnitAlias('dayOfYear', 'DDD');
9443
9444// PRIORITY
9445addUnitPriority('dayOfYear', 4);
9446
9447// PARSING
9448
9449addRegexToken('DDD',  match1to3);
9450addRegexToken('DDDD', match3);
9451addParseToken(['DDD', 'DDDD'], function (input, array, config) {
9452    config._dayOfYear = toInt(input);
9453});
9454
9455// HELPERS
9456
9457// MOMENTS
9458
9459function getSetDayOfYear (input) {
9460    var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
9461    return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
9462}
9463
9464// FORMATTING
9465
9466addFormatToken('m', ['mm', 2], 0, 'minute');
9467
9468// ALIASES
9469
9470addUnitAlias('minute', 'm');
9471
9472// PRIORITY
9473
9474addUnitPriority('minute', 14);
9475
9476// PARSING
9477
9478addRegexToken('m',  match1to2);
9479addRegexToken('mm', match1to2, match2);
9480addParseToken(['m', 'mm'], MINUTE);
9481
9482// MOMENTS
9483
9484var getSetMinute = makeGetSet('Minutes', false);
9485
9486// FORMATTING
9487
9488addFormatToken('s', ['ss', 2], 0, 'second');
9489
9490// ALIASES
9491
9492addUnitAlias('second', 's');
9493
9494// PRIORITY
9495
9496addUnitPriority('second', 15);
9497
9498// PARSING
9499
9500addRegexToken('s',  match1to2);
9501addRegexToken('ss', match1to2, match2);
9502addParseToken(['s', 'ss'], SECOND);
9503
9504// MOMENTS
9505
9506var getSetSecond = makeGetSet('Seconds', false);
9507
9508// FORMATTING
9509
9510addFormatToken('S', 0, 0, function () {
9511    return ~~(this.millisecond() / 100);
9512});
9513
9514addFormatToken(0, ['SS', 2], 0, function () {
9515    return ~~(this.millisecond() / 10);
9516});
9517
9518addFormatToken(0, ['SSS', 3], 0, 'millisecond');
9519addFormatToken(0, ['SSSS', 4], 0, function () {
9520    return this.millisecond() * 10;
9521});
9522addFormatToken(0, ['SSSSS', 5], 0, function () {
9523    return this.millisecond() * 100;
9524});
9525addFormatToken(0, ['SSSSSS', 6], 0, function () {
9526    return this.millisecond() * 1000;
9527});
9528addFormatToken(0, ['SSSSSSS', 7], 0, function () {
9529    return this.millisecond() * 10000;
9530});
9531addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
9532    return this.millisecond() * 100000;
9533});
9534addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
9535    return this.millisecond() * 1000000;
9536});
9537
9538
9539// ALIASES
9540
9541addUnitAlias('millisecond', 'ms');
9542
9543// PRIORITY
9544
9545addUnitPriority('millisecond', 16);
9546
9547// PARSING
9548
9549addRegexToken('S',    match1to3, match1);
9550addRegexToken('SS',   match1to3, match2);
9551addRegexToken('SSS',  match1to3, match3);
9552
9553var token;
9554for (token = 'SSSS'; token.length <= 9; token += 'S') {
9555    addRegexToken(token, matchUnsigned);
9556}
9557
9558function parseMs(input, array) {
9559    array[MILLISECOND] = toInt(('0.' + input) * 1000);
9560}
9561
9562for (token = 'S'; token.length <= 9; token += 'S') {
9563    addParseToken(token, parseMs);
9564}
9565// MOMENTS
9566
9567var getSetMillisecond = makeGetSet('Milliseconds', false);
9568
9569// FORMATTING
9570
9571addFormatToken('z',  0, 0, 'zoneAbbr');
9572addFormatToken('zz', 0, 0, 'zoneName');
9573
9574// MOMENTS
9575
9576function getZoneAbbr () {
9577    return this._isUTC ? 'UTC' : '';
9578}
9579
9580function getZoneName () {
9581    return this._isUTC ? 'Coordinated Universal Time' : '';
9582}
9583
9584var proto = Moment.prototype;
9585
9586proto.add               = add;
9587proto.calendar          = calendar$1;
9588proto.clone             = clone;
9589proto.diff              = diff;
9590proto.endOf             = endOf;
9591proto.format            = format;
9592proto.from              = from;
9593proto.fromNow           = fromNow;
9594proto.to                = to;
9595proto.toNow             = toNow;
9596proto.get               = stringGet;
9597proto.invalidAt         = invalidAt;
9598proto.isAfter           = isAfter;
9599proto.isBefore          = isBefore;
9600proto.isBetween         = isBetween;
9601proto.isSame            = isSame;
9602proto.isSameOrAfter     = isSameOrAfter;
9603proto.isSameOrBefore    = isSameOrBefore;
9604proto.isValid           = isValid$2;
9605proto.lang              = lang;
9606proto.locale            = locale;
9607proto.localeData        = localeData;
9608proto.max               = prototypeMax;
9609proto.min               = prototypeMin;
9610proto.parsingFlags      = parsingFlags;
9611proto.set               = stringSet;
9612proto.startOf           = startOf;
9613proto.subtract          = subtract;
9614proto.toArray           = toArray;
9615proto.toObject          = toObject;
9616proto.toDate            = toDate;
9617proto.toISOString       = toISOString;
9618proto.inspect           = inspect;
9619proto.toJSON            = toJSON;
9620proto.toString          = toString;
9621proto.unix              = unix;
9622proto.valueOf           = valueOf;
9623proto.creationData      = creationData;
9624
9625// Year
9626proto.year       = getSetYear;
9627proto.isLeapYear = getIsLeapYear;
9628
9629// Week Year
9630proto.weekYear    = getSetWeekYear;
9631proto.isoWeekYear = getSetISOWeekYear;
9632
9633// Quarter
9634proto.quarter = proto.quarters = getSetQuarter;
9635
9636// Month
9637proto.month       = getSetMonth;
9638proto.daysInMonth = getDaysInMonth;
9639
9640// Week
9641proto.week           = proto.weeks        = getSetWeek;
9642proto.isoWeek        = proto.isoWeeks     = getSetISOWeek;
9643proto.weeksInYear    = getWeeksInYear;
9644proto.isoWeeksInYear = getISOWeeksInYear;
9645
9646// Day
9647proto.date       = getSetDayOfMonth;
9648proto.day        = proto.days             = getSetDayOfWeek;
9649proto.weekday    = getSetLocaleDayOfWeek;
9650proto.isoWeekday = getSetISODayOfWeek;
9651proto.dayOfYear  = getSetDayOfYear;
9652
9653// Hour
9654proto.hour = proto.hours = getSetHour;
9655
9656// Minute
9657proto.minute = proto.minutes = getSetMinute;
9658
9659// Second
9660proto.second = proto.seconds = getSetSecond;
9661
9662// Millisecond
9663proto.millisecond = proto.milliseconds = getSetMillisecond;
9664
9665// Offset
9666proto.utcOffset            = getSetOffset;
9667proto.utc                  = setOffsetToUTC;
9668proto.local                = setOffsetToLocal;
9669proto.parseZone            = setOffsetToParsedOffset;
9670proto.hasAlignedHourOffset = hasAlignedHourOffset;
9671proto.isDST                = isDaylightSavingTime;
9672proto.isLocal              = isLocal;
9673proto.isUtcOffset          = isUtcOffset;
9674proto.isUtc                = isUtc;
9675proto.isUTC                = isUtc;
9676
9677// Timezone
9678proto.zoneAbbr = getZoneAbbr;
9679proto.zoneName = getZoneName;
9680
9681// Deprecations
9682proto.dates  = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
9683proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
9684proto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);
9685proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
9686proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);
9687
9688function createUnix (input) {
9689    return createLocal(input * 1000);
9690}
9691
9692function createInZone () {
9693    return createLocal.apply(null, arguments).parseZone();
9694}
9695
9696function preParsePostFormat (string) {
9697    return string;
9698}
9699
9700var proto$1 = Locale.prototype;
9701
9702proto$1.calendar        = calendar;
9703proto$1.longDateFormat  = longDateFormat;
9704proto$1.invalidDate     = invalidDate;
9705proto$1.ordinal         = ordinal;
9706proto$1.preparse        = preParsePostFormat;
9707proto$1.postformat      = preParsePostFormat;
9708proto$1.relativeTime    = relativeTime;
9709proto$1.pastFuture      = pastFuture;
9710proto$1.set             = set;
9711
9712// Month
9713proto$1.months            =        localeMonths;
9714proto$1.monthsShort       =        localeMonthsShort;
9715proto$1.monthsParse       =        localeMonthsParse;
9716proto$1.monthsRegex       = monthsRegex;
9717proto$1.monthsShortRegex  = monthsShortRegex;
9718
9719// Week
9720proto$1.week = localeWeek;
9721proto$1.firstDayOfYear = localeFirstDayOfYear;
9722proto$1.firstDayOfWeek = localeFirstDayOfWeek;
9723
9724// Day of Week
9725proto$1.weekdays       =        localeWeekdays;
9726proto$1.weekdaysMin    =        localeWeekdaysMin;
9727proto$1.weekdaysShort  =        localeWeekdaysShort;
9728proto$1.weekdaysParse  =        localeWeekdaysParse;
9729
9730proto$1.weekdaysRegex       =        weekdaysRegex;
9731proto$1.weekdaysShortRegex  =        weekdaysShortRegex;
9732proto$1.weekdaysMinRegex    =        weekdaysMinRegex;
9733
9734// Hours
9735proto$1.isPM = localeIsPM;
9736proto$1.meridiem = localeMeridiem;
9737
9738function get$1 (format, index, field, setter) {
9739    var locale = getLocale();
9740    var utc = createUTC().set(setter, index);
9741    return locale[field](utc, format);
9742}
9743
9744function listMonthsImpl (format, index, field) {
9745    if (isNumber(format)) {
9746        index = format;
9747        format = undefined;
9748    }
9749
9750    format = format || '';
9751
9752    if (index != null) {
9753        return get$1(format, index, field, 'month');
9754    }
9755
9756    var i;
9757    var out = [];
9758    for (i = 0; i < 12; i++) {
9759        out[i] = get$1(format, i, field, 'month');
9760    }
9761    return out;
9762}
9763
9764// ()
9765// (5)
9766// (fmt, 5)
9767// (fmt)
9768// (true)
9769// (true, 5)
9770// (true, fmt, 5)
9771// (true, fmt)
9772function listWeekdaysImpl (localeSorted, format, index, field) {
9773    if (typeof localeSorted === 'boolean') {
9774        if (isNumber(format)) {
9775            index = format;
9776            format = undefined;
9777        }
9778
9779        format = format || '';
9780    } else {
9781        format = localeSorted;
9782        index = format;
9783        localeSorted = false;
9784
9785        if (isNumber(format)) {
9786            index = format;
9787            format = undefined;
9788        }
9789
9790        format = format || '';
9791    }
9792
9793    var locale = getLocale(),
9794        shift = localeSorted ? locale._week.dow : 0;
9795
9796    if (index != null) {
9797        return get$1(format, (index + shift) % 7, field, 'day');
9798    }
9799
9800    var i;
9801    var out = [];
9802    for (i = 0; i < 7; i++) {
9803        out[i] = get$1(format, (i + shift) % 7, field, 'day');
9804    }
9805    return out;
9806}
9807
9808function listMonths (format, index) {
9809    return listMonthsImpl(format, index, 'months');
9810}
9811
9812function listMonthsShort (format, index) {
9813    return listMonthsImpl(format, index, 'monthsShort');
9814}
9815
9816function listWeekdays (localeSorted, format, index) {
9817    return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
9818}
9819
9820function listWeekdaysShort (localeSorted, format, index) {
9821    return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
9822}
9823
9824function listWeekdaysMin (localeSorted, format, index) {
9825    return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
9826}
9827
9828getSetGlobalLocale('en', {
9829    dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
9830    ordinal : function (number) {
9831        var b = number % 10,
9832            output = (toInt(number % 100 / 10) === 1) ? 'th' :
9833            (b === 1) ? 'st' :
9834            (b === 2) ? 'nd' :
9835            (b === 3) ? 'rd' : 'th';
9836        return number + output;
9837    }
9838});
9839
9840// Side effect imports
9841hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);
9842hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);
9843
9844var mathAbs = Math.abs;
9845
9846function abs () {
9847    var data           = this._data;
9848
9849    this._milliseconds = mathAbs(this._milliseconds);
9850    this._days         = mathAbs(this._days);
9851    this._months       = mathAbs(this._months);
9852
9853    data.milliseconds  = mathAbs(data.milliseconds);
9854    data.seconds       = mathAbs(data.seconds);
9855    data.minutes       = mathAbs(data.minutes);
9856    data.hours         = mathAbs(data.hours);
9857    data.months        = mathAbs(data.months);
9858    data.years         = mathAbs(data.years);
9859
9860    return this;
9861}
9862
9863function addSubtract$1 (duration, input, value, direction) {
9864    var other = createDuration(input, value);
9865
9866    duration._milliseconds += direction * other._milliseconds;
9867    duration._days         += direction * other._days;
9868    duration._months       += direction * other._months;
9869
9870    return duration._bubble();
9871}
9872
9873// supports only 2.0-style add(1, 's') or add(duration)
9874function add$1 (input, value) {
9875    return addSubtract$1(this, input, value, 1);
9876}
9877
9878// supports only 2.0-style subtract(1, 's') or subtract(duration)
9879function subtract$1 (input, value) {
9880    return addSubtract$1(this, input, value, -1);
9881}
9882
9883function absCeil (number) {
9884    if (number < 0) {
9885        return Math.floor(number);
9886    } else {
9887        return Math.ceil(number);
9888    }
9889}
9890
9891function bubble () {
9892    var milliseconds = this._milliseconds;
9893    var days         = this._days;
9894    var months       = this._months;
9895    var data         = this._data;
9896    var seconds, minutes, hours, years, monthsFromDays;
9897
9898    // if we have a mix of positive and negative values, bubble down first
9899    // check: https://github.com/moment/moment/issues/2166
9900    if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
9901            (milliseconds <= 0 && days <= 0 && months <= 0))) {
9902        milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
9903        days = 0;
9904        months = 0;
9905    }
9906
9907    // The following code bubbles up values, see the tests for
9908    // examples of what that means.
9909    data.milliseconds = milliseconds % 1000;
9910
9911    seconds           = absFloor(milliseconds / 1000);
9912    data.seconds      = seconds % 60;
9913
9914    minutes           = absFloor(seconds / 60);
9915    data.minutes      = minutes % 60;
9916
9917    hours             = absFloor(minutes / 60);
9918    data.hours        = hours % 24;
9919
9920    days += absFloor(hours / 24);
9921
9922    // convert days to months
9923    monthsFromDays = absFloor(daysToMonths(days));
9924    months += monthsFromDays;
9925    days -= absCeil(monthsToDays(monthsFromDays));
9926
9927    // 12 months -> 1 year
9928    years = absFloor(months / 12);
9929    months %= 12;
9930
9931    data.days   = days;
9932    data.months = months;
9933    data.years  = years;
9934
9935    return this;
9936}
9937
9938function daysToMonths (days) {
9939    // 400 years have 146097 days (taking into account leap year rules)
9940    // 400 years have 12 months === 4800
9941    return days * 4800 / 146097;
9942}
9943
9944function monthsToDays (months) {
9945    // the reverse of daysToMonths
9946    return months * 146097 / 4800;
9947}
9948
9949function as (units) {
9950    if (!this.isValid()) {
9951        return NaN;
9952    }
9953    var days;
9954    var months;
9955    var milliseconds = this._milliseconds;
9956
9957    units = normalizeUnits(units);
9958
9959    if (units === 'month' || units === 'year') {
9960        days   = this._days   + milliseconds / 864e5;
9961        months = this._months + daysToMonths(days);
9962        return units === 'month' ? months : months / 12;
9963    } else {
9964        // handle milliseconds separately because of floating point math errors (issue #1867)
9965        days = this._days + Math.round(monthsToDays(this._months));
9966        switch (units) {
9967            case 'week'   : return days / 7     + milliseconds / 6048e5;
9968            case 'day'    : return days         + milliseconds / 864e5;
9969            case 'hour'   : return days * 24    + milliseconds / 36e5;
9970            case 'minute' : return days * 1440  + milliseconds / 6e4;
9971            case 'second' : return days * 86400 + milliseconds / 1000;
9972            // Math.floor prevents floating point math errors here
9973            case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
9974            default: throw new Error('Unknown unit ' + units);
9975        }
9976    }
9977}
9978
9979// TODO: Use this.as('ms')?
9980function valueOf$1 () {
9981    if (!this.isValid()) {
9982        return NaN;
9983    }
9984    return (
9985        this._milliseconds +
9986        this._days * 864e5 +
9987        (this._months % 12) * 2592e6 +
9988        toInt(this._months / 12) * 31536e6
9989    );
9990}
9991
9992function makeAs (alias) {
9993    return function () {
9994        return this.as(alias);
9995    };
9996}
9997
9998var asMilliseconds = makeAs('ms');
9999var asSeconds      = makeAs('s');
10000var asMinutes      = makeAs('m');
10001var asHours        = makeAs('h');
10002var asDays         = makeAs('d');
10003var asWeeks        = makeAs('w');
10004var asMonths       = makeAs('M');
10005var asYears        = makeAs('y');
10006
10007function clone$1 () {
10008    return createDuration(this);
10009}
10010
10011function get$2 (units) {
10012    units = normalizeUnits(units);
10013    return this.isValid() ? this[units + 's']() : NaN;
10014}
10015
10016function makeGetter(name) {
10017    return function () {
10018        return this.isValid() ? this._data[name] : NaN;
10019    };
10020}
10021
10022var milliseconds = makeGetter('milliseconds');
10023var seconds      = makeGetter('seconds');
10024var minutes      = makeGetter('minutes');
10025var hours        = makeGetter('hours');
10026var days         = makeGetter('days');
10027var months       = makeGetter('months');
10028var years        = makeGetter('years');
10029
10030function weeks () {
10031    return absFloor(this.days() / 7);
10032}
10033
10034var round = Math.round;
10035var thresholds = {
10036    ss: 44,         // a few seconds to seconds
10037    s : 45,         // seconds to minute
10038    m : 45,         // minutes to hour
10039    h : 22,         // hours to day
10040    d : 26,         // days to month
10041    M : 11          // months to year
10042};
10043
10044// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
10045function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
10046    return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
10047}
10048
10049function relativeTime$1 (posNegDuration, withoutSuffix, locale) {
10050    var duration = createDuration(posNegDuration).abs();
10051    var seconds  = round(duration.as('s'));
10052    var minutes  = round(duration.as('m'));
10053    var hours    = round(duration.as('h'));
10054    var days     = round(duration.as('d'));
10055    var months   = round(duration.as('M'));
10056    var years    = round(duration.as('y'));
10057
10058    var a = seconds <= thresholds.ss && ['s', seconds]  ||
10059            seconds < thresholds.s   && ['ss', seconds] ||
10060            minutes <= 1             && ['m']           ||
10061            minutes < thresholds.m   && ['mm', minutes] ||
10062            hours   <= 1             && ['h']           ||
10063            hours   < thresholds.h   && ['hh', hours]   ||
10064            days    <= 1             && ['d']           ||
10065            days    < thresholds.d   && ['dd', days]    ||
10066            months  <= 1             && ['M']           ||
10067            months  < thresholds.M   && ['MM', months]  ||
10068            years   <= 1             && ['y']           || ['yy', years];
10069
10070    a[2] = withoutSuffix;
10071    a[3] = +posNegDuration > 0;
10072    a[4] = locale;
10073    return substituteTimeAgo.apply(null, a);
10074}
10075
10076// This function allows you to set the rounding function for relative time strings
10077function getSetRelativeTimeRounding (roundingFunction) {
10078    if (roundingFunction === undefined) {
10079        return round;
10080    }
10081    if (typeof(roundingFunction) === 'function') {
10082        round = roundingFunction;
10083        return true;
10084    }
10085    return false;
10086}
10087
10088// This function allows you to set a threshold for relative time strings
10089function getSetRelativeTimeThreshold (threshold, limit) {
10090    if (thresholds[threshold] === undefined) {
10091        return false;
10092    }
10093    if (limit === undefined) {
10094        return thresholds[threshold];
10095    }
10096    thresholds[threshold] = limit;
10097    if (threshold === 's') {
10098        thresholds.ss = limit - 1;
10099    }
10100    return true;
10101}
10102
10103function humanize (withSuffix) {
10104    if (!this.isValid()) {
10105        return this.localeData().invalidDate();
10106    }
10107
10108    var locale = this.localeData();
10109    var output = relativeTime$1(this, !withSuffix, locale);
10110
10111    if (withSuffix) {
10112        output = locale.pastFuture(+this, output);
10113    }
10114
10115    return locale.postformat(output);
10116}
10117
10118var abs$1 = Math.abs;
10119
10120function sign(x) {
10121    return ((x > 0) - (x < 0)) || +x;
10122}
10123
10124function toISOString$1() {
10125    // for ISO strings we do not use the normal bubbling rules:
10126    //  * milliseconds bubble up until they become hours
10127    //  * days do not bubble at all
10128    //  * months bubble up until they become years
10129    // This is because there is no context-free conversion between hours and days
10130    // (think of clock changes)
10131    // and also not between days and months (28-31 days per month)
10132    if (!this.isValid()) {
10133        return this.localeData().invalidDate();
10134    }
10135
10136    var seconds = abs$1(this._milliseconds) / 1000;
10137    var days         = abs$1(this._days);
10138    var months       = abs$1(this._months);
10139    var minutes, hours, years;
10140
10141    // 3600 seconds -> 60 minutes -> 1 hour
10142    minutes           = absFloor(seconds / 60);
10143    hours             = absFloor(minutes / 60);
10144    seconds %= 60;
10145    minutes %= 60;
10146
10147    // 12 months -> 1 year
10148    years  = absFloor(months / 12);
10149    months %= 12;
10150
10151
10152    // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
10153    var Y = years;
10154    var M = months;
10155    var D = days;
10156    var h = hours;
10157    var m = minutes;
10158    var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
10159    var total = this.asSeconds();
10160
10161    if (!total) {
10162        // this is the same as C#'s (Noda) and python (isodate)...
10163        // but not other JS (goog.date)
10164        return 'P0D';
10165    }
10166
10167    var totalSign = total < 0 ? '-' : '';
10168    var ymSign = sign(this._months) !== sign(total) ? '-' : '';
10169    var daysSign = sign(this._days) !== sign(total) ? '-' : '';
10170    var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
10171
10172    return totalSign + 'P' +
10173        (Y ? ymSign + Y + 'Y' : '') +
10174        (M ? ymSign + M + 'M' : '') +
10175        (D ? daysSign + D + 'D' : '') +
10176        ((h || m || s) ? 'T' : '') +
10177        (h ? hmsSign + h + 'H' : '') +
10178        (m ? hmsSign + m + 'M' : '') +
10179        (s ? hmsSign + s + 'S' : '');
10180}
10181
10182var proto$2 = Duration.prototype;
10183
10184proto$2.isValid        = isValid$1;
10185proto$2.abs            = abs;
10186proto$2.add            = add$1;
10187proto$2.subtract       = subtract$1;
10188proto$2.as             = as;
10189proto$2.asMilliseconds = asMilliseconds;
10190proto$2.asSeconds      = asSeconds;
10191proto$2.asMinutes      = asMinutes;
10192proto$2.asHours        = asHours;
10193proto$2.asDays         = asDays;
10194proto$2.asWeeks        = asWeeks;
10195proto$2.asMonths       = asMonths;
10196proto$2.asYears        = asYears;
10197proto$2.valueOf        = valueOf$1;
10198proto$2._bubble        = bubble;
10199proto$2.clone          = clone$1;
10200proto$2.get            = get$2;
10201proto$2.milliseconds   = milliseconds;
10202proto$2.seconds        = seconds;
10203proto$2.minutes        = minutes;
10204proto$2.hours          = hours;
10205proto$2.days           = days;
10206proto$2.weeks          = weeks;
10207proto$2.months         = months;
10208proto$2.years          = years;
10209proto$2.humanize       = humanize;
10210proto$2.toISOString    = toISOString$1;
10211proto$2.toString       = toISOString$1;
10212proto$2.toJSON         = toISOString$1;
10213proto$2.locale         = locale;
10214proto$2.localeData     = localeData;
10215
10216// Deprecations
10217proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);
10218proto$2.lang = lang;
10219
10220// Side effect imports
10221
10222// FORMATTING
10223
10224addFormatToken('X', 0, 0, 'unix');
10225addFormatToken('x', 0, 0, 'valueOf');
10226
10227// PARSING
10228
10229addRegexToken('x', matchSigned);
10230addRegexToken('X', matchTimestamp);
10231addParseToken('X', function (input, array, config) {
10232    config._d = new Date(parseFloat(input, 10) * 1000);
10233});
10234addParseToken('x', function (input, array, config) {
10235    config._d = new Date(toInt(input));
10236});
10237
10238// Side effect imports
10239
10240
10241hooks.version = '2.20.1';
10242
10243setHookCallback(createLocal);
10244
10245hooks.fn                    = proto;
10246hooks.min                   = min;
10247hooks.max                   = max;
10248hooks.now                   = now;
10249hooks.utc                   = createUTC;
10250hooks.unix                  = createUnix;
10251hooks.months                = listMonths;
10252hooks.isDate                = isDate;
10253hooks.locale                = getSetGlobalLocale;
10254hooks.invalid               = createInvalid;
10255hooks.duration              = createDuration;
10256hooks.isMoment              = isMoment;
10257hooks.weekdays              = listWeekdays;
10258hooks.parseZone             = createInZone;
10259hooks.localeData            = getLocale;
10260hooks.isDuration            = isDuration;
10261hooks.monthsShort           = listMonthsShort;
10262hooks.weekdaysMin           = listWeekdaysMin;
10263hooks.defineLocale          = defineLocale;
10264hooks.updateLocale          = updateLocale;
10265hooks.locales               = listLocales;
10266hooks.weekdaysShort         = listWeekdaysShort;
10267hooks.normalizeUnits        = normalizeUnits;
10268hooks.relativeTimeRounding  = getSetRelativeTimeRounding;
10269hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
10270hooks.calendarFormat        = getCalendarFormat;
10271hooks.prototype             = proto;
10272
10273// currently HTML5 input type only supports 24-hour formats
10274hooks.HTML5_FMT = {
10275    DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm',             // <input type="datetime-local" />
10276    DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss',  // <input type="datetime-local" step="1" />
10277    DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS',   // <input type="datetime-local" step="0.001" />
10278    DATE: 'YYYY-MM-DD',                             // <input type="date" />
10279    TIME: 'HH:mm',                                  // <input type="time" />
10280    TIME_SECONDS: 'HH:mm:ss',                       // <input type="time" step="1" />
10281    TIME_MS: 'HH:mm:ss.SSS',                        // <input type="time" step="0.001" />
10282    WEEK: 'YYYY-[W]WW',                             // <input type="week" />
10283    MONTH: 'YYYY-MM'                                // <input type="month" />
10284};
10285
10286return hooks;
10287
10288})));
10289
10290/*!
10291 * FullCalendar v3.10.5
10292 * Docs & License: https://fullcalendar.io/
10293 * (c) 2019 Adam Shaw
10294 */
10295(function webpackUniversalModuleDefinition(root, factory) {
10296	if(typeof exports === 'object' && typeof module === 'object')
10297		module.exports = factory(require("moment"), require("jquery"));
10298	else if(typeof define === 'function' && define.amd)
10299		define(["moment", "jquery"], factory);
10300	else if(typeof exports === 'object')
10301		exports["FullCalendar"] = factory(require("moment"), require("jquery"));
10302	else
10303		root["FullCalendar"] = factory(root["moment"], root["jQuery"]);
10304})(typeof self !== 'undefined' ? self : this, function(__WEBPACK_EXTERNAL_MODULE_0__, __WEBPACK_EXTERNAL_MODULE_3__) {
10305return /******/ (function(modules) { // webpackBootstrap
10306/******/ 	// The module cache
10307/******/ 	var installedModules = {};
10308/******/
10309/******/ 	// The require function
10310/******/ 	function __webpack_require__(moduleId) {
10311/******/
10312/******/ 		// Check if module is in cache
10313/******/ 		if(installedModules[moduleId]) {
10314/******/ 			return installedModules[moduleId].exports;
10315/******/ 		}
10316/******/ 		// Create a new module (and put it into the cache)
10317/******/ 		var module = installedModules[moduleId] = {
10318/******/ 			i: moduleId,
10319/******/ 			l: false,
10320/******/ 			exports: {}
10321/******/ 		};
10322/******/
10323/******/ 		// Execute the module function
10324/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
10325/******/
10326/******/ 		// Flag the module as loaded
10327/******/ 		module.l = true;
10328/******/
10329/******/ 		// Return the exports of the module
10330/******/ 		return module.exports;
10331/******/ 	}
10332/******/
10333/******/
10334/******/ 	// expose the modules object (__webpack_modules__)
10335/******/ 	__webpack_require__.m = modules;
10336/******/
10337/******/ 	// expose the module cache
10338/******/ 	__webpack_require__.c = installedModules;
10339/******/
10340/******/ 	// define getter function for harmony exports
10341/******/ 	__webpack_require__.d = function(exports, name, getter) {
10342/******/ 		if(!__webpack_require__.o(exports, name)) {
10343/******/ 			Object.defineProperty(exports, name, {
10344/******/ 				configurable: false,
10345/******/ 				enumerable: true,
10346/******/ 				get: getter
10347/******/ 			});
10348/******/ 		}
10349/******/ 	};
10350/******/
10351/******/ 	// getDefaultExport function for compatibility with non-harmony modules
10352/******/ 	__webpack_require__.n = function(module) {
10353/******/ 		var getter = module && module.__esModule ?
10354/******/ 			function getDefault() { return module['default']; } :
10355/******/ 			function getModuleExports() { return module; };
10356/******/ 		__webpack_require__.d(getter, 'a', getter);
10357/******/ 		return getter;
10358/******/ 	};
10359/******/
10360/******/ 	// Object.prototype.hasOwnProperty.call
10361/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
10362/******/
10363/******/ 	// __webpack_public_path__
10364/******/ 	__webpack_require__.p = "";
10365/******/
10366/******/ 	// Load entry module and return exports
10367/******/ 	return __webpack_require__(__webpack_require__.s = 256);
10368/******/ })
10369/************************************************************************/
10370/******/ ([
10371/* 0 */
10372/***/ (function(module, exports) {
10373
10374module.exports = __WEBPACK_EXTERNAL_MODULE_0__;
10375
10376/***/ }),
10377/* 1 */,
10378/* 2 */
10379/***/ (function(module, exports) {
10380
10381/*
10382derived from:
10383https://github.com/Microsoft/tslib/blob/v1.6.0/tslib.js
10384
10385only include the helpers we need, to keep down filesize
10386*/
10387var extendStatics = Object.setPrototypeOf ||
10388    ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
10389    function (d, b) { for (var p in b)
10390        if (b.hasOwnProperty(p))
10391            d[p] = b[p]; };
10392exports.__extends = function (d, b) {
10393    extendStatics(d, b);
10394    function __() { this.constructor = d; }
10395    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
10396};
10397
10398
10399/***/ }),
10400/* 3 */
10401/***/ (function(module, exports) {
10402
10403module.exports = __WEBPACK_EXTERNAL_MODULE_3__;
10404
10405/***/ }),
10406/* 4 */
10407/***/ (function(module, exports, __webpack_require__) {
10408
10409Object.defineProperty(exports, "__esModule", { value: true });
10410var moment = __webpack_require__(0);
10411var $ = __webpack_require__(3);
10412/* FullCalendar-specific DOM Utilities
10413----------------------------------------------------------------------------------------------------------------------*/
10414// Given the scrollbar widths of some other container, create borders/margins on rowEls in order to match the left
10415// and right space that was offset by the scrollbars. A 1-pixel border first, then margin beyond that.
10416function compensateScroll(rowEls, scrollbarWidths) {
10417    if (scrollbarWidths.left) {
10418        rowEls.css({
10419            'border-left-width': 1,
10420            'margin-left': scrollbarWidths.left - 1
10421        });
10422    }
10423    if (scrollbarWidths.right) {
10424        rowEls.css({
10425            'border-right-width': 1,
10426            'margin-right': scrollbarWidths.right - 1
10427        });
10428    }
10429}
10430exports.compensateScroll = compensateScroll;
10431// Undoes compensateScroll and restores all borders/margins
10432function uncompensateScroll(rowEls) {
10433    rowEls.css({
10434        'margin-left': '',
10435        'margin-right': '',
10436        'border-left-width': '',
10437        'border-right-width': ''
10438    });
10439}
10440exports.uncompensateScroll = uncompensateScroll;
10441// Make the mouse cursor express that an event is not allowed in the current area
10442function disableCursor() {
10443    $('body').addClass('fc-not-allowed');
10444}
10445exports.disableCursor = disableCursor;
10446// Returns the mouse cursor to its original look
10447function enableCursor() {
10448    $('body').removeClass('fc-not-allowed');
10449}
10450exports.enableCursor = enableCursor;
10451// Given a total available height to fill, have `els` (essentially child rows) expand to accomodate.
10452// By default, all elements that are shorter than the recommended height are expanded uniformly, not considering
10453// any other els that are already too tall. if `shouldRedistribute` is on, it considers these tall rows and
10454// reduces the available height.
10455function distributeHeight(els, availableHeight, shouldRedistribute) {
10456    // *FLOORING NOTE*: we floor in certain places because zoom can give inaccurate floating-point dimensions,
10457    // and it is better to be shorter than taller, to avoid creating unnecessary scrollbars.
10458    var minOffset1 = Math.floor(availableHeight / els.length); // for non-last element
10459    var minOffset2 = Math.floor(availableHeight - minOffset1 * (els.length - 1)); // for last element *FLOORING NOTE*
10460    var flexEls = []; // elements that are allowed to expand. array of DOM nodes
10461    var flexOffsets = []; // amount of vertical space it takes up
10462    var flexHeights = []; // actual css height
10463    var usedHeight = 0;
10464    undistributeHeight(els); // give all elements their natural height
10465    // find elements that are below the recommended height (expandable).
10466    // important to query for heights in a single first pass (to avoid reflow oscillation).
10467    els.each(function (i, el) {
10468        var minOffset = i === els.length - 1 ? minOffset2 : minOffset1;
10469        var naturalOffset = $(el).outerHeight(true);
10470        if (naturalOffset < minOffset) {
10471            flexEls.push(el);
10472            flexOffsets.push(naturalOffset);
10473            flexHeights.push($(el).height());
10474        }
10475        else {
10476            // this element stretches past recommended height (non-expandable). mark the space as occupied.
10477            usedHeight += naturalOffset;
10478        }
10479    });
10480    // readjust the recommended height to only consider the height available to non-maxed-out rows.
10481    if (shouldRedistribute) {
10482        availableHeight -= usedHeight;
10483        minOffset1 = Math.floor(availableHeight / flexEls.length);
10484        minOffset2 = Math.floor(availableHeight - minOffset1 * (flexEls.length - 1)); // *FLOORING NOTE*
10485    }
10486    // assign heights to all expandable elements
10487    $(flexEls).each(function (i, el) {
10488        var minOffset = i === flexEls.length - 1 ? minOffset2 : minOffset1;
10489        var naturalOffset = flexOffsets[i];
10490        var naturalHeight = flexHeights[i];
10491        var newHeight = minOffset - (naturalOffset - naturalHeight); // subtract the margin/padding
10492        if (naturalOffset < minOffset) { // we check this again because redistribution might have changed things
10493            $(el).height(newHeight);
10494        }
10495    });
10496}
10497exports.distributeHeight = distributeHeight;
10498// Undoes distrubuteHeight, restoring all els to their natural height
10499function undistributeHeight(els) {
10500    els.height('');
10501}
10502exports.undistributeHeight = undistributeHeight;
10503// Given `els`, a jQuery set of <td> cells, find the cell with the largest natural width and set the widths of all the
10504// cells to be that width.
10505// PREREQUISITE: if you want a cell to take up width, it needs to have a single inner element w/ display:inline
10506function matchCellWidths(els) {
10507    var maxInnerWidth = 0;
10508    els.find('> *').each(function (i, innerEl) {
10509        var innerWidth = $(innerEl).outerWidth();
10510        if (innerWidth > maxInnerWidth) {
10511            maxInnerWidth = innerWidth;
10512        }
10513    });
10514    maxInnerWidth++; // sometimes not accurate of width the text needs to stay on one line. insurance
10515    els.width(maxInnerWidth);
10516    return maxInnerWidth;
10517}
10518exports.matchCellWidths = matchCellWidths;
10519// Given one element that resides inside another,
10520// Subtracts the height of the inner element from the outer element.
10521function subtractInnerElHeight(outerEl, innerEl) {
10522    var both = outerEl.add(innerEl);
10523    var diff;
10524    // effin' IE8/9/10/11 sometimes returns 0 for dimensions. this weird hack was the only thing that worked
10525    both.css({
10526        position: 'relative',
10527        left: -1 // ensure reflow in case the el was already relative. negative is less likely to cause new scroll
10528    });
10529    diff = outerEl.outerHeight() - innerEl.outerHeight(); // grab the dimensions
10530    both.css({ position: '', left: '' }); // undo hack
10531    return diff;
10532}
10533exports.subtractInnerElHeight = subtractInnerElHeight;
10534/* Element Geom Utilities
10535----------------------------------------------------------------------------------------------------------------------*/
10536// borrowed from https://github.com/jquery/jquery-ui/blob/1.11.0/ui/core.js#L51
10537function getScrollParent(el) {
10538    var position = el.css('position');
10539    var scrollParent = el.parents().filter(function () {
10540        var parent = $(this);
10541        return (/(auto|scroll)/).test(parent.css('overflow') + parent.css('overflow-y') + parent.css('overflow-x'));
10542    }).eq(0);
10543    return position === 'fixed' || !scrollParent.length ? $(el[0].ownerDocument || document) : scrollParent;
10544}
10545exports.getScrollParent = getScrollParent;
10546// Queries the outer bounding area of a jQuery element.
10547// Returns a rectangle with absolute coordinates: left, right (exclusive), top, bottom (exclusive).
10548// Origin is optional.
10549function getOuterRect(el, origin) {
10550    var offset = el.offset();
10551    var left = offset.left - (origin ? origin.left : 0);
10552    var top = offset.top - (origin ? origin.top : 0);
10553    return {
10554        left: left,
10555        right: left + el.outerWidth(),
10556        top: top,
10557        bottom: top + el.outerHeight()
10558    };
10559}
10560exports.getOuterRect = getOuterRect;
10561// Queries the area within the margin/border/scrollbars of a jQuery element. Does not go within the padding.
10562// Returns a rectangle with absolute coordinates: left, right (exclusive), top, bottom (exclusive).
10563// Origin is optional.
10564// WARNING: given element can't have borders
10565// NOTE: should use clientLeft/clientTop, but very unreliable cross-browser.
10566function getClientRect(el, origin) {
10567    var offset = el.offset();
10568    var scrollbarWidths = getScrollbarWidths(el);
10569    var left = offset.left + getCssFloat(el, 'border-left-width') + scrollbarWidths.left - (origin ? origin.left : 0);
10570    var top = offset.top + getCssFloat(el, 'border-top-width') + scrollbarWidths.top - (origin ? origin.top : 0);
10571    return {
10572        left: left,
10573        right: left + el[0].clientWidth,
10574        top: top,
10575        bottom: top + el[0].clientHeight // clientHeight includes padding but NOT scrollbars
10576    };
10577}
10578exports.getClientRect = getClientRect;
10579// Queries the area within the margin/border/padding of a jQuery element. Assumed not to have scrollbars.
10580// Returns a rectangle with absolute coordinates: left, right (exclusive), top, bottom (exclusive).
10581// Origin is optional.
10582function getContentRect(el, origin) {
10583    var offset = el.offset(); // just outside of border, margin not included
10584    var left = offset.left + getCssFloat(el, 'border-left-width') + getCssFloat(el, 'padding-left') -
10585        (origin ? origin.left : 0);
10586    var top = offset.top + getCssFloat(el, 'border-top-width') + getCssFloat(el, 'padding-top') -
10587        (origin ? origin.top : 0);
10588    return {
10589        left: left,
10590        right: left + el.width(),
10591        top: top,
10592        bottom: top + el.height()
10593    };
10594}
10595exports.getContentRect = getContentRect;
10596// Returns the computed left/right/top/bottom scrollbar widths for the given jQuery element.
10597// WARNING: given element can't have borders (which will cause offsetWidth/offsetHeight to be larger).
10598// NOTE: should use clientLeft/clientTop, but very unreliable cross-browser.
10599function getScrollbarWidths(el) {
10600    var leftRightWidth = el[0].offsetWidth - el[0].clientWidth;
10601    var bottomWidth = el[0].offsetHeight - el[0].clientHeight;
10602    var widths;
10603    leftRightWidth = sanitizeScrollbarWidth(leftRightWidth);
10604    bottomWidth = sanitizeScrollbarWidth(bottomWidth);
10605    widths = { left: 0, right: 0, top: 0, bottom: bottomWidth };
10606    if (getIsLeftRtlScrollbars() && el.css('direction') === 'rtl') { // is the scrollbar on the left side?
10607        widths.left = leftRightWidth;
10608    }
10609    else {
10610        widths.right = leftRightWidth;
10611    }
10612    return widths;
10613}
10614exports.getScrollbarWidths = getScrollbarWidths;
10615// The scrollbar width computations in getScrollbarWidths are sometimes flawed when it comes to
10616// retina displays, rounding, and IE11. Massage them into a usable value.
10617function sanitizeScrollbarWidth(width) {
10618    width = Math.max(0, width); // no negatives
10619    width = Math.round(width);
10620    return width;
10621}
10622// Logic for determining if, when the element is right-to-left, the scrollbar appears on the left side
10623var _isLeftRtlScrollbars = null;
10624function getIsLeftRtlScrollbars() {
10625    if (_isLeftRtlScrollbars === null) {
10626        _isLeftRtlScrollbars = computeIsLeftRtlScrollbars();
10627    }
10628    return _isLeftRtlScrollbars;
10629}
10630function computeIsLeftRtlScrollbars() {
10631    var el = $('<div><div></div></div>')
10632        .css({
10633        position: 'absolute',
10634        top: -1000,
10635        left: 0,
10636        border: 0,
10637        padding: 0,
10638        overflow: 'scroll',
10639        direction: 'rtl'
10640    })
10641        .appendTo('body');
10642    var innerEl = el.children();
10643    var res = innerEl.offset().left > el.offset().left; // is the inner div shifted to accommodate a left scrollbar?
10644    el.remove();
10645    return res;
10646}
10647// Retrieves a jQuery element's computed CSS value as a floating-point number.
10648// If the queried value is non-numeric (ex: IE can return "medium" for border width), will just return zero.
10649function getCssFloat(el, prop) {
10650    return parseFloat(el.css(prop)) || 0;
10651}
10652/* Mouse / Touch Utilities
10653----------------------------------------------------------------------------------------------------------------------*/
10654// Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac)
10655function isPrimaryMouseButton(ev) {
10656    return ev.which === 1 && !ev.ctrlKey;
10657}
10658exports.isPrimaryMouseButton = isPrimaryMouseButton;
10659function getEvX(ev) {
10660    var touches = ev.originalEvent.touches;
10661    // on mobile FF, pageX for touch events is present, but incorrect,
10662    // so, look at touch coordinates first.
10663    if (touches && touches.length) {
10664        return touches[0].pageX;
10665    }
10666    return ev.pageX;
10667}
10668exports.getEvX = getEvX;
10669function getEvY(ev) {
10670    var touches = ev.originalEvent.touches;
10671    // on mobile FF, pageX for touch events is present, but incorrect,
10672    // so, look at touch coordinates first.
10673    if (touches && touches.length) {
10674        return touches[0].pageY;
10675    }
10676    return ev.pageY;
10677}
10678exports.getEvY = getEvY;
10679function getEvIsTouch(ev) {
10680    return /^touch/.test(ev.type);
10681}
10682exports.getEvIsTouch = getEvIsTouch;
10683function preventSelection(el) {
10684    el.addClass('fc-unselectable')
10685        .on('selectstart', preventDefault);
10686}
10687exports.preventSelection = preventSelection;
10688function allowSelection(el) {
10689    el.removeClass('fc-unselectable')
10690        .off('selectstart', preventDefault);
10691}
10692exports.allowSelection = allowSelection;
10693// Stops a mouse/touch event from doing it's native browser action
10694function preventDefault(ev) {
10695    ev.preventDefault();
10696}
10697exports.preventDefault = preventDefault;
10698/* General Geometry Utils
10699----------------------------------------------------------------------------------------------------------------------*/
10700// Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false
10701function intersectRects(rect1, rect2) {
10702    var res = {
10703        left: Math.max(rect1.left, rect2.left),
10704        right: Math.min(rect1.right, rect2.right),
10705        top: Math.max(rect1.top, rect2.top),
10706        bottom: Math.min(rect1.bottom, rect2.bottom)
10707    };
10708    if (res.left < res.right && res.top < res.bottom) {
10709        return res;
10710    }
10711    return false;
10712}
10713exports.intersectRects = intersectRects;
10714// Returns a new point that will have been moved to reside within the given rectangle
10715function constrainPoint(point, rect) {
10716    return {
10717        left: Math.min(Math.max(point.left, rect.left), rect.right),
10718        top: Math.min(Math.max(point.top, rect.top), rect.bottom)
10719    };
10720}
10721exports.constrainPoint = constrainPoint;
10722// Returns a point that is the center of the given rectangle
10723function getRectCenter(rect) {
10724    return {
10725        left: (rect.left + rect.right) / 2,
10726        top: (rect.top + rect.bottom) / 2
10727    };
10728}
10729exports.getRectCenter = getRectCenter;
10730// Subtracts point2's coordinates from point1's coordinates, returning a delta
10731function diffPoints(point1, point2) {
10732    return {
10733        left: point1.left - point2.left,
10734        top: point1.top - point2.top
10735    };
10736}
10737exports.diffPoints = diffPoints;
10738/* Object Ordering by Field
10739----------------------------------------------------------------------------------------------------------------------*/
10740function parseFieldSpecs(input) {
10741    var specs = [];
10742    var tokens = [];
10743    var i;
10744    var token;
10745    if (typeof input === 'string') {
10746        tokens = input.split(/\s*,\s*/);
10747    }
10748    else if (typeof input === 'function') {
10749        tokens = [input];
10750    }
10751    else if ($.isArray(input)) {
10752        tokens = input;
10753    }
10754    for (i = 0; i < tokens.length; i++) {
10755        token = tokens[i];
10756        if (typeof token === 'string') {
10757            specs.push(token.charAt(0) === '-' ?
10758                { field: token.substring(1), order: -1 } :
10759                { field: token, order: 1 });
10760        }
10761        else if (typeof token === 'function') {
10762            specs.push({ func: token });
10763        }
10764    }
10765    return specs;
10766}
10767exports.parseFieldSpecs = parseFieldSpecs;
10768function compareByFieldSpecs(obj1, obj2, fieldSpecs, obj1fallback, obj2fallback) {
10769    var i;
10770    var cmp;
10771    for (i = 0; i < fieldSpecs.length; i++) {
10772        cmp = compareByFieldSpec(obj1, obj2, fieldSpecs[i], obj1fallback, obj2fallback);
10773        if (cmp) {
10774            return cmp;
10775        }
10776    }
10777    return 0;
10778}
10779exports.compareByFieldSpecs = compareByFieldSpecs;
10780function compareByFieldSpec(obj1, obj2, fieldSpec, obj1fallback, obj2fallback) {
10781    if (fieldSpec.func) {
10782        return fieldSpec.func(obj1, obj2);
10783    }
10784    var val1 = obj1[fieldSpec.field];
10785    var val2 = obj2[fieldSpec.field];
10786    if (val1 == null && obj1fallback) {
10787        val1 = obj1fallback[fieldSpec.field];
10788    }
10789    if (val2 == null && obj2fallback) {
10790        val2 = obj2fallback[fieldSpec.field];
10791    }
10792    return flexibleCompare(val1, val2) * (fieldSpec.order || 1);
10793}
10794exports.compareByFieldSpec = compareByFieldSpec;
10795function flexibleCompare(a, b) {
10796    if (!a && !b) {
10797        return 0;
10798    }
10799    if (b == null) {
10800        return -1;
10801    }
10802    if (a == null) {
10803        return 1;
10804    }
10805    if ($.type(a) === 'string' || $.type(b) === 'string') {
10806        return String(a).localeCompare(String(b));
10807    }
10808    return a - b;
10809}
10810exports.flexibleCompare = flexibleCompare;
10811/* Date Utilities
10812----------------------------------------------------------------------------------------------------------------------*/
10813exports.dayIDs = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
10814exports.unitsDesc = ['year', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
10814 // descending
10815// Diffs the two moments into a Duration where full-days are recorded first, then the remaining time.
10816// Moments will have their timezones normalized.
10817function diffDayTime(a, b) {
10818    return moment.duration({
10819        days: a.clone().stripTime().diff(b.clone().stripTime(), 'days'),
10820        ms: a.time() - b.time() // time-of-day from day start. disregards timezone
10821    });
10822}
10823exports.diffDayTime = diffDayTime;
10824// Diffs the two moments via their start-of-day (regardless of timezone). Produces whole-day durations.
10825function diffDay(a, b) {
10826    return moment.duration({
10827        days: a.clone().stripTime().diff(b.clone().stripTime(), 'days')
10828    });
10829}
10830exports.diffDay = diffDay;
10831// Diffs two moments, producing a duration, made of a whole-unit-increment of the given unit. Uses rounding.
10832function diffByUnit(a, b, unit) {
10833    return moment.duration(Math.round(a.diff(b, unit, true)), // returnFloat=true
10834    unit);
10835}
10836exports.diffByUnit = diffByUnit;
10837// Computes the unit name of the largest whole-unit period of time.
10838// For example, 48 hours will be "days" whereas 49 hours will be "hours".
10839// Accepts start/end, a range object, or an original duration object.
10840function computeGreatestUnit(start, end) {
10841    var i;
10842    var unit;
10843    var val;
10844    for (i = 0; i < exports.unitsDesc.length; i++) {
10845        unit = exports.unitsDesc[i];
10846        val = computeRangeAs(unit, start, end);
10847        if (val >= 1 && isInt(val)) {
10848            break;
10849        }
10850    }
10851    return unit; // will be "milliseconds" if nothing else matches
10852}
10853exports.computeGreatestUnit = computeGreatestUnit;
10854// like computeGreatestUnit, but has special abilities to interpret the source input for clues
10855function computeDurationGreatestUnit(duration, durationInput) {
10856    var unit = computeGreatestUnit(duration);
10857    // prevent days:7 from being interpreted as a week
10858    if (unit === 'week' && typeof durationInput === 'object' && durationInput.days) {
10859        unit = 'day';
10860    }
10861    return unit;
10862}
10863exports.computeDurationGreatestUnit = computeDurationGreatestUnit;
10864// Computes the number of units (like "hours") in the given range.
10865// Range can be a {start,end} object, separate start/end args, or a Duration.
10866// Results are based on Moment's .as() and .diff() methods, so results can depend on internal handling
10867// of month-diffing logic (which tends to vary from version to version).
10868function computeRangeAs(unit, start, end) {
10869    if (end != null) { // given start, end
10870        return end.diff(start, unit, true);
10871    }
10872    else if (moment.isDuration(start)) { // given duration
10873        return start.as(unit);
10874    }
10875    else { // given { start, end } range object
10876        return start.end.diff(start.start, unit, true);
10877    }
10878}
10879// Intelligently divides a range (specified by a start/end params) by a duration
10880function divideRangeByDuration(start, end, dur) {
10881    var months;
10882    if (durationHasTime(dur)) {
10883        return (end - start) / dur;
10884    }
10885    months = dur.asMonths();
10886    if (Math.abs(months) >= 1 && isInt(months)) {
10887        return end.diff(start, 'months', true) / months;
10888    }
10889    return end.diff(start, 'days', true) / dur.asDays();
10890}
10891exports.divideRangeByDuration = divideRangeByDuration;
10892// Intelligently divides one duration by another
10893function divideDurationByDuration(dur1, dur2) {
10894    var months1;
10895    var months2;
10896    if (durationHasTime(dur1) || durationHasTime(dur2)) {
10897        return dur1 / dur2;
10898    }
10899    months1 = dur1.asMonths();
10900    months2 = dur2.asMonths();
10901    if (Math.abs(months1) >= 1 && isInt(months1) &&
10902        Math.abs(months2) >= 1 && isInt(months2)) {
10903        return months1 / months2;
10904    }
10905    return dur1.asDays() / dur2.asDays();
10906}
10907exports.divideDurationByDuration = divideDurationByDuration;
10908// Intelligently multiplies a duration by a number
10909function multiplyDuration(dur, n) {
10910    var months;
10911    if (durationHasTime(dur)) {
10912        return moment.duration(dur * n);
10913    }
10914    months = dur.asMonths();
10915    if (Math.abs(months) >= 1 && isInt(months)) {
10916        return moment.duration({ months: months * n });
10917    }
10918    return moment.duration({ days: dur.asDays() * n });
10919}
10920exports.multiplyDuration = multiplyDuration;
10921// Returns a boolean about whether the given duration has any time parts (hours/minutes/seconds/ms)
10922function durationHasTime(dur) {
10923    return Boolean(dur.hours() || dur.minutes() || dur.seconds() || dur.milliseconds());
10924}
10925exports.durationHasTime = durationHasTime;
10926function isNativeDate(input) {
10927    return Object.prototype.toString.call(input) === '[object Date]' || input instanceof Date;
10928}
10929exports.isNativeDate = isNativeDate;
10930// Returns a boolean about whether the given input is a time string, like "06:40:00" or "06:00"
10931function isTimeString(str) {
10932    return typeof str === 'string' &&
10933        /^\d+\:\d+(?:\:\d+\.?(?:\d{3})?)?$/.test(str);
10934}
10935exports.isTimeString = isTimeString;
10936/* Logging and Debug
10937----------------------------------------------------------------------------------------------------------------------*/
10938function log() {
10939    var args = [];
10940    for (var _i = 0; _i < arguments.length; _i++) {
10941        args[_i] = arguments[_i];
10942    }
10943    var console = window.console;
10944    if (console && console.log) {
10945        return console.log.apply(console, args);
10946    }
10947}
10948exports.log = log;
10949function warn() {
10950    var args = [];
10951    for (var _i = 0; _i < arguments.length; _i++) {
10952        args[_i] = arguments[_i];
10953    }
10954    var console = window.console;
10955    if (console && console.warn) {
10956        return console.warn.apply(console, args);
10957    }
10958    else {
10959        return log.apply(null, args);
10960    }
10961}
10962exports.warn = warn;
10963/* General Utilities
10964----------------------------------------------------------------------------------------------------------------------*/
10965var hasOwnPropMethod = {}.hasOwnProperty;
10966// Merges an array of objects into a single object.
10967// The second argument allows for an array of property names who's object values will be merged together.
10968function mergeProps(propObjs, complexProps) {
10969    var dest = {};
10970    var i;
10971    var name;
10972    var complexObjs;
10973    var j;
10974    var val;
10975    var props;
10976    if (complexProps) {
10977        for (i = 0; i < complexProps.length; i++) {
10978            name = complexProps[i];
10979            complexObjs = [];
10980            // collect the trailing object values, stopping when a non-object is discovered
10981            for (j = propObjs.length - 1; j >= 0; j--) {
10982                val = propObjs[j][name];
10983                if (typeof val === 'object') {
10984                    complexObjs.unshift(val);
10985                }
10986                else if (val !== undefined) {
10987                    dest[name] = val; // if there were no objects, this value will be used
10988                    break;
10989                }
10990            }
10991            // if the trailing values were objects, use the merged value
10992            if (complexObjs.length) {
10993                dest[name] = mergeProps(complexObjs);
10994            }
10995        }
10996    }
10997    // copy values into the destination, going from last to first
10998    for (i = propObjs.length - 1; i >= 0; i--) {
10999        props = propObjs[i];
11000        for (name in props) {
11001            if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign
11002                dest[name] = props[name];
11003            }
11004        }
11005    }
11006    return dest;
11007}
11008exports.mergeProps = mergeProps;
11009function copyOwnProps(src, dest) {
11010    for (var name_1 in src) {
11011        if (hasOwnProp(src, name_1)) {
11012            dest[name_1] = src[name_1];
11013        }
11014    }
11015}
11016exports.copyOwnProps = copyOwnProps;
11017function hasOwnProp(obj, name) {
11018    return hasOwnPropMethod.call(obj, name);
11019}
11020exports.hasOwnProp = hasOwnProp;
11021function applyAll(functions, thisObj, args) {
11022    if ($.isFunction(functions)) {
11023        functions = [functions];
11024    }
11025    if (functions) {
11026        var i = void 0;
11027        var ret = void 0;
11028        for (i = 0; i < functions.length; i++) {
11029            ret = functions[i].apply(thisObj, args) || ret;
11030        }
11031        return ret;
11032    }
11033}
11034exports.applyAll = applyAll;
11035function removeMatching(array, testFunc) {
11036    var removeCnt = 0;
11037    var i = 0;
11038    while (i < array.length) {
11039        if (testFunc(array[i])) { // truthy value means *remove*
11040            array.splice(i, 1);
11041            removeCnt++;
11042        }
11043        else {
11044            i++;
11045        }
11046    }
11047    return removeCnt;
11048}
11049exports.removeMatching = removeMatching;
11050function removeExact(array, exactVal) {
11051    var removeCnt = 0;
11052    var i = 0;
11053    while (i < array.length) {
11054        if (array[i] === exactVal) {
11055            array.splice(i, 1);
11056            removeCnt++;
11057        }
11058        else {
11059            i++;
11060        }
11061    }
11062    return removeCnt;
11063}
11064exports.removeExact = removeExact;
11065function isArraysEqual(a0, a1) {
11066    var len = a0.length;
11067    var i;
11068    if (len == null || len !== a1.length) { // not array? or not same length?
11069        return false;
11070    }
11071    for (i = 0; i < len; i++) {
11072        if (a0[i] !== a1[i]) {
11073            return false;
11074        }
11075    }
11076    return true;
11077}
11078exports.isArraysEqual = isArraysEqual;
11079function firstDefined() {
11080    var args = [];
11081    for (var _i = 0; _i < arguments.length; _i++) {
11082        args[_i] = arguments[_i];
11083    }
11084    for (var i = 0; i < args.length; i++) {
11085        if (args[i] !== undefined) {
11086            return args[i];
11087        }
11088    }
11089}
11090exports.firstDefined = firstDefined;
11091function htmlEscape(s) {
11092    return (s + '').replace(/&/g, '&amp;')
11093        .replace(/</g, '&lt;')
11094        .replace(/>/g, '&gt;')
11095        .replace(/'/g, '&#039;')
11096        .replace(/"/g, '&quot;')
11097        .replace(/\n/g, '<br>');
11098}
11099exports.htmlEscape = htmlEscape;
11100function stripHtmlEntities(text) {
11101    return text.replace(/&.*?;/g, '');
11102}
11103exports.stripHtmlEntities = stripHtmlEntities;
11104// Given a hash of CSS properties, returns a string of CSS.
11105// Uses property names as-is (no camel-case conversion). Will not make statements for null/undefined values.
11106function cssToStr(cssProps) {
11107    var statements = [];
11108    $.each(cssProps, function (name, val) {
11109        if (val != null) {
11110            statements.push(name + ':' + val);
11111        }
11112    });
11113    return statements.join(';');
11114}
11115exports.cssToStr = cssToStr;
11116// Given an object hash of HTML attribute names to values,
11117// generates a string that can be injected between < > in HTML
11118function attrsToStr(attrs) {
11119    var parts = [];
11120    $.each(attrs, function (name, val) {
11121        if (val != null) {
11122            parts.push(name + '="' + htmlEscape(val) + '"');
11123        }
11124    });
11125    return parts.join(' ');
11126}
11127exports.attrsToStr = attrsToStr;
11128function capitaliseFirstLetter(str) {
11129    return str.charAt(0).toUpperCase() + str.slice(1);
11130}
11131exports.capitaliseFirstLetter = capitaliseFirstLetter;
11132function compareNumbers(a, b) {
11133    return a - b;
11134}
11135exports.compareNumbers = compareNumbers;
11136function isInt(n) {
11137    return n % 1 === 0;
11138}
11139exports.isInt = isInt;
11140// Returns a method bound to the given object context.
11141// Just like one of the jQuery.proxy signatures, but without the undesired behavior of treating the same method with
11142// different contexts as identical when binding/unbinding events.
11143function proxy(obj, methodName) {
11144    var method = obj[methodName];
11145    return function () {
11146        return method.apply(obj, arguments);
11147    };
11148}
11149exports.proxy = proxy;
11150// Returns a function, that, as long as it continues to be invoked, will not
11151// be triggered. The function will be called after it stops being called for
11152// N milliseconds. If `immediate` is passed, trigger the function on the
11153// leading edge, instead of the trailing.
11154// https://github.com/jashkenas/underscore/blob/1.6.0/underscore.js#L714
11155function debounce(func, wait, immediate) {
11156    if (immediate === void 0) { immediate = false; }
11157    var timeout;
11158    var args;
11159    var context;
11160    var timestamp;
11161    var result;
11162    var later = function () {
11163        var last = +new Date() - timestamp;
11164        if (last < wait) {
11165            timeout = setTimeout(later, wait - last);
11166        }
11167        else {
11168            timeout = null;
11169            if (!immediate) {
11170                result = func.apply(context, args);
11171                context = args = null;
11172            }
11173        }
11174    };
11175    return function () {
11176        context = this;
11177        args = arguments;
11178        timestamp = +new Date();
11179        var callNow = immediate && !timeout;
11180        if (!timeout) {
11181            timeout = setTimeout(later, wait);
11182        }
11183        if (callNow) {
11184            result = func.apply(context, args);
11185            context = args = null;
11186        }
11187        return result;
11188    };
11189}
11190exports.debounce = debounce;
11191
11192
11193/***/ }),
11194/* 5 */
11195/***/ (function(module, exports, __webpack_require__) {
11196
11197Object.defineProperty(exports, "__esModule", { value: true });
11198var moment = __webpack_require__(0);
11199var moment_ext_1 = __webpack_require__(11);
11200var UnzonedRange = /** @class */ (function () {
11201    function UnzonedRange(startInput, endInput) {
11202        // TODO: move these into footprint.
11203        // Especially, doesn't make sense for null startMs/endMs.
11204        this.isStart = true;
11205        this.isEnd = true;
11206        if (moment.isMoment(startInput)) {
11207            startInput = startInput.clone().stripZone();
11208        }
11209        if (moment.isMoment(endInput)) {
11210            endInput = endInput.clone().stripZone();
11211        }
11212        if (startInput) {
11213            this.startMs = startInput.valueOf();
11214        }
11215        if (endInput) {
11216            this.endMs = endInput.valueOf();
11217        }
11218    }
11219    /*
11220    SIDEEFFECT: will mutate eventRanges.
11221    Will return a new array result.
11222    Only works for non-open-ended ranges.
11223    */
11224    UnzonedRange.invertRanges = function (ranges, constraintRange) {
11225        var invertedRanges = [];
11226        var startMs = constraintRange.startMs; // the end of the previous range. the start of the new range
11227        var i;
11228        var dateRange;
11229        // ranges need to be in order. required for our date-walking algorithm
11230        ranges.sort(compareUnzonedRanges);
11231        for (i = 0; i < ranges.length; i++) {
11232            dateRange = ranges[i];
11233            // add the span of time before the event (if there is any)
11234            if (dateRange.startMs > startMs) { // compare millisecond time (skip any ambig logic)
11235                invertedRanges.push(new UnzonedRange(startMs, dateRange.startMs));
11236            }
11237            if (dateRange.endMs > startMs) {
11238                startMs = dateRange.endMs;
11239            }
11240        }
11241        // add the span of time after the last event (if there is any)
11242        if (startMs < constraintRange.endMs) { // compare millisecond time (skip any ambig logic)
11243            invertedRanges.push(new UnzonedRange(startMs, constraintRange.endMs));
11244        }
11245        return invertedRanges;
11246    };
11247    UnzonedRange.prototype.intersect = function (otherRange) {
11248        var startMs = this.startMs;
11249        var endMs = this.endMs;
11250        var newRange = null;
11251        if (otherRange.startMs != null) {
11252            if (startMs == null) {
11253                startMs = otherRange.startMs;
11254            }
11255            else {
11256                startMs = Math.max(startMs, otherRange.startMs);
11257            }
11258        }
11259        if (otherRange.endMs != null) {
11260            if (endMs == null) {
11261                endMs = otherRange.endMs;
11262            }
11263            else {
11264                endMs = Math.min(endMs, otherRange.endMs);
11265            }
11266        }
11267        if (startMs == null || endMs == null || startMs < endMs) {
11268            newRange = new UnzonedRange(startMs, endMs);
11269            newRange.isStart = this.isStart && startMs === this.startMs;
11270            newRange.isEnd = this.isEnd && endMs === this.endMs;
11271        }
11272        return newRange;
11273    };
11274    UnzonedRange.prototype.intersectsWith = function (otherRange) {
11275        return (this.endMs == null || otherRange.startMs == null || this.endMs > otherRange.startMs) &&
11276            (this.startMs == null || otherRange.endMs == null || this.startMs < otherRange.endMs);
11277    };
11278    UnzonedRange.prototype.containsRange = function (innerRange) {
11279        return (this.startMs == null || (innerRange.startMs != null && innerRange.startMs >= this.startMs)) &&
11280            (this.endMs == null || (innerRange.endMs != null && innerRange.endMs <= this.endMs));
11281    };
11282    // `date` can be a moment, a Date, or a millisecond time.
11283    UnzonedRange.prototype.containsDate = function (date) {
11284        var ms = date.valueOf();
11285        return (this.startMs == null || ms >= this.startMs) &&
11286            (this.endMs == null || ms < this.endMs);
11287    };
11288    // If the given date is not within the given range, move it inside.
11289    // (If it's past the end, make it one millisecond before the end).
11290    // `date` can be a moment, a Date, or a millisecond time.
11291    // Returns a MS-time.
11292    UnzonedRange.prototype.constrainDate = function (date) {
11293        var ms = date.valueOf();
11294        if (this.startMs != null && ms < this.startMs) {
11295            ms = this.startMs;
11296        }
11297        if (this.endMs != null && ms >= this.endMs) {
11298            ms = this.endMs - 1;
11299        }
11300        return ms;
11301    };
11302    UnzonedRange.prototype.equals = function (otherRange) {
11303        return this.startMs === otherRange.startMs && this.endMs === otherRange.endMs;
11304    };
11305    UnzonedRange.prototype.clone = function () {
11306        var range = new UnzonedRange(this.startMs, this.endMs);
11307        range.isStart = this.isStart;
11308        range.isEnd = this.isEnd;
11309        return range;
11310    };
11311    // Returns an ambig-zoned moment from startMs.
11312    // BEWARE: returned moment is not localized.
11313    // Formatting and start-of-week will be default.
11314    UnzonedRange.prototype.getStart = function () {
11315        if (this.startMs != null) {
11316            return moment_ext_1.default.utc(this.startMs).stripZone();
11317        }
11318        return null;
11319    };
11320    // Returns an ambig-zoned moment from startMs.
11321    // BEWARE: returned moment is not localized.
11322    // Formatting and start-of-week will be default.
11323    UnzonedRange.prototype.getEnd = function () {
11324        if (this.endMs != null) {
11325            return moment_ext_1.default.utc(this.endMs).stripZone();
11326        }
11327        return null;
11328    };
11329    UnzonedRange.prototype.as = function (unit) {
11330        return moment.utc(this.endMs).diff(moment.utc(this.startMs), unit, true);
11331    };
11332    return UnzonedRange;
11333}());
11334exports.default = UnzonedRange;
11335/*
11336Only works for non-open-ended ranges.
11337*/
11338function compareUnzonedRanges(range1, range2) {
11339    return range1.startMs - range2.startMs; // earlier ranges go first
11340}
11341
11342
11343/***/ }),
11344/* 6 */
11345/***/ (function(module, exports, __webpack_require__) {
11346
11347Object.defineProperty(exports, "__esModule", { value: true });
11348var tslib_1 = __webpack_require__(2);
11349var $ = __webpack_require__(3);
11350var ParsableModelMixin_1 = __webpack_require__(52);
11351var Class_1 = __webpack_require__(35);
11352var EventDefParser_1 = __webpack_require__(36);
11353var EventSource = /** @class */ (function (_super) {
11354    tslib_1.__extends(EventSource, _super);
11355    // can we do away with calendar? at least for the abstract?
11356    // useful for buildEventDef
11357    function EventSource(calendar) {
11358        var _this = _super.call(this) || this;
11359        _this.calendar = calendar;
11360        _this.className = [];
11361        _this.uid = String(EventSource.uuid++);
11362        return _this;
11363    }
11364    /*
11365    rawInput can be any data type!
11366    */
11367    EventSource.parse = function (rawInput, calendar) {
11368        var source = new this(calendar);
11369        if (typeof rawInput === 'object') {
11370            if (source.applyProps(rawInput)) {
11371                return source;
11372            }
11373        }
11374        return false;
11375    };
11376    EventSource.normalizeId = function (id) {
11377        if (id) {
11378            return String(id);
11379        }
11380        return null;
11381    };
11382    EventSource.prototype.fetch = function (start, end, timezone) {
11383        // subclasses must implement. must return a promise.
11384    };
11385    EventSource.prototype.removeEventDefsById = function (eventDefId) {
11386        // optional for subclasses to implement
11387    };
11388    EventSource.prototype.removeAllEventDefs = function () {
11389        // optional for subclasses to implement
11390    };
11391    /*
11392    For compairing/matching
11393    */
11394    EventSource.prototype.getPrimitive = function (otherSource) {
11395        // subclasses must implement
11396    };
11397    EventSource.prototype.parseEventDefs = function (rawEventDefs) {
11398        var i;
11399        var eventDef;
11400        var eventDefs = [];
11401        for (i = 0; i < rawEventDefs.length; i++) {
11402            eventDef = this.parseEventDef(rawEventDefs[i]);
11403            if (eventDef) {
11404                eventDefs.push(eventDef);
11405            }
11406        }
11407        return eventDefs;
11408    };
11409    EventSource.prototype.parseEventDef = function (rawInput) {
11410        var calendarTransform = this.calendar.opt('eventDataTransform');
11411        var sourceTransform = this.eventDataTransform;
11412        if (calendarTransform) {
11413            rawInput = calendarTransform(rawInput, this.calendar);
11414        }
11415        if (sourceTransform) {
11416            rawInput = sourceTransform(rawInput, this.calendar);
11417        }
11418        return EventDefParser_1.default.parse(rawInput, this);
11419    };
11420    EventSource.prototype.applyManualStandardProps = function (rawProps) {
11421        if (rawProps.id != null) {
11422            this.id = EventSource.normalizeId(rawProps.id);
11423        }
11424        // TODO: converge with EventDef
11425        if ($.isArray(rawProps.className)) {
11426            this.className = rawProps.className;
11427        }
11428        else if (typeof rawProps.className === 'string') {
11429            this.className = rawProps.className.split(/\s+/);
11430        }
11431        return true;
11432    };
11433    EventSource.uuid = 0;
11434    EventSource.defineStandardProps = ParsableModelMixin_1.default.defineStandardProps;
11435    EventSource.copyVerbatimStandardProps = ParsableModelMixin_1.default.copyVerbatimStandardProps;
11436    return EventSource;
11437}(Class_1.default));
11438exports.default = EventSource;
11439ParsableModelMixin_1.default.mixInto(EventSource);
11440// Parsing
11441// ---------------------------------------------------------------------------------------------------------------------
11442EventSource.defineStandardProps({
11443    // manually process...
11444    id: false,
11445    className: false,
11446    // automatically transfer...
11447    color: true,
11448    backgroundColor: true,
11449    borderColor: true,
11450    textColor: true,
11451    editable: true,
11452    startEditable: true,
11453    durationEditable: true,
11454    rendering: true,
11455    overlap: true,
11456    constraint: true,
11457    allDayDefault: true,
11458    eventDataTransform: true
11459});
11460
11461
11462/***/ }),
11463/* 7 */
11464/***/ (function(module, exports, __webpack_require__) {
11465
11466/*
11467Utility methods for easily listening to events on another object,
11468and more importantly, easily unlistening from them.
11469
11470USAGE:
11471  import { default as ListenerMixin, ListenerInterface } from './ListenerMixin'
11472in class:
11473  listenTo: ListenerInterface['listenTo']
11474  stopListeningTo: ListenerInterface['stopListeningTo']
11475after class:
11476  ListenerMixin.mixInto(TheClass)
11477*/
11478Object.defineProperty(exports, "__esModule", { value: true });
11479var tslib_1 = __webpack_require__(2);
11480var $ = __webpack_require__(3);
11481var Mixin_1 = __webpack_require__(15);
11482var guid = 0;
11483var ListenerMixin = /** @class */ (function (_super) {
11484    tslib_1.__extends(ListenerMixin, _super);
11485    function ListenerMixin() {
11486        return _super !== null && _super.apply(this, arguments) || this;
11487    }
11488    /*
11489    Given an `other` object that has on/off methods, bind the given `callback` to an event by the given name.
11490    The `callback` will be called with the `this` context of the object that .listenTo is being called on.
11491    Can be called:
11492      .listenTo(other, eventName, callback)
11493    OR
11494      .listenTo(other, {
11495        eventName1: callback1,
11496        eventName2: callback2
11497      })
11498    */
11499    ListenerMixin.prototype.listenTo = function (other, arg, callback) {
11500        if (typeof arg === 'object') { // given dictionary of callbacks
11501            for (var eventName in arg) {
11502                if (arg.hasOwnProperty(eventName)) {
11503                    this.listenTo(other, eventName, arg[eventName]);
11504                }
11505            }
11506        }
11507        else if (typeof arg === 'string') {
11508            other.on(arg + '.' + this.getListenerNamespace(), // use event namespacing to identify this object
11509            $.proxy(callback, this) // always use `this` context
11510            // the usually-undesired jQuery guid behavior doesn't matter,
11511            // because we always unbind via namespace
11512            );
11513        }
11514    };
11515    /*
11516    Causes the current object to stop listening to events on the `other` object.
11517    `eventName` is optional. If omitted, will stop listening to ALL events on `other`.
11518    */
11519    ListenerMixin.prototype.stopListeningTo = function (other, eventName) {
11520        other.off((eventName || '') + '.' + this.getListenerNamespace());
11521    };
11522    /*
11523    Returns a string, unique to this object, to be used for event namespacing
11524    */
11525    ListenerMixin.prototype.getListenerNamespace = function () {
11526        if (this.listenerId == null) {
11527            this.listenerId = guid++;
11528        }
11529        return '_listener' + this.listenerId;
11530    };
11531    return ListenerMixin;
11532}(Mixin_1.default));
11533exports.default = ListenerMixin;
11534
11535
11536/***/ }),
11537/* 8 */,
11538/* 9 */
11539/***/ (function(module, exports, __webpack_require__) {
11540
11541Object.defineProperty(exports, "__esModule", { value: true });
11542var tslib_1 = __webpack_require__(2);
11543var EventDef_1 = __webpack_require__(37);
11544var EventInstance_1 = __webpack_require__(53);
11545var EventDateProfile_1 = __webpack_require__(16);
11546var SingleEventDef = /** @class */ (function (_super) {
11547    tslib_1.__extends(SingleEventDef, _super);
11548    function SingleEventDef() {
11549        return _super !== null && _super.apply(this, arguments) || this;
11550    }
11551    /*
11552    Will receive start/end params, but will be ignored.
11553    */
11554    SingleEventDef.prototype.buildInstances = function () {
11555        return [this.buildInstance()];
11556    };
11557    SingleEventDef.prototype.buildInstance = function () {
11558        return new EventInstance_1.default(this, // definition
11559        this.dateProfile);
11560    };
11561    SingleEventDef.prototype.isAllDay = function () {
11562        return this.dateProfile.isAllDay();
11563    };
11564    SingleEventDef.prototype.clone = function () {
11565        var def = _super.prototype.clone.call(this);
11566        def.dateProfile = this.dateProfile;
11567        return def;
11568    };
11569    SingleEventDef.prototype.rezone = function () {
11570        var calendar = this.source.calendar;
11571        var dateProfile = this.dateProfile;
11572        this.dateProfile = new EventDateProfile_1.default(calendar.moment(dateProfile.start), dateProfile.end ? calendar.moment(dateProfile.end) : null, calendar);
11573    };
11574    /*
11575    NOTE: if super-method fails, should still attempt to apply
11576    */
11577    SingleEventDef.prototype.applyManualStandardProps = function (rawProps) {
11578        var superSuccess = _super.prototype.applyManualStandardProps.call(this, rawProps);
11579        var dateProfile = EventDateProfile_1.default.parse(rawProps, this.source); // returns null on failure
11580        if (dateProfile) {
11581            this.dateProfile = dateProfile;
11582            // make sure `date` shows up in the legacy event objects as-is
11583            if (rawProps.date != null) {
11584                this.miscProps.date = rawProps.date;
11585            }
11586            return superSuccess;
11587        }
11588        else {
11589            return false;
11590        }
11591    };
11592    return SingleEventDef;
11593}(EventDef_1.default));
11594exports.default = SingleEventDef;
11595// Parsing
11596// ---------------------------------------------------------------------------------------------------------------------
11597SingleEventDef.defineStandardProps({
11598    start: false,
11599    date: false,
11600    end: false,
11601    allDay: false
11602});
11603
11604
11605/***/ }),
11606/* 10 */,
11607/* 11 */
11608/***/ (function(module, exports, __webpack_require__) {
11609
11610Object.defineProperty(exports, "__esModule", { value: true });
11611var moment = __webpack_require__(0);
11612var $ = __webpack_require__(3);
11613var util_1 = __webpack_require__(4);
11614var ambigDateOfMonthRegex = /^\s*\d{4}-\d\d$/;
11615var ambigTimeOrZoneRegex = /^\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+)?)?)?)?)?$/;
11616var newMomentProto = moment.fn; // where we will attach our new methods
11617exports.newMomentProto = newMomentProto;
11618var oldMomentProto = $.extend({}, newMomentProto); // copy of original moment methods
11619exports.oldMomentProto = oldMomentProto;
11620// tell momentjs to transfer these properties upon clone
11621var momentProperties = moment.momentProperties;
11622momentProperties.push('_fullCalendar');
11623momentProperties.push('_ambigTime');
11624momentProperties.push('_ambigZone');
11625/*
11626Call this if you want Moment's original format method to be used
11627*/
11628function oldMomentFormat(mom, formatStr) {
11629    return oldMomentProto.format.call(mom, formatStr); // oldMomentProto defined in moment-ext.js
11630}
11631exports.oldMomentFormat = oldMomentFormat;
11632// Creating
11633// -------------------------------------------------------------------------------------------------
11634// Creates a new moment, similar to the vanilla moment(...) constructor, but with
11635// extra features (ambiguous time, enhanced formatting). When given an existing moment,
11636// it will function as a clone (and retain the zone of the moment). Anything else will
11637// result in a moment in the local zone.
11638var momentExt = function () {
11639    return makeMoment(arguments);
11640};
11641exports.default = momentExt;
11642// Sames as momentExt, but forces the resulting moment to be in the UTC timezone.
11643momentExt.utc = function () {
11644    var mom = makeMoment(arguments, true);
11645    // Force it into UTC because makeMoment doesn't guarantee it
11646    // (if given a pre-existing moment for example)
11647    if (mom.hasTime()) { // don't give ambiguously-timed moments a UTC zone
11648        mom.utc();
11649    }
11650    return mom;
11651};
11652// Same as momentExt, but when given an ISO8601 string, the timezone offset is preserved.
11653// ISO8601 strings with no timezone offset will become ambiguously zoned.
11654momentExt.parseZone = function () {
11655    return makeMoment(arguments, true, true);
11656};
11657// Builds an enhanced moment from args. When given an existing moment, it clones. When given a
11658// native Date, or called with no arguments (the current time), the resulting moment will be local.
11659// Anything else needs to be "parsed" (a string or an array), and will be affected by:
11660//    parseAsUTC - if there is no zone information, should we parse the input in UTC?
11661//    parseZone - if there is zone information, should we force the zone of the moment?
11662function makeMoment(args, parseAsUTC, parseZone) {
11663    if (parseAsUTC === void 0) { parseAsUTC = false; }
11664    if (parseZone === void 0) { parseZone = false; }
11665    var input = args[0];
11666    var isSingleString = args.length === 1 && typeof input === 'string';
11667    var isAmbigTime;
11668    var isAmbigZone;
11669    var ambigMatch;
11670    var mom;
11671    if (moment.isMoment(input) || util_1.isNativeDate(input) || input === undefined) {
11672        mom = moment.apply(null, args);
11673    }
11674    else { // "parsing" is required
11675        isAmbigTime = false;
11676        isAmbigZone = false;
11677        if (isSingleString) {
11678            if (ambigDateOfMonthRegex.test(input)) {
11679                // accept strings like '2014-05', but convert to the first of the month
11680                input += '-01';
11681                args = [input]; // for when we pass it on to moment's constructor
11682                isAmbigTime = true;
11683                isAmbigZone = true;
11684            }
11685            else if ((ambigMatch = ambigTimeOrZoneRegex.exec(input))) {
11686                isAmbigTime = !ambigMatch[5]; // no time part?
11687                isAmbigZone = true;
11688            }
11689        }
11690        else if ($.isArray(input)) {
11691            // arrays have no timezone information, so assume ambiguous zone
11692            isAmbigZone = true;
11693        }
11694        // otherwise, probably a string with a format
11695        if (parseAsUTC || isAmbigTime) {
11696            mom = moment.utc.apply(moment, args);
11697        }
11698        else {
11699            mom = moment.apply(null, args);
11700        }
11701        if (isAmbigTime) {
11702            mom._ambigTime = true;
11703            mom._ambigZone = true; // ambiguous time always means ambiguous zone
11704        }
11705        else if (parseZone) { // let's record the inputted zone somehow
11706            if (isAmbigZone) {
11707                mom._ambigZone = true;
11708            }
11709            else if (isSingleString) {
11710                mom.utcOffset(input); // if not a valid zone, will assign UTC
11711            }
11712        }
11713    }
11714    mom._fullCalendar = true; // flag for extended functionality
11715    return mom;
11716}
11717// Week Number
11718// -------------------------------------------------------------------------------------------------
11719// Returns the week number, considering the locale's custom week number calcuation
11720// `weeks` is an alias for `week`
11721newMomentProto.week = newMomentProto.weeks = function (input) {
11722    var weekCalc = this._locale._fullCalendar_weekCalc;
11723    if (input == null && typeof weekCalc === 'function') { // custom function only works for getter
11724        return weekCalc(this);
11725    }
11726    else if (weekCalc === 'ISO') {
11727        return oldMomentProto.isoWeek.apply(this, arguments); // ISO getter/setter
11728    }
11729    return oldMomentProto.week.apply(this, arguments); // local getter/setter
11730};
11731// Time-of-day
11732// -------------------------------------------------------------------------------------------------
11733// GETTER
11734// Returns a Duration with the hours/minutes/seconds/ms values of the moment.
11735// If the moment has an ambiguous time, a duration of 00:00 will be returned.
11736//
11737// SETTER
11738// You can supply a Duration, a Moment, or a Duration-like argument.
11739// When setting the time, and the moment has an ambiguous time, it then becomes unambiguous.
11740newMomentProto.time = function (time) {
11741    // Fallback to the original method (if there is one) if this moment wasn't created via FullCalendar.
11742    // `time` is a generic enough method name where this precaution is necessary to avoid collisions w/ other plugins.
11743    if (!this._fullCalendar) {
11744        return oldMomentProto.time.apply(this, arguments);
11745    }
11746    if (time == null) { // getter
11747        return moment.duration({
11748            hours: this.hours(),
11749            minutes: this.minutes(),
11750            seconds: this.seconds(),
11751            milliseconds: this.milliseconds()
11752        });
11753    }
11754    else { // setter
11755        this._ambigTime = false; // mark that the moment now has a time
11756        if (!moment.isDuration(time) && !moment.isMoment(time)) {
11757            time = moment.duration(time);
11758        }
11759        // The day value should cause overflow (so 24 hours becomes 00:00:00 of next day).
11760        // Only for Duration times, not Moment times.
11761        var dayHours = 0;
11762        if (moment.isDuration(time)) {
11763            dayHours = Math.floor(time.asDays()) * 24;
11764        }
11765        // We need to set the individual fields.
11766        // Can't use startOf('day') then add duration. In case of DST at start of day.
11767        return this.hours(dayHours + time.hours())
11768            .minutes(time.minutes())
11769            .seconds(time.seconds())
11770            .milliseconds(time.milliseconds());
11771    }
11772};
11773// Converts the moment to UTC, stripping out its time-of-day and timezone offset,
11774// but preserving its YMD. A moment with a stripped time will display no time
11775// nor timezone offset when .format() is called.
11776newMomentProto.stripTime = function () {
11777    if (!this._ambigTime) {
11778        this.utc(true); // keepLocalTime=true (for keeping *date* value)
11779        // set time to zero
11780        this.set({
11781            hours: 0,
11782            minutes: 0,
11783            seconds: 0,
11784            ms: 0
11785        });
11786        // Mark the time as ambiguous. This needs to happen after the .utc() call, which might call .utcOffset(),
11787        // which clears all ambig flags.
11788        this._ambigTime = true;
11789        this._ambigZone = true; // if ambiguous time, also ambiguous timezone offset
11790    }
11791    return this; // for chaining
11792};
11793// Returns if the moment has a non-ambiguous time (boolean)
11794newMomentProto.hasTime = function () {
11795    return !this._ambigTime;
11796};
11797// Timezone
11798// -------------------------------------------------------------------------------------------------
11799// Converts the moment to UTC, stripping out its timezone offset, but preserving its
11800// YMD and time-of-day. A moment with a stripped timezone offset will display no
11801// timezone offset when .format() is called.
11802newMomentProto.stripZone = function () {
11803    var wasAmbigTime;
11804    if (!this._ambigZone) {
11805        wasAmbigTime = this._ambigTime;
11806        this.utc(true); // keepLocalTime=true (for keeping date and time values)
11807        // the above call to .utc()/.utcOffset() unfortunately might clear the ambig flags, so restore
11808        this._ambigTime = wasAmbigTime || false;
11809        // Mark the zone as ambiguous. This needs to happen after the .utc() call, which might call .utcOffset(),
11810        // which clears the ambig flags.
11811        this._ambigZone = true;
11812    }
11813    return this; // for chaining
11814};
11815// Returns of the moment has a non-ambiguous timezone offset (boolean)
11816newMomentProto.hasZone = function () {
11817    return !this._ambigZone;
11818};
11819// implicitly marks a zone
11820newMomentProto.local = function (keepLocalTime) {
11821    // for when converting from ambiguously-zoned to local,
11822    // keep the time values when converting from UTC -> local
11823    oldMomentProto.local.call(this, this._ambigZone || keepLocalTime);
11824    // ensure non-ambiguous
11825    // this probably already happened via local() -> utcOffset(), but don't rely on Moment's internals
11826    this._ambigTime = false;
11827    this._ambigZone = false;
11828    return this; // for chaining
11829};
11830// implicitly marks a zone
11831newMomentProto.utc = function (keepLocalTime) {
11832    oldMomentProto.utc.call(this, keepLocalTime);
11833    // ensure non-ambiguous
11834    // this probably already happened via utc() -> utcOffset(), but don't rely on Moment's internals
11835    this._ambigTime = false;
11836    this._ambigZone = false;
11837    return this;
11838};
11839// implicitly marks a zone (will probably get called upon .utc() and .local())
11840newMomentProto.utcOffset = function (tzo) {
11841    if (tzo != null) { // setter
11842        // these assignments needs to happen before the original zone method is called.
11843        // I forget why, something to do with a browser crash.
11844        this._ambigTime = false;
11845        this._ambigZone = false;
11846    }
11847    return oldMomentProto.utcOffset.apply(this, arguments);
11848};
11849
11850
11851/***/ }),
11852/* 12 */
11853/***/ (function(module, exports) {
11854
11855Object.defineProperty(exports, "__esModule", { value: true });
11856/*
11857Meant to be immutable
11858*/
11859var ComponentFootprint = /** @class */ (function () {
11860    function ComponentFootprint(unzonedRange, isAllDay) {
11861        this.isAllDay = false; // component can choose to ignore this
11862        this.unzonedRange = unzonedRange;
11863        this.isAllDay = isAllDay;
11864    }
11865    /*
11866    Only works for non-open-ended ranges.
11867    */
11868    ComponentFootprint.prototype.toLegacy = function (calendar) {
11869        return {
11870            start: calendar.msToMoment(this.unzonedRange.startMs, this.isAllDay),
11871            end: calendar.msToMoment(this.unzonedRange.endMs, this.isAllDay)
11872        };
11873    };
11874    return ComponentFootprint;
11875}());
11876exports.default = ComponentFootprint;
11877
11878
11879/***/ }),
11880/* 13 */
11881/***/ (function(module, exports, __webpack_require__) {
11882
11883/*
11884USAGE:
11885  import { default as EmitterMixin, EmitterInterface } from './EmitterMixin'
11886in class:
11887  on: EmitterInterface['on']
11888  one: EmitterInterface['one']
11889  off: EmitterInterface['off']
11890  trigger: EmitterInterface['trigger']
11891  triggerWith: EmitterInterface['triggerWith']
11892  hasHandlers: EmitterInterface['hasHandlers']
11893after class:
11894  EmitterMixin.mixInto(TheClass)
11895*/
11896Object.defineProperty(exports, "__esModule", { value: true });
11897var tslib_1 = __webpack_require__(2);
11898var $ = __webpack_require__(3);
11899var Mixin_1 = __webpack_require__(15);
11900var EmitterMixin = /** @class */ (function (_super) {
11901    tslib_1.__extends(EmitterMixin, _super);
11902    function EmitterMixin() {
11903        return _super !== null && _super.apply(this, arguments) || this;
11904    }
11905    // jQuery-ification via $(this) allows a non-DOM object to have
11906    // the same event handling capabilities (including namespaces).
11907    EmitterMixin.prototype.on = function (types, handler) {
11908        $(this).on(types, this._prepareIntercept(handler));
11909        return this; // for chaining
11910    };
11911    EmitterMixin.prototype.one = function (types, handler) {
11912        $(this).one(types, this._prepareIntercept(handler));
11913        return this; // for chaining
11914    };
11915    EmitterMixin.prototype._prepareIntercept = function (handler) {
11916        // handlers are always called with an "event" object as their first param.
11917        // sneak the `this` context and arguments into the extra parameter object
11918        // and forward them on to the original handler.
11919        var intercept = function (ev, extra) {
11920            return handler.apply(extra.context || this, extra.args || []);
11921        };
11922        // mimick jQuery's internal "proxy" system (risky, I know)
11923        // causing all functions with the same .guid to appear to be the same.
11924        // https://github.com/jquery/jquery/blob/2.2.4/src/core.js#L448
11925        // this is needed for calling .off with the original non-intercept handler.
11926        if (!handler.guid) {
11927            handler.guid = $.guid++;
11928        }
11929        intercept.guid = handler.guid;
11930        return intercept;
11931    };
11932    EmitterMixin.prototype.off = function (types, handler) {
11933        $(this).off(types, handler);
11934        return this; // for chaining
11935    };
11936    EmitterMixin.prototype.trigger = function (types) {
11937        var args = [];
11938        for (var _i = 1; _i < arguments.length; _i++) {
11939            args[_i - 1] = arguments[_i];
11940        }
11941        // pass in "extra" info to the intercept
11942        $(this).triggerHandler(types, { args: args });
11943        return this; // for chaining
11944    };
11945    EmitterMixin.prototype.triggerWith = function (types, context, args
11945) {
11946        // `triggerHandler` is less reliant on the DOM compared to `trigger`.
11947        // pass in "extra" info to the intercept.
11948        $(this).triggerHandler(types, { context: context, args: args });
11949        return this; // for chaining
11950    };
11951    EmitterMixin.prototype.hasHandlers = function (type) {
11952        var hash = $._data(this, 'events'); // http://blog.jquery.com/2012/08/09/jquery-1-8-released/
11953        return hash && hash[type] && hash[type].length > 0;
11954    };
11955    return EmitterMixin;
11956}(Mixin_1.default));
11957exports.default = EmitterMixin;
11958
11959
11960/***/ }),
11961/* 14 */
11962/***/ (function(module, exports) {
11963
11964Object.defineProperty(exports, "__esModule", { value: true });
11965var Interaction = /** @class */ (function () {
11966    function Interaction(component) {
11967        this.view = component._getView();
11968        this.component = component;
11969    }
11970    Interaction.prototype.opt = function (name) {
11971        return this.view.opt(name);
11972    };
11973    Interaction.prototype.end = function () {
11974        // subclasses can implement
11975    };
11976    return Interaction;
11977}());
11978exports.default = Interaction;
11979
11980
11981/***/ }),
11982/* 15 */
11983/***/ (function(module, exports) {
11984
11985Object.defineProperty(exports, "__esModule", { value: true });
11986var Mixin = /** @class */ (function () {
11987    function Mixin() {
11988    }
11989    Mixin.mixInto = function (destClass) {
11990        var _this = this;
11991        Object.getOwnPropertyNames(this.prototype).forEach(function (name) {
11992            if (!destClass.prototype[name]) { // if destination class doesn't already define it
11993                destClass.prototype[name] = _this.prototype[name];
11994            }
11995        });
11996    };
11997    /*
11998    will override existing methods
11999    TODO: remove! not used anymore
12000    */
12001    Mixin.mixOver = function (destClass) {
12002        var _this = this;
12003        Object.getOwnPropertyNames(this.prototype).forEach(function (name) {
12004            destClass.prototype[name] = _this.prototype[name];
12005        });
12006    };
12007    return Mixin;
12008}());
12009exports.default = Mixin;
12010
12011
12012/***/ }),
12013/* 16 */
12014/***/ (function(module, exports, __webpack_require__) {
12015
12016Object.defineProperty(exports, "__esModule", { value: true });
12017var UnzonedRange_1 = __webpack_require__(5);
12018/*
12019Meant to be immutable
12020*/
12021var EventDateProfile = /** @class */ (function () {
12022    function EventDateProfile(start, end, calendar) {
12023        this.start = start;
12024        this.end = end || null;
12025        this.unzonedRange = this.buildUnzonedRange(calendar);
12026    }
12027    /*
12028    Needs an EventSource object
12029    */
12030    EventDateProfile.parse = function (rawProps, source) {
12031        var startInput = rawProps.start || rawProps.date;
12032        var endInput = rawProps.end;
12033        if (!startInput) {
12034            return false;
12035        }
12036        var calendar = source.calendar;
12037        var start = calendar.moment(startInput);
12038        var end = endInput ? calendar.moment(endInput) : null;
12039        var forcedAllDay = rawProps.allDay;
12040        var forceEventDuration = calendar.opt('forceEventDuration');
12041        if (!start.isValid()) {
12042            return false;
12043        }
12044        if (forcedAllDay == null) {
12045            forcedAllDay = source.allDayDefault;
12046            if (forcedAllDay == null) {
12047                forcedAllDay = calendar.opt('allDayDefault');
12048            }
12049        }
12050        if (forcedAllDay === true) {
12051            start.stripTime();
12052            if (end) {
12053                end.stripTime();
12054            }
12055        }
12056        else if (forcedAllDay === false) {
12057            if (!start.hasTime()) {
12058                start.time(0);
12059            }
12060            if (end && !end.hasTime()) {
12061                end.time(0);
12062            }
12063        }
12064        if (end && (!end.isValid() || !end.isAfter(start))) {
12065            end = null;
12066        }
12067        if (!end && forceEventDuration) {
12068            end = calendar.getDefaultEventEnd(!start.hasTime(), start);
12069        }
12070        return new EventDateProfile(start, end, calendar);
12071    };
12072    EventDateProfile.isStandardProp = function (propName) {
12073        return propName === 'start' || propName === 'date' || propName === 'end' || propName === 'allDay';
12074    };
12075    EventDateProfile.prototype.isAllDay = function () {
12076        return !(this.start.hasTime() || (this.end && this.end.hasTime()));
12077    };
12078    /*
12079    Needs a Calendar object
12080    */
12081    EventDateProfile.prototype.buildUnzonedRange = function (calendar) {
12082        var startMs = this.start.clone().stripZone().valueOf();
12083        var endMs = this.getEnd(calendar).stripZone().valueOf();
12084        return new UnzonedRange_1.default(startMs, endMs);
12085    };
12086    /*
12087    Needs a Calendar object
12088    */
12089    EventDateProfile.prototype.getEnd = function (calendar) {
12090        return this.end ?
12091            this.end.clone() :
12092            // derive the end from the start and allDay. compute allDay if necessary
12093            calendar.getDefaultEventEnd(this.isAllDay(), this.start);
12094    };
12095    return EventDateProfile;
12096}());
12097exports.default = EventDateProfile;
12098
12099
12100/***/ }),
12101/* 17 */
12102/***/ (function(module, exports, __webpack_require__) {
12103
12104Object.defineProperty(exports, "__esModule", { value: true });
12105var tslib_1 = __webpack_require__(2);
12106var util_1 = __webpack_require__(4);
12107var DragListener_1 = __webpack_require__(59);
12108/* Tracks mouse movements over a component and raises events about which hit the mouse is over.
12109------------------------------------------------------------------------------------------------------------------------
12110options:
12111- subjectEl
12112- subjectCenter
12113*/
12114var HitDragListener = /** @class */ (function (_super) {
12115    tslib_1.__extends(HitDragListener, _super);
12116    function HitDragListener(component, options) {
12117        var _this = _super.call(this, options) || this;
12118        _this.component = component;
12119        return _this;
12120    }
12121    // Called when drag listening starts (but a real drag has not necessarily began).
12122    // ev might be undefined if dragging was started manually.
12123    HitDragListener.prototype.handleInteractionStart = function (ev) {
12124        var subjectEl = this.subjectEl;
12125        var subjectRect;
12126        var origPoint;
12127        var point;
12128        this.component.hitsNeeded();
12129        this.computeScrollBounds(); // for autoscroll
12130        if (ev) {
12131            origPoint = { left: util_1.getEvX(ev), top: util_1.getEvY(ev) };
12132            point = origPoint;
12133            // constrain the point to bounds of the element being dragged
12134            if (subjectEl) {
12135                subjectRect = util_1.getOuterRect(subjectEl); // used for centering as well
12136                point = util_1.constrainPoint(point, subjectRect);
12137            }
12138            this.origHit = this.queryHit(point.left, point.top);
12139            // treat the center of the subject as the collision point?
12140            if (subjectEl && this.options.subjectCenter) {
12141                // only consider the area the subject overlaps the hit. best for large subjects.
12142                // TODO: skip this if hit didn't supply left/right/top/bottom
12143                if (this.origHit) {
12144                    subjectRect = util_1.intersectRects(this.origHit, subjectRect) ||
12145                        subjectRect; // in case there is no intersection
12146                }
12147                point = util_1.getRectCenter(subjectRect);
12148            }
12149            this.coordAdjust = util_1.diffPoints(point, origPoint); // point - origPoint
12150        }
12151        else {
12152            this.origHit = null;
12153            this.coordAdjust = null;
12154        }
12155        // call the super-method. do it after origHit has been computed
12156        _super.prototype.handleInteractionStart.call(this, ev);
12157    };
12158    // Called when the actual drag has started
12159    HitDragListener.prototype.handleDragStart = function (ev) {
12160        var hit;
12161        _super.prototype.handleDragStart.call(this, ev);
12162        // might be different from this.origHit if the min-distance is large
12163        hit = this.queryHit(util_1.getEvX(ev), util_1.getEvY(ev));
12164        // report the initial hit the mouse is over
12165        // especially important if no min-distance and drag starts immediately
12166        if (hit) {
12167            this.handleHitOver(hit);
12168        }
12169    };
12170    // Called when the drag moves
12171    HitDragListener.prototype.handleDrag = function (dx, dy, ev) {
12172        var hit;
12173        _super.prototype.handleDrag.call(this, dx, dy, ev);
12174        hit = this.queryHit(util_1.getEvX(ev), util_1.getEvY(ev));
12175        if (!isHitsEqual(hit, this.hit)) { // a different hit than before?
12176            if (this.hit) {
12177                this.handleHitOut();
12178            }
12179            if (hit) {
12180                this.handleHitOver(hit);
12181            }
12182        }
12183    };
12184    // Called when dragging has been stopped
12185    HitDragListener.prototype.handleDragEnd = function (ev) {
12186        this.handleHitDone();
12187        _super.prototype.handleDragEnd.call(this, ev);
12188    };
12189    // Called when a the mouse has just moved over a new hit
12190    HitDragListener.prototype.handleHitOver = function (hit) {
12191        var isOrig = isHitsEqual(hit, this.origHit);
12192        this.hit = hit;
12193        this.trigger('hitOver', this.hit, isOrig, this.origHit);
12194    };
12195    // Called when the mouse has just moved out of a hit
12196    HitDragListener.prototype.handleHitOut = function () {
12197        if (this.hit) {
12198            this.trigger('hitOut', this.hit);
12199            this.handleHitDone();
12200            this.hit = null;
12201        }
12202    };
12203    // Called after a hitOut. Also called before a dragStop
12204    HitDragListener.prototype.handleHitDone = function () {
12205        if (this.hit) {
12206            this.trigger('hitDone', this.hit);
12207        }
12208    };
12209    // Called when the interaction ends, whether there was a real drag or not
12210    HitDragListener.prototype.handleInteractionEnd = function (ev, isCancelled) {
12211        _super.prototype.handleInteractionEnd.call(this, ev, isCancelled);
12212        this.origHit = null;
12213        this.hit = null;
12214        this.component.hitsNotNeeded();
12215    };
12216    // Called when scrolling has stopped, whether through auto scroll, or the user scrolling
12217    HitDragListener.prototype.handleScrollEnd = function () {
12218        _super.prototype.handleScrollEnd.call(this);
12219        // hits' absolute positions will be in new places after a user's scroll.
12220        // HACK for recomputing.
12221        if (this.isDragging) {
12222            this.component.releaseHits();
12223            this.component.prepareHits();
12224        }
12225    };
12226    // Gets the hit underneath the coordinates for the given mouse event
12227    HitDragListener.prototype.queryHit = function (left, top) {
12228        if (this.coordAdjust) {
12229            left += this.coordAdjust.left;
12230            top += this.coordAdjust.top;
12231        }
12232        return this.component.queryHit(left, top);
12233    };
12234    return HitDragListener;
12235}(DragListener_1.default));
12236exports.default = HitDragListener;
12237// Returns `true` if the hits are identically equal. `false` otherwise. Must be from the same component.
12238// Two null values will be considered equal, as two "out of the component" states are the same.
12239function isHitsEqual(hit0, hit1) {
12240    if (!hit0 && !hit1) {
12241        return true;
12242    }
12243    if (hit0 && hit1) {
12244        return hit0.component === hit1.component &&
12245            isHitPropsWithin(hit0, hit1) &&
12246            isHitPropsWithin(hit1, hit0); // ensures all props are identical
12247    }
12248    return false;
12249}
12250// Returns true if all of subHit's non-standard properties are within superHit
12251function isHitPropsWithin(subHit, superHit) {
12252    for (var propName in subHit) {
12253        if (!/^(component|left|right|top|bottom)$/.test(propName)) {
12254            if (subHit[propName] !== superHit[propName]) {
12255                return false;
12256            }
12257        }
12258    }
12259    return true;
12260}
12261
12262
12263/***/ }),
12264/* 18 */
12265/***/ (function(module, exports, __webpack_require__) {
12266
12267Object.defineProperty(exports, "__esModule", { value: true });
12268exports.version = '3.10.5';
12269// When introducing internal API incompatibilities (where fullcalendar plugins would break),
12270// the minor version of the calendar should be upped (ex: 2.7.2 -> 2.8.0)
12271// and the below integer should be incremented.
12272exports.internalApiVersion = 12;
12273var util_1 = __webpack_require__(4);
12274exports.applyAll = util_1.applyAll;
12275exports.debounce = util_1.debounce;
12276exports.isInt = util_1.isInt;
12277exports.htmlEscape = util_1.htmlEscape;
12278exports.cssToStr = util_1.cssToStr;
12279exports.proxy = util_1.proxy;
12280exports.capitaliseFirstLetter = util_1.capitaliseFirstLetter;
12281exports.getOuterRect = util_1.getOuterRect;
12282exports.getClientRect = util_1.getClientRect;
12283exports.getContentRect = util_1.getContentRect;
12284exports.getScrollbarWidths = util_1.getScrollbarWidths;
12285exports.preventDefault = util_1.preventDefault;
12286exports.parseFieldSpecs = util_1.parseFieldSpecs;
12287exports.compareByFieldSpecs = util_1.compareByFieldSpecs;
12288exports.compareByFieldSpec = util_1.compareByFieldSpec;
12289exports.flexibleCompare = util_1.flexibleCompare;
12290exports.computeGreatestUnit = util_1.computeGreatestUnit;
12291exports.divideRangeByDuration = util_1.divideRangeByDuration;
12292exports.divideDurationByDuration = util_1.divideDurationByDuration;
12293exports.multiplyDuration = util_1.multiplyDuration;
12294exports.durationHasTime = util_1.durationHasTime;
12295exports.log = util_1.log;
12296exports.warn = util_1.warn;
12297exports.removeExact = util_1.removeExact;
12298exports.intersectRects = util_1.intersectRects;
12299exports.allowSelection = util_1.allowSelection;
12300exports.attrsToStr = util_1.attrsToStr;
12301exports.compareNumbers = util_1.compareNumbers;
12302exports.compensateScroll = util_1.compensateScroll;
12303exports.computeDurationGreatestUnit = util_1.computeDurationGreatestUnit;
12304exports.constrainPoint = util_1.constrainPoint;
12305exports.copyOwnProps = util_1.copyOwnProps;
12306exports.diffByUnit = util_1.diffByUnit;
12307exports.diffDay = util_1.diffDay;
12308exports.diffDayTime = util_1.diffDayTime;
12309exports.diffPoints = util_1.diffPoints;
12310exports.disableCursor = util_1.disableCursor;
12311exports.distributeHeight = util_1.distributeHeight;
12312exports.enableCursor = util_1.enableCursor;
12313exports.firstDefined = util_1.firstDefined;
12314exports.getEvIsTouch = util_1.getEvIsTouch;
12315exports.getEvX = util_1.getEvX;
12316exports.getEvY = util_1.getEvY;
12317exports.getRectCenter = util_1.getRectCenter;
12318exports.getScrollParent = util_1.getScrollParent;
12319exports.hasOwnProp = util_1.hasOwnProp;
12320exports.isArraysEqual = util_1.isArraysEqual;
12321exports.isNativeDate = util_1.isNativeDate;
12322exports.isPrimaryMouseButton = util_1.isPrimaryMouseButton;
12323exports.isTimeString = util_1.isTimeString;
12324exports.matchCellWidths = util_1.matchCellWidths;
12325exports.mergeProps = util_1.mergeProps;
12326exports.preventSelection = util_1.preventSelection;
12327exports.removeMatching = util_1.removeMatching;
12328exports.stripHtmlEntities = util_1.stripHtmlEntities;
12329exports.subtractInnerElHeight = util_1.subtractInnerElHeight;
12330exports.uncompensateScroll = util_1.uncompensateScroll;
12331exports.undistributeHeight = util_1.undistributeHeight;
12332exports.dayIDs = util_1.dayIDs;
12333exports.unitsDesc = util_1.unitsDesc;
12334var date_formatting_1 = __webpack_require__(49);
12335exports.formatDate = date_formatting_1.formatDate;
12336exports.formatRange = date_formatting_1.formatRange;
12337exports.queryMostGranularFormatUnit = date_formatting_1.queryMostGranularFormatUnit;
12338var locale_1 = __webpack_require__(32);
12339exports.datepickerLocale = locale_1.datepickerLocale;
12340exports.locale = locale_1.locale;
12341exports.getMomentLocaleData = locale_1.getMomentLocaleData;
12342exports.populateInstanceComputableOptions = locale_1.populateInstanceComputableOptions;
12343var util_2 = __webpack_require__(19);
12344exports.eventDefsToEventInstances = util_2.eventDefsToEventInstances;
12345exports.eventFootprintToComponentFootprint = util_2.eventFootprintToComponentFootprint;
12346exports.eventInstanceToEventRange = util_2.eventInstanceToEventRange;
12347exports.eventInstanceToUnzonedRange = util_2.eventInstanceToUnzonedRange;
12348exports.eventRangeToEventFootprint = util_2.eventRangeToEventFootprint;
12349var moment_ext_1 = __webpack_require__(11);
12350exports.moment = moment_ext_1.default;
12351var EmitterMixin_1 = __webpack_require__(13);
12352exports.EmitterMixin = EmitterMixin_1.default;
12353var ListenerMixin_1 = __webpack_require__(7);
12354exports.ListenerMixin = ListenerMixin_1.default;
12355var Model_1 = __webpack_require__(51);
12356exports.Model = Model_1.default;
12357var Constraints_1 = __webpack_require__(217);
12358exports.Constraints = Constraints_1.default;
12359var DateProfileGenerator_1 = __webpack_require__(55);
12360exports.DateProfileGenerator = DateProfileGenerator_1.default;
12361var UnzonedRange_1 = __webpack_require__(5);
12362exports.UnzonedRange = UnzonedRange_1.default;
12363var ComponentFootprint_1 = __webpack_require__(12);
12364exports.ComponentFootprint = ComponentFootprint_1.default;
12365var BusinessHourGenerator_1 = __webpack_require__(218);
12366exports.BusinessHourGenerator = BusinessHourGenerator_1.default;
12367var EventPeriod_1 = __webpack_require__(219);
12368exports.EventPeriod = EventPeriod_1.default;
12369var EventManager_1 = __webpack_require__(220);
12370exports.EventManager = EventManager_1.default;
12371var EventDef_1 = __webpack_require__(37);
12372exports.EventDef = EventDef_1.default;
12373var EventDefMutation_1 = __webpack_require__(39);
12374exports.EventDefMutation = EventDefMutation_1.default;
12375var EventDefParser_1 = __webpack_require__(36);
12376exports.EventDefParser = EventDefParser_1.default;
12377var EventInstance_1 = __webpack_require__(53);
12378exports.EventInstance = EventInstance_1.default;
12379var EventRange_1 = __webpack_require__(50);
12380exports.EventRange = EventRange_1.default;
12381var RecurringEventDef_1 = __webpack_require__(54);
12382exports.RecurringEventDef = RecurringEventDef_1.default;
12383var SingleEventDef_1 = __webpack_require__(9);
12384exports.SingleEventDef = SingleEventDef_1.default;
12385var EventDefDateMutation_1 = __webpack_require__(40);
12386exports.EventDefDateMutation = EventDefDateMutation_1.default;
12387var EventDateProfile_1 = __webpack_require__(16);
12388exports.EventDateProfile = EventDateProfile_1.default;
12389var EventSourceParser_1 = __webpack_require__(38);
12390exports.EventSourceParser = EventSourceParser_1.default;
12391var EventSource_1 = __webpack_require__(6);
12392exports.EventSource = EventSource_1.default;
12393var ThemeRegistry_1 = __webpack_require__(57);
12394exports.defineThemeSystem = ThemeRegistry_1.defineThemeSystem;
12395exports.getThemeSystemClass = ThemeRegistry_1.getThemeSystemClass;
12396var EventInstanceGroup_1 = __webpack_require__(20);
12397exports.EventInstanceGroup = EventInstanceGroup_1.default;
12398var ArrayEventSource_1 = __webpack_require__(56);
12399exports.ArrayEventSource = ArrayEventSource_1.default;
12400var FuncEventSource_1 = __webpack_require__(223);
12401exports.FuncEventSource = FuncEventSource_1.default;
12402var JsonFeedEventSource_1 = __webpack_require__(224);
12403exports.JsonFeedEventSource = JsonFeedEventSource_1.default;
12404var EventFootprint_1 = __webpack_require__(34);
12405exports.EventFootprint = EventFootprint_1.default;
12406var Class_1 = __webpack_require__(35);
12407exports.Class = Class_1.default;
12408var Mixin_1 = __webpack_require__(15);
12409exports.Mixin = Mixin_1.default;
12410var CoordCache_1 = __webpack_require__(58);
12411exports.CoordCache = CoordCache_1.default;
12412var Iterator_1 = __webpack_require__(225);
12413exports.Iterator = Iterator_1.default;
12414var DragListener_1 = __webpack_require__(59);
12415exports.DragListener = DragListener_1.default;
12416var HitDragListener_1 = __webpack_require__(17);
12417exports.HitDragListener = HitDragListener_1.default;
12418var MouseFollower_1 = __webpack_require__(226);
12419exports.MouseFollower = MouseFollower_1.default;
12420var ParsableModelMixin_1 = __webpack_require__(52);
12421exports.ParsableModelMixin = ParsableModelMixin_1.default;
12422var Popover_1 = __webpack_require__(227);
12423exports.Popover = Popover_1.default;
12424var Promise_1 = __webpack_require__(21);
12425exports.Promise = Promise_1.default;
12426var TaskQueue_1 = __webpack_require__(228);
12427exports.TaskQueue = TaskQueue_1.default;
12428var RenderQueue_1 = __webpack_require__(229);
12429exports.RenderQueue = RenderQueue_1.default;
12430var Scroller_1 = __webpack_require__(41);
12431exports.Scroller = Scroller_1.default;
12432var Theme_1 = __webpack_require__(22);
12433exports.Theme = Theme_1.default;
12434var Component_1 = __webpack_require__(230);
12435exports.Component = Component_1.default;
12436var DateComponent_1 = __webpack_require__(231);
12437exports.DateComponent = DateComponent_1.default;
12438var InteractiveDateComponent_1 = __webpack_require__(42);
12439exports.InteractiveDateComponent = InteractiveDateComponent_1.default;
12440var Calendar_1 = __webpack_require__(232);
12441exports.Calendar = Calendar_1.default;
12442var View_1 = __webpack_require__(43);
12443exports.View = View_1.default;
12444var ViewRegistry_1 = __webpack_require__(24);
12445exports.defineView = ViewRegistry_1.defineView;
12446exports.getViewConfig = ViewRegistry_1.getViewConfig;
12447var DayTableMixin_1 = __webpack_require__(60);
12448exports.DayTableMixin = DayTableMixin_1.default;
12449var BusinessHourRenderer_1 = __webpack_require__(61);
12450exports.BusinessHourRenderer = BusinessHourRenderer_1.default;
12451var EventRenderer_1 = __webpack_require__(44);
12452exports.EventRenderer = EventRenderer_1.default;
12453var FillRenderer_1 = __webpack_require__(62);
12454exports.FillRenderer = FillRenderer_1.default;
12455var HelperRenderer_1 = __webpack_require__(63);
12456exports.HelperRenderer = HelperRenderer_1.default;
12457var ExternalDropping_1 = __webpack_require__(233);
12458exports.ExternalDropping = ExternalDropping_1.default;
12459var EventResizing_1 = __webpack_require__(234);
12460exports.EventResizing = EventResizing_1.default;
12461var EventPointing_1 = __webpack_require__(64);
12462exports.EventPointing = EventPointing_1.default;
12463var EventDragging_1 = __webpack_require__(235);
12464exports.EventDragging = EventDragging_1.default;
12465var DateSelecting_1 = __webpack_require__(236);
12466exports.DateSelecting = DateSelecting_1.default;
12467var DateClicking_1 = __webpack_require__(237);
12468exports.DateClicking = DateClicking_1.default;
12469var Interaction_1 = __webpack_require__(14);
12470exports.Interaction = Interaction_1.default;
12471var StandardInteractionsMixin_1 = __webpack_require__(65);
12472exports.StandardInteractionsMixin = StandardInteractionsMixin_1.default;
12473var AgendaView_1 = __webpack_require__(238);
12474exports.AgendaView = AgendaView_1.default;
12475var TimeGrid_1 = __webpack_require__(239);
12476exports.TimeGrid = TimeGrid_1.default;
12477var TimeGridEventRenderer_1 = __webpack_require__(240);
12478exports.TimeGridEventRenderer = TimeGridEventRenderer_1.default;
12479var TimeGridFillRenderer_1 = __webpack_require__(242);
12480exports.TimeGridFillRenderer = TimeGridFillRenderer_1.default;
12481var TimeGridHelperRenderer_1 = __webpack_require__(241);
12482exports.TimeGridHelperRenderer = TimeGridHelperRenderer_1.default;
12483var DayGrid_1 = __webpack_require__(66);
12484exports.DayGrid = DayGrid_1.default;
12485var DayGridEventRenderer_1 = __webpack_require__(243);
12486exports.DayGridEventRenderer = DayGridEventRenderer_1.default;
12487var DayGridFillRenderer_1 = __webpack_require__(245);
12488exports.DayGridFillRenderer = DayGridFillRenderer_1.default;
12489var DayGridHelperRenderer_1 = __webpack_require__(244);
12490exports.DayGridHelperRenderer = DayGridHelperRenderer_1.default;
12491var BasicView_1 = __webpack_require__(67);
12492exports.BasicView = BasicView_1.default;
12493var BasicViewDateProfileGenerator_1 = __webpack_require__(68);
12494exports.BasicViewDateProfileGenerator = BasicViewDateProfileGenerator_1.default;
12495var MonthView_1 = __webpack_require__(246);
12496exports.MonthView = MonthView_1.default;
12497var MonthViewDateProfileGenerator_1 = __webpack_require__(247);
12498exports.MonthViewDateProfileGenerator = MonthViewDateProfileGenerator_1.default;
12499var ListView_1 = __webpack_require__(248);
12500exports.ListView = ListView_1.default;
12501var ListEventPointing_1 = __webpack_require__(250);
12502exports.ListEventPointing = ListEventPointing_1.default;
12503var ListEventRenderer_1 = __webpack_require__(249);
12504exports.ListEventRenderer = ListEventRenderer_1.default;
12505
12506
12507/***/ }),
12508/* 19 */
12509/***/ (function(module, exports, __webpack_require__) {
12510
12511Object.defineProperty(exports, "__esModule", { value: true });
12512var EventRange_1 = __webpack_require__(50);
12513var EventFootprint_1 = __webpack_require__(34);
12514var ComponentFootprint_1 = __webpack_require__(12);
12515function eventDefsToEventInstances(eventDefs, unzonedRange) {
12516    var eventInstances = [];
12517    var i;
12518    for (i = 0; i < eventDefs.length; i++) {
12519        eventInstances.push.apply(eventInstances, // append
12520        eventDefs[i].buildInstances(unzonedRange));
12521    }
12522    return eventInstances;
12523}
12524exports.eventDefsToEventInstances = eventDefsToEventInstances;
12525function eventInstanceToEventRange(eventInstance) {
12526    return new EventRange_1.default(eventInstance.dateProfile.unzonedRange, eventInstance.def, eventInstance);
12527}
12528exports.eventInstanceToEventRange = eventInstanceToEventRange;
12529function eventRangeToEventFootprint(eventRange) {
12530    return new EventFootprint_1.default(new ComponentFootprint_1.default(eventRange.unzonedRange, eventRange.eventDef.isAllDay()), eventRange.eventDef, eventRange.eventInstance // might not exist
12531    );
12532}
12533exports.eventRangeToEventFootprint = eventRangeToEventFootprint;
12534function eventInstanceToUnzonedRange(eventInstance) {
12535    return eventInstance.dateProfile.unzonedRange;
12536}
12537exports.eventInstanceToUnzonedRange = eventInstanceToUnzonedRange;
12538function eventFootprintToComponentFootprint(eventFootprint) {
12539    return eventFootprint.componentFootprint;
12540}
12541exports.eventFootprintToComponentFootprint = eventFootprintToComponentFootprint;
12542
12543
12544/***/ }),
12545/* 20 */
12546/***/ (function(module, exports, __webpack_require__) {
12547
12548Object.defineProperty(exports, "__esModule", { value: true });
12549var UnzonedRange_1 = __webpack_require__(5);
12550var util_1 = __webpack_require__(19);
12551var EventRange_1 = __webpack_require__(50);
12552/*
12553It's expected that there will be at least one EventInstance,
12554OR that an explicitEventDef is assigned.
12555*/
12556var EventInstanceGroup = /** @class */ (function () {
12557    function EventInstanceGroup(eventInstances) {
12558        this.eventInstances = eventInstances || [];
12559    }
12560    EventInstanceGroup.prototype.getAllEventRanges = function (constraintRange) {
12561        if (constraintRange) {
12562            return this.sliceNormalRenderRanges(constraintRange);
12563        }
12564        else {
12565            return this.eventInstances.map(util_1.eventInstanceToEventRange);
12566        }
12567    };
12568    EventInstanceGroup.prototype.sliceRenderRanges = function (constraintRange) {
12569        if (this.isInverse()) {
12570            return this.sliceInverseRenderRanges(constraintRange);
12571        }
12572        else {
12573            return this.sliceNormalRenderRanges(constraintRange);
12574        }
12575    };
12576    EventInstanceGroup.prototype.sliceNormalRenderRanges = function (constraintRange) {
12577        var eventInstances = this.eventInstances;
12578        var i;
12579        var eventInstance;
12580        var slicedRange;
12581        var slicedEventRanges = [];
12582        for (i = 0; i < eventInstances.length; i++) {
12583            eventInstance = eventInstances[i];
12584            slicedRange = eventInstance.dateProfile.unzonedRange.intersect(constraintRange);
12585            if (slicedRange) {
12586                slicedEventRanges.push(new EventRange_1.default(slicedRange, eventInstance.def, eventInstance));
12587            }
12588        }
12589        return slicedEventRanges;
12590    };
12591    EventInstanceGroup.prototype.sliceInverseRenderRanges = function (constraintRange) {
12592        var unzonedRanges = this.eventInstances.map(util_1.eventInstanceToUnzonedRange);
12593        var ownerDef = this.getEventDef();
12594        unzonedRanges = UnzonedRange_1.default.invertRanges(unzonedRanges, constraintRange);
12595        return unzonedRanges.map(function (unzonedRange) {
12596            return new EventRange_1.default(unzonedRange, ownerDef); // don't give an EventInstance
12597        });
12598    };
12599    EventInstanceGroup.prototype.isInverse = function () {
12600        return this.getEventDef().hasInverseRendering();
12601    };
12602    EventInstanceGroup.prototype.getEventDef = function () {
12603        return this.explicitEventDef || this.eventInstances[0].def;
12604    };
12605    return EventInstanceGroup;
12606}());
12607exports.default = EventInstanceGroup;
12608
12609
12610/***/ }),
12611/* 21 */
12612/***/ (function(module, exports, __webpack_require__) {
12613
12614Object.defineProperty(exports, "__esModule", { value: true });
12615var $ = __webpack_require__(3);
12616var PromiseStub = {
12617    construct: function (executor) {
12618        var deferred = $.Deferred();
12619        var promise = deferred.promise();
12620        if (typeof executor === 'function') {
12621            executor(function (val) {
12622                deferred.resolve(val);
12623                attachImmediatelyResolvingThen(promise, val);
12624            }, function () {
12625                deferred.reject();
12626                attachImmediatelyRejectingThen(promise);
12627            });
12628        }
12629        return promise;
12630    },
12631    resolve: function (val) {
12632        var deferred = $.Deferred().resolve(val);
12633        var promise = deferred.promise();
12634        attachImmediatelyResolvingThen(promise, val);
12635        return promise;
12636    },
12637    reject: function () {
12638        var deferred = $.Deferred().reject();
12639        var promise = deferred.promise();
12640        attachImmediatelyRejectingThen(promise);
12641        return promise;
12642    }
12643};
12644exports.default = PromiseStub;
12645function attachImmediatelyResolvingThen(promise, val) {
12646    promise.then = function (onResolve) {
12647        if (typeof onResolve === 'function') {
12648            return PromiseStub.resolve(onResolve(val));
12649        }
12650        return promise;
12651    };
12652}
12653function attachImmediatelyRejectingThen(promise) {
12654    promise.then = function (onResolve, onReject) {
12655        if (typeof onReject === 'function') {
12656            onReject();
12657        }
12658        return promise;
12659    };
12660}
12661
12662
12663/***/ }),
12664/* 22 */
12665/***/ (function(module, exports, __webpack_require__) {
12666
12667Object.defineProperty(exports, "__esModule", { value: true });
12668var $ = __webpack_require__(3);
12669var Theme = /** @class */ (function () {
12670    function Theme(optionsManager) {
12671        this.optionsManager = optionsManager;
12672        this.processIconOverride();
12673    }
12674    Theme.prototype.processIconOverride = function () {
12675        if (this.iconOverrideOption) {
12676            this.setIconOverride(this.optionsManager.get(this.iconOverrideOption));
12677        }
12678    };
12679    Theme.prototype.setIconOverride = function (iconOverrideHash) {
12680        var iconClassesCopy;
12681        var buttonName;
12682        if ($.isPlainObject(iconOverrideHash)) {
12683            iconClassesCopy = $.extend({}, this.iconClasses);
12684            for (buttonName in iconOverrideHash) {
12685                iconClassesCopy[buttonName] = this.applyIconOverridePrefix(iconOverrideHash[buttonName]);
12686            }
12687            this.iconClasses = iconClassesCopy;
12688        }
12689        else if (iconOverrideHash === false) {
12690            this.iconClasses = {};
12691        }
12692    };
12693    Theme.prototype.applyIconOverridePrefix = function (className) {
12694        var prefix = this.iconOverridePrefix;
12695        if (prefix && className.indexOf(prefix) !== 0) { // if not already present
12696            className = prefix + className;
12697        }
12698        return className;
12699    };
12700    Theme.prototype.getClass = function (key) {
12701        return this.classes[key] || '';
12702    };
12703    Theme.prototype.getIconClass = function (buttonName) {
12704        var className = this.iconClasses[buttonName];
12705        if (className) {
12706            return this.baseIconClass + ' ' + className;
12707        }
12708        return '';
12709    };
12710    Theme.prototype.getCustomButtonIconClass = function (customButtonProps) {
12711        var className;
12712        if (this.iconOverrideCustomButtonOption) {
12713            className = customButtonProps[this.iconOverrideCustomButtonOption];
12714            if (className) {
12715                return this.baseIconClass + ' ' + this.applyIconOverridePrefix(className);
12716            }
12717        }
12718        return '';
12719    };
12720    return Theme;
12721}());
12722exports.default = Theme;
12723Theme.prototype.classes = {};
12724Theme.prototype.iconClasses = {};
12725Theme.prototype.baseIconClass = '';
12726Theme.prototype.iconOverridePrefix = '';
12727
12728
12729/***/ }),
12730/* 23 */
12731/***/ (function(module, exports, __webpack_require__) {
12732
12733Object.defineProperty(exports, "__esModule", { value: true });
12734var $ = __webpack_require__(3);
12735var exportHooks = __webpack_require__(18);
12736var EmitterMixin_1 = __webpack_require__(13);
12737var ListenerMixin_1 = __webpack_require__(7);
12738exportHooks.touchMouseIgnoreWait = 500;
12739var globalEmitter = null;
12740var neededCount = 0;
12741/*
12742Listens to document and window-level user-interaction events, like touch events and mouse events,
12743and fires these events as-is to whoever is observing a GlobalEmitter.
12744Best when used as a singleton via GlobalEmitter.get()
12745
12746Normalizes mouse/touch events. For examples:
12747- ignores the the simulated mouse events that happen after a quick tap: mousemove+mousedown+mouseup+click
12748- compensates for various buggy scenarios where a touchend does not fire
12749*/
12750var GlobalEmitter = /** @class */ (function () {
12751    function GlobalEmitter() {
12752        this.isTouching = false;
12753        this.mouseIgnoreDepth = 0;
12754    }
12755    // gets the singleton
12756    GlobalEmitter.get = function () {
12757        if (!globalEmitter) {
12758            globalEmitter = new GlobalEmitter();
12759            globalEmitter.bind();
12760        }
12761        return globalEmitter;
12762    };
12763    // called when an object knows it will need a GlobalEmitter in the near future.
12764    GlobalEmitter.needed = function () {
12765        GlobalEmitter.get(); // ensures globalEmitter
12766        neededCount++;
12767    };
12768    // called when the object that originally called needed() doesn't need a GlobalEmitter anymore.
12769    GlobalEmitter.unneeded = function () {
12770        neededCount--;
12771        if (!neededCount) { // nobody else needs it
12772            globalEmitter.unbind();
12773            globalEmitter = null;
12774        }
12775    };
12776    GlobalEmitter.prototype.bind = function () {
12777        var _this = this;
12778        this.listenTo($(document), {
12779            touchstart: this.handleTouchStart,
12780            touchcancel: this.handleTouchCancel,
12781            touchend: this.handleTouchEnd,
12782            mousedown: this.handleMouseDown,
12783            mousemove: this.handleMouseMove,
12784            mouseup: this.handleMouseUp,
12785            click: this.handleClick,
12786            selectstart: this.handleSelectStart,
12787            contextmenu: this.handleContextMenu
12788        });
12789        // because we need to call preventDefault
12790        // because https://www.chromestatus.com/features/5093566007214080
12791        // TODO: investigate performance because this is a global handler
12792        window.addEventListener('touchmove', this.handleTouchMoveProxy = function (ev) {
12793            _this.handleTouchMove($.Event(ev));
12794        }, { passive: false } // allows preventDefault()
12795        );
12796        // attach a handler to get called when ANY scroll action happens on the page.
12797        // this was impossible to do with normal on/off because 'scroll' doesn't bubble.
12798        // http://stackoverflow.com/a/32954565/96342
12799        window.addEventListener('scroll', this.handleScrollProxy = function (ev) {
12800            _this.handleScroll($.Event(ev));
12801        }, true // useCapture
12802        );
12803    };
12804    GlobalEmitter.prototype.unbind = function () {
12805        this.stopListeningTo($(document));
12806        window.removeEventListener('touchmove', this.handleTouchMoveProxy, { passive: false } // use same options as addEventListener
12807        );
12808        window.removeEventListener('scroll', this.handleScrollProxy, true // useCapture
12809        );
12810    };
12811    // Touch Handlers
12812    // -----------------------------------------------------------------------------------------------------------------
12813    GlobalEmitter.prototype.handleTouchStart = function (ev) {
12814        // if a previous touch interaction never ended with a touchend, then implicitly end it,
12815        // but since a new touch interaction is about to begin, don't start the mouse ignore period.
12816        this.stopTouch(ev, true); // skipMouseIgnore=true
12817        this.isTouching = true;
12818        this.trigger('touchstart', ev);
12819    };
12820    GlobalEmitter.prototype.handleTouchMove = function (ev) {
12821        if (this.isTouching) {
12822            this.trigger('touchmove', ev);
12823        }
12824    };
12825    GlobalEmitter.prototype.handleTouchCancel = function (ev) {
12826        if (this.isTouching) {
12827            this.trigger('touchcancel', ev);
12828            // Have touchcancel fire an artificial touchend. That way, handlers won't need to listen to both.
12829            // If touchend fires later, it won't have any effect b/c isTouching will be false.
12830            this.stopTouch(ev);
12831        }
12832    };
12833    GlobalEmitter.prototype.handleTouchEnd = function (ev) {
12834        this.stopTouch(ev);
12835    };
12836    // Mouse Handlers
12837    // -----------------------------------------------------------------------------------------------------------------
12838    GlobalEmitter.prototype.handleMouseDown = function (ev) {
12839        if (!this.shouldIgnoreMouse()) {
12840            this.trigger('mousedown', ev);
12841        }
12842    };
12843    GlobalEmitter.prototype.handleMouseMove = function (ev) {
12844        if (!this.shouldIgnoreMouse()) {
12845            this.trigger('mousemove', ev);
12846        }
12847    };
12848    GlobalEmitter.prototype.handleMouseUp = function (ev) {
12849        if (!this.shouldIgnoreMouse()) {
12850            this.trigger('mouseup', ev);
12851        }
12852    };
12853    GlobalEmitter.prototype.handleClick = function (ev) {
12854        if (!this.shouldIgnoreMouse()) {
12855            this.trigger('click', ev);
12856        }
12857    };
12858    // Misc Handlers
12859    // -----------------------------------------------------------------------------------------------------------------
12860    GlobalEmitter.prototype.handleSelectStart = function (ev) {
12861        this.trigger('selectstart', ev);
12862    };
12863    GlobalEmitter.prototype.handleContextMenu = function (ev) {
12864        this.trigger('contextmenu', ev);
12865    };
12866    GlobalEmitter.prototype.handleScroll = function (ev) {
12867        this.trigger('scroll', ev);
12868    };
12869    // Utils
12870    // -----------------------------------------------------------------------------------------------------------------
12871    GlobalEmitter.prototype.stopTouch = function (ev, skipMouseIgnore) {
12872        if (skipMouseIgnore === void 0) { skipMouseIgnore = false; }
12873        if (this.isTouching) {
12874            this.isTouching = false;
12875            this.trigger('touchend', ev);
12876            if (!skipMouseIgnore) {
12877                this.startTouchMouseIgnore();
12878            }
12879        }
12880    };
12881    GlobalEmitter.prototype.startTouchMouseIgnore = function () {
12882        var _this = this;
12883        var wait = exportHooks.touchMouseIgnoreWait;
12884        if (wait) {
12885            this.mouseIgnoreDepth++;
12886            setTimeout(function () {
12887                _this.mouseIgnoreDepth--;
12888            }, wait);
12889        }
12890    };
12891    GlobalEmitter.prototype.shouldIgnoreMouse = function () {
12892        return this.isTouching || Boolean(this.mouseIgnoreDepth);
12893    };
12894    return GlobalEmitter;
12895}());
12896exports.default = GlobalEmitter;
12897ListenerMixin_1.default.mixInto(GlobalEmitter);
12898EmitterMixin_1.default.mixInto(GlobalEmitter);
12899
12900
12901/***/ }),
12902/* 24 */
12903/***/ (function(module, exports, __webpack_require__) {
12904
12905Object.defineProperty(exports, "__esModule", { value: true });
12906var exportHooks = __webpack_require__(18);
12907exports.viewHash = {};
12908exportHooks.views = exports.viewHash;
12909function defineView(viewName, viewConfig) {
12910    exports.viewHash[viewName] = viewConfig;
12911}
12912exports.defineView = defineView;
12913function getViewConfig(viewName) {
12914    return exports.viewHash[viewName];
12915}
12916exports.getViewConfig = getViewConfig;
12917
12918
12919/***/ }),
12920/* 25 */,
12921/* 26 */,
12922/* 27 */,
12923/* 28 */,
12924/* 29 */,
12925/* 30 */,
12926/* 31 */,
12927/* 32 */
12928/***/ (function(module, exports, __webpack_require__) {
12929
12930Object.defineProperty(exports, "__esModule", { value: true });
12931var $ = __webpack_require__(3);
12932var moment = __webpack_require__(0);
12933var exportHooks = __webpack_require__(18);
12934var options_1 = __webpack_require__(33);
12935var util_1 = __webpack_require__(4);
12936exports.localeOptionHash = {};
12937exportHooks.locales = exports.localeOptionHash;
12938// NOTE: can't guarantee any of these computations will run because not every locale has datepicker
12939// configs, so make sure there are English fallbacks for these in the defaults file.
12940var dpComputableOptions = {
12941    buttonText: function (dpOptions) {
12942        return {
12943            // the translations sometimes wrongly contain HTML entities
12944            prev: util_1.stripHtmlEntities(dpOptions.prevText),
12945            next: util_1.stripHtmlEntities(dpOptions.nextText),
12946            today: util_1.stripHtmlEntities(dpOptions.currentText)
12947        };
12948    },
12949    // Produces format strings like "MMMM YYYY" -> "September 2014"
12950    monthYearFormat: function (dpOptions) {
12951        return dpOptions.showMonthAfterYear ?
12952            'YYYY[' + dpOptions.yearSuffix + '] MMMM' :
12953            'MMMM YYYY[' + dpOptions.yearSuffix + ']';
12954    }
12955};
12956var momComputableOptions = {
12957    // Produces format strings like "ddd M/D" -> "Fri 9/15"
12958    dayOfMonthFormat: function (momOptions, fcOptions) {
12959        var format = momOptions.longDateFormat('l'); // for the format like "M/D/YYYY"
12960        // strip the year off the edge, as well as other misc non-whitespace chars
12961        format = format.replace(/^Y+[^\w\s]*|[^\w\s]*Y+$/g, '');
12962        if (fcOptions.isRTL) {
12963            format += ' ddd'; // for RTL, add day-of-week to end
12964        }
12965        else {
12966            format = 'ddd ' + format; // for LTR, add day-of-week to beginning
12967        }
12968        return format;
12969    },
12970    // Produces format strings like "h:mma" -> "6:00pm"
12971    mediumTimeFormat: function (momOptions) {
12972        return momOptions.longDateFormat('LT')
12973            .replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand
12974    },
12975    // Produces format strings like "h(:mm)a" -> "6pm" / "6:30pm"
12976    smallTimeFormat: function (momOptions) {
12977        return momOptions.longDateFormat('LT')
12978            .replace(':mm', '(:mm)')
12979            .replace(/(\Wmm)$/, '($1)') // like above, but for foreign locales
12980            .replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand
12981    },
12982    // Produces format strings like "h(:mm)t" -> "6p" / "6:30p"
12983    extraSmallTimeFormat: function (momOptions) {
12984        return momOptions.longDateFormat('LT')
12985            .replace(':mm', '(:mm)')
12986            .replace(/(\Wmm)$/, '($1)') // like above, but for foreign locales
12987            .replace(/\s*a$/i, 't'); // convert to AM/PM/am/pm to lowercase one-letter. remove any spaces beforehand
12988    },
12989    // Produces format strings like "ha" / "H" -> "6pm" / "18"
12990    hourFormat: function (momOptions) {
12991        return momOptions.longDateFormat('LT')
12992            .replace(':mm', '')
12993            .replace(/(\Wmm)$/, '') // like above, but for foreign locales
12994            .replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand
12995    },
12996    // Produces format strings like "h:mm" -> "6:30" (with no AM/PM)
12997    noMeridiemTimeFormat: function (momOptions) {
12998        return momOptions.longDateFormat('LT')
12999            .replace(/\s*a$/i, ''); // remove trailing AM/PM
13000    }
13001};
13002// options that should be computed off live calendar options (considers override options)
13003// TODO: best place for this? related to locale?
13004// TODO: flipping text based on isRTL is a bad idea because the CSS `direction` might want to handle it
13005var instanceComputableOptions = {
13006    // Produces format strings for results like "Mo 16"
13007    smallDayDateFormat: function (options) {
13008        return options.isRTL ?
13009            'D dd' :
13010            'dd D';
13011    },
13012    // Produces format strings for results like "Wk 5"
13013    weekFormat: function (options) {
13014        return options.isRTL ?
13015            'w[ ' + options.weekNumberTitle + ']' :
13016            '[' + options.weekNumberTitle + ' ]w';
13017    },
13018    // Produces format strings for results like "Wk5"
13019    smallWeekFormat: function (options) {
13020        return options.isRTL ?
13021            'w[' + options.weekNumberTitle + ']' :
13022            '[' + options.weekNumberTitle + ']w';
13023    }
13024};
13025// TODO: make these computable properties in optionsManager
13026function populateInstanceComputableOptions(options) {
13027    $.each(instanceComputableOptions, function (name, func) {
13028        if (options[name] == null) {
13029            options[name] = func(options);
13030        }
13031    });
13032}
13033exports.populateInstanceComputableOptions = populateInstanceComputableOptions;
13034// Initialize jQuery UI datepicker translations while using some of the translations
13035// Will set this as the default locales for datepicker.
13036function datepickerLocale(localeCode, dpLocaleCode, dpOptions) {
13037    // get the FullCalendar internal option hash for this locale. create if necessary
13038    var fcOptions = exports.localeOptionHash[localeCode] || (exports.localeOptionHash[localeCode] = {});
13039    // transfer some simple options from datepicker to fc
13040    fcOptions.isRTL = dpOptions.isRTL;
13041    fcOptions.weekNumberTitle = dpOptions.weekHeader;
13042    // compute some more complex options from datepicker
13043    $.each(dpComputableOptions, function (name, func) {
13044        fcOptions[name] = func(dpOptions);
13045    });
13046    var jqDatePicker = $.datepicker;
13047    // is jQuery UI Datepicker is on the page?
13048    if (jqDatePicker) {
13049        // Register the locale data.
13050        // FullCalendar and MomentJS use locale codes like "pt-br" but Datepicker
13051        // does it like "pt-BR" or if it doesn't have the locale, maybe just "pt".
13052        // Make an alias so the locale can be referenced either way.
13053        jqDatePicker.regional[dpLocaleCode] =
13054            jqDatePicker.regional[localeCode] = // alias
13055                dpOptions;
13056        // Alias 'en' to the default locale data. Do this every time.
13057        jqDatePicker.regional.en = jqDatePicker.regional[''];
13058        // Set as Datepicker's global defaults.
13059        jqDatePicker.setDefaults(dpOptions);
13060    }
13061}
13062exports.datepickerLocale = datepickerLocale;
13063// Sets FullCalendar-specific translations. Will set the locales as the global default.
13064function locale(localeCode, newFcOptions) {
13065    var fcOptions;
13066    var momOptions;
13067    // get the FullCalendar internal option hash for this locale. create if necessary
13068    fcOptions = exports.localeOptionHash[localeCode] || (exports.localeOptionHash[localeCode] = {});
13069    // provided new options for this locales? merge them in
13070    if (newFcOptions) {
13071        fcOptions = exports.localeOptionHash[localeCode] = options_1.mergeOptions([fcOptions, newFcOptions]);
13072    }
13073    // compute locale options that weren't defined.
13074    // always do this. newFcOptions can be undefined when initializing from i18n file,
13075    // so no way to tell if this is an initialization or a default-setting.
13076    momOptions = getMomentLocaleData(localeCode); // will fall back to en
13077    $.each(momComputableOptions, function (name, func) {
13078        if (fcOptions[name] == null) {
13079            fcOptions[name] = (func)(momOptions, fcOptions);
13080        }
13081    });
13082    // set it as the default locale for FullCalendar
13083    options_1.globalDefaults.locale = localeCode;
13084}
13085exports.locale = locale;
13086// Returns moment's internal locale data. If doesn't exist, returns English.
13087function getMomentLocaleData(localeCode) {
13088    return moment.localeData(localeCode) || moment.localeData('en');
13089}
13090exports.getMomentLocaleData = getMomentLocaleData;
13091// Initialize English by forcing computation of moment-derived options.
13092// Also, sets it as the default.
13093locale('en', options_1.englishDefaults);
13094
13095
13096/***/ }),
13097/* 33 */
13098/***/ (function(module, exports, __webpack_require__) {
13099
13100Object.defineProperty(exports, "__esModule", { value: true });
13101var util_1 = __webpack_require__(4);
13102exports.globalDefaults = {
13103    titleRangeSeparator: ' \u2013 ',
13104    monthYearFormat: 'MMMM YYYY',
13105    defaultTimedEventDuration: '02:00:00',
13106    defaultAllDayEventDuration: { days: 1 },
13107    forceEventDuration: false,
13108    nextDayThreshold: '09:00:00',
13109    // display
13110    columnHeader: true,
13111    defaultView: 'month',
13112    aspectRatio: 1.35,
13113    header: {
13114        left: 'title',
13115        center: '',
13116        right: 'today prev,next'
13117    },
13118    weekends: true,
13119    weekNumbers: false,
13120    weekNumberTitle: 'W',
13121    weekNumberCalculation: 'local',
13122    // editable: false,
13123    // nowIndicator: false,
13124    scrollTime: '06:00:00',
13125    minTime: '00:00:00',
13126    maxTime: '24:00:00',
13127    showNonCurrentDates: true,
13128    // event ajax
13129    lazyFetching: true,
13130    startParam: 'start',
13131    endParam: 'end',
13132    timezoneParam: 'timezone',
13133    timezone: false,
13134    // allDayDefault: undefined,
13135    // locale
13136    locale: null,
13137    isRTL: false,
13138    buttonText: {
13139        prev: 'prev',
13140        next: 'next',
13141        prevYear: 'prev year',
13142        nextYear: 'next year',
13143        year: 'year',
13144        today: 'today',
13145        month: 'month',
13146        week: 'week',
13147        day: 'day'
13148    },
13149    // buttonIcons: null,
13150    allDayText: 'all-day',
13151    // allows setting a min-height to the event segment to prevent short events overlapping each other
13152    agendaEventMinHeight: 0,
13153    // jquery-ui theming
13154    theme: false,
13155    // themeButtonIcons: null,
13156    // eventResizableFromStart: false,
13157    dragOpacity: .75,
13158    dragRevertDuration: 500,
13159    dragScroll: true,
13160    // selectable: false,
13161    unselectAuto: true,
13162    // selectMinDistance: 0,
13163    dropAccept: '*',
13164    eventOrder: 'title',
13165    // eventRenderWait: null,
13166    eventLimit: false,
13167    eventLimitText: 'more',
13168    eventLimitClick: 'popover',
13169    dayPopoverFormat: 'LL',
13170    handleWindowResize: true,
13171    windowResizeDelay: 100,
13172    longPressDelay: 1000
13173};
13174exports.englishDefaults = {
13175    dayPopoverFormat: 'dddd, MMMM D'
13176};
13177exports.rtlDefaults = {
13178    header: {
13179        left: 'next,prev today',
13180        center: '',
13181        right: 'title'
13182    },
13183    buttonIcons: {
13184        prev: 'right-single-arrow',
13185        next: 'left-single-arrow',
13186        prevYear: 'right-double-arrow',
13187        nextYear: 'left-double-arrow'
13188    },
13189    themeButtonIcons: {
13190        prev: 'circle-triangle-e',
13191        next: 'circle-triangle-w',
13192        nextYear: 'seek-prev',
13193        prevYear: 'seek-next'
13194    }
13195};
13196var complexOptions = [
13197    'header',
13198    'footer',
13199    'buttonText',
13200    'buttonIcons',
13201    'themeButtonIcons'
13202];
13203// Merges an array of option objects into a single object
13204function mergeOptions(optionObjs) {
13205    return util_1.mergeProps(optionObjs, complexOptions);
13206}
13207exports.mergeOptions = mergeOptions;
13208
13209
13210/***/ }),
13211/* 34 */
13212/***/ (function(module, exports) {
13213
13214Object.defineProperty(exports, "__esModule", { value: true });
13215var EventFootprint = /** @class */ (function () {
13216    function EventFootprint(componentFootprint, eventDef, eventInstance) {
13217        this.componentFootprint = componentFootprint;
13218        this.eventDef = eventDef;
13219        if (eventInstance) {
13220            this.eventInstance = eventInstance;
13221        }
13222    }
13223    EventFootprint.prototype.getEventLegacy = function () {
13224        return (this.eventInstance || this.eventDef).toLegacy();
13225    };
13226    return EventFootprint;
13227}());
13228exports.default = EventFootprint;
13229
13230
13231/***/ }),
13232/* 35 */
13233/***/ (function(module, exports, __webpack_require__) {
13234
13235Object.defineProperty(exports, "__esModule", { value: true });
13236var tslib_1 = __webpack_require__(2);
13237var util_1 = __webpack_require__(4);
13238// Class that all other classes will inherit from
13239var Class = /** @class */ (function () {
13240    function Class() {
13241    }
13242    // Called on a class to create a subclass.
13243    // LIMITATION: cannot provide a constructor!
13244    Class.extend = function (members) {
13245        var SubClass = /** @class */ (function (_super) {
13246            tslib_1.__extends(SubClass, _super);
13247            function SubClass() {
13248                return _super !== null && _super.apply(this, arguments) || this;
13249            }
13250            return SubClass;
13251        }(this));
13252        util_1.copyOwnProps(members, SubClass.prototype);
13253        return SubClass;
13254    };
13255    // Adds new member variables/methods to the class's prototype.
13256    // Can be called with another class, or a plain object hash containing new members.
13257    Class.mixin = function (members) {
13258        util_1.copyOwnProps(members, this.prototype);
13259    };
13260    return Class;
13261}());
13262exports.default = Class;
13263
13264
13265/***/ }),
13266/* 36 */
13267/***/ (function(module, exports, __webpack_require__) {
13268
13269Object.defineProperty(exports, "__esModule", { value: true });
13270var moment = __webpack_require__(0);
13271var util_1 = __webpack_require__(4);
13272var SingleEventDef_1 = __webpack_require__(9);
13273var RecurringEventDef_1 = __webpack_require__(54);
13274exports.default = {
13275    parse: function (eventInput, source) {
13276        if (util_1.isTimeString(eventInput.start) || moment.isDuration(eventInput.start) ||
13277            util_1.isTimeString(eventInput.end) || moment.isDuration(eventInput.end)) {
13278            return RecurringEventDef_1.default.parse(eventInput, source);
13279        }
13280        else {
13281            return SingleEventDef_1.default.parse(eventInput, source);
13282        }
13283    }
13284};
13285
13286
13287/***/ }),
13288/* 37 */
13289/***/ (function(module, exports, __webpack_require__) {
13290
13291Object.defineProperty(exports, "__esModule", { value: true });
13292var $ = __webpack_require__(3);
13293var ParsableModelMixin_1 = __webpack_require__(52);
13294var EventDef = /** @class */ (function () {
13295    function EventDef(source) {
13296        this.source = source;
13297        this.className = [];
13298        this.miscProps = {};
13299    }
13300    EventDef.parse = function (rawInput, source) {
13301        var def = new this(source);
13302        if (def.applyProps(rawInput)) {
13303            return def;
13304        }
13305        return false;
13306    };
13307    EventDef.normalizeId = function (id) {
13308        return String(id);
13309    };
13310    EventDef.generateId = function () {
13311        return '_fc' + (EventDef.uuid++);
13312    };
13313    EventDef.prototype.clone = function () {
13314        var copy = new this.constructor(this.source);
13315        copy.id = this.id;
13316        copy.rawId = this.rawId;
13317        copy.uid = this.uid; // not really unique anymore :(
13318        EventDef.copyVerbatimStandardProps(this, copy);
13319        copy.className = this.className.slice(); // copy
13320        copy.miscProps = $.extend({}, this.miscProps);
13321        return copy;
13322    };
13323    EventDef.prototype.hasInverseRendering = function () {
13324        return this.getRendering() === 'inverse-background';
13325    };
13326    EventDef.prototype.hasBgRendering = function () {
13327        var rendering = this.getRendering();
13328        return rendering === 'inverse-background' || rendering === 'background';
13329    };
13330    EventDef.prototype.getRendering = function () {
13331        if (this.rendering != null) {
13332            return this.rendering;
13333        }
13334        return this.source.rendering;
13335    };
13336    EventDef.prototype.getConstraint = function () {
13337        if (this.constraint != null) {
13338            return this.constraint;
13339        }
13340        if (this.source.constraint != null) {
13341            return this.source.constraint;
13342        }
13343        return this.source.calendar.opt('eventConstraint'); // what about View option?
13344    };
13345    EventDef.prototype.getOverlap = function () {
13346        if (this.overlap != null) {
13347            return this.overlap;
13348        }
13349        if (this.source.overlap != null) {
13350            return this.source.overlap;
13351        }
13352        return this.source.calendar.opt('eventOverlap'); // what about View option?
13353    };
13354    EventDef.prototype.isStartExplicitlyEditable = function () {
13355        if (this.startEditable != null) {
13356            return this.startEditable;
13357        }
13358        return this.source.startEditable;
13359    };
13360    EventDef.prototype.isDurationExplicitlyEditable = function () {
13361        if (this.durationEditable != null) {
13362            return this.durationEditable;
13363        }
13364        return this.source.durationEditable;
13365    };
13366    EventDef.prototype.isExplicitlyEditable = function () {
13367        if (this.editable != null) {
13368            return this.editable;
13369        }
13370        return this.source.editable;
13371    };
13372    EventDef.prototype.toLegacy = function () {
13373        var obj = $.extend({}, this.miscProps);
13374        obj._id = this.uid;
13375        obj.source = this.source;
13376        obj.className = this.className.slice(); // copy
13377        obj.allDay = this.isAllDay();
13378        if (this.rawId != null) {
13379            obj.id = this.rawId;
13380        }
13381        EventDef.copyVerbatimStandardProps(this, obj);
13382        return obj;
13383    };
13384    EventDef.prototype.applyManualStandardProps = function (rawProps) {
13385        if (rawProps.id != null) {
13386            this.id = EventDef.normalizeId((this.rawId = rawProps.id));
13387        }
13388        else {
13389            this.id = EventDef.generateId();
13390        }
13391        if (rawProps._id != null) { // accept this prop, even tho somewhat internal
13392            this.uid = String(rawProps._id);
13393        }
13394        else {
13395            this.uid = EventDef.generateId();
13396        }
13397        // TODO: converge with EventSource
13398        if ($.isArray(rawProps.className)) {
13399            this.className = rawProps.className;
13400        }
13401        if (typeof rawProps.className === 'string') {
13402            this.className = rawProps.className.split(/\s+/);
13403        }
13404        return true;
13405    };
13406    EventDef.prototype.applyMiscProps = function (rawProps) {
13407        $.extend(this.miscProps, rawProps);
13408    };
13409    EventDef.uuid = 0;
13410    EventDef.defineStandardProps = ParsableModelMixin_1.default.defineStandardProps;
13411    EventDef.copyVerbatimStandardProps = ParsableModelMixin_1.default.copyVerbatimStandardProps;
13412    return EventDef;
13413}());
13414exports.default = EventDef;
13415ParsableModelMixin_1.default.mixInto(EventDef);
13416EventDef.defineStandardProps({
13417    // not automatically assigned (`false`)
13418    _id: false,
13419    id: false,
13420    className: false,
13421    source: false,
13422    // automatically assigned (`true`)
13423    title: true,
13424    url: true,
13425    rendering: true,
13426    constraint: true,
13427    overlap: true,
13428    editable: true,
13429    startEditable: true,
13430    durationEditable: true,
13431    color: true,
13432    backgroundColor: true,
13433    borderColor: true,
13434    textColor: true
13435});
13436
13437
13438/***/ }),
13439/* 38 */
13440/***/ (function(module, exports) {
13441
13442Object.defineProperty(exports, "__esModule", { value: true });
13443exports.default = {
13444    sourceClasses: [],
13445    registerClass: function (EventSourceClass) {
13446        this.sourceClasses.unshift(EventSourceClass); // give highest priority
13447    },
13448    parse: function (rawInput, calendar) {
13449        var sourceClasses = this.sourceClasses;
13450        var i;
13451        var eventSource;
13452        for (i = 0; i < sourceClasses.length; i++) {
13453            eventSource = sourceClasses[i].parse(rawInput, calendar);
13454            if (eventSource) {
13455                return eventSource;
13456            }
13457        }
13458    }
13459};
13460
13461
13462/***/ }),
13463/* 39 */
13464/***/ (function(module, exports, __webpack_require__) {
13465
13466Object.defineProperty(exports, "__esModule", { value: true });
13467var util_1 = __webpack_require__(4);
13468var EventDateProfile_1 = __webpack_require__(16);
13469var EventDef_1 = __webpack_require__(37);
13470var EventDefDateMutation_1 = __webpack_require__(40);
13471var SingleEventDef_1 = __webpack_require__(9);
13472var EventDefMutation = /** @class */ (function () {
13473    function EventDefMutation() {
13474    }
13475    EventDefMutation.createFromRawProps = function (eventInstance, rawProps, largeUnit) {
13476        var eventDef = eventInstance.def;
13477        var dateProps = {};
13478        var standardProps = {};
13479        var miscProps = {};
13480        var verbatimStandardProps = {};
13481        var eventDefId = null;
13482        var className = null;
13483        var propName;
13484        var dateProfile;
13485        var dateMutation;
13486        var defMutation;
13487        for (propName in rawProps) {
13488            if (EventDateProfile_1.default.isStandardProp(propName)) {
13489                dateProps[propName] = rawProps[propName];
13490            }
13491            else if (eventDef.isStandardProp(propName)) {
13492                standardProps[propName] = rawProps[propName];
13493            }
13494            else if (eventDef.miscProps[propName] !== rawProps[propName]) { // only if changed
13495                miscProps[propName] = rawProps[propName];
13496            }
13497        }
13498        dateProfile = EventDateProfile_1.default.parse(dateProps, eventDef.source);
13499        if (dateProfile) { // no failure?
13500            dateMutation = EventDefDateMutation_1.default.createFromDiff(eventInstance.dateProfile, dateProfile, largeUnit);
13501        }
13502        if (standardProps.id !== eventDef.id) {
13503            eventDefId = standardProps.id; // only apply if there's a change
13504        }
13505        if (!util_1.isArraysEqual(standardProps.className, eventDef.className)) {
13506            className = standardProps.className; // only apply if there's a change
13507        }
13508        EventDef_1.default.copyVerbatimStandardProps(standardProps, // src
13509        verbatimStandardProps // dest
13510        );
13511        defMutation = new EventDefMutation();
13512        defMutation.eventDefId = eventDefId;
13513        defMutation.className = className;
13514        defMutation.verbatimStandardProps = verbatimStandardProps;
13515        defMutation.miscProps = miscProps;
13516        if (dateMutation) {
13517            defMutation.dateMutation = dateMutation;
13518        }
13519        return defMutation;
13520    };
13521    /*
13522    eventDef assumed to be a SingleEventDef.
13523    returns an undo function.
13524    */
13525    EventDefMutation.prototype.mutateSingle = function (eventDef) {
13526        var origDateProfile;
13527        if (this.dateMutation) {
13528            origDateProfile = eventDef.dateProfile;
13529            eventDef.dateProfile = this.dateMutation.buildNewDateProfile(origDateProfile, eventDef.source.calendar);
13530        }
13531        // can't undo
13532        // TODO: more DRY with EventDef::applyManualStandardProps
13533        if (this.eventDefId != null) {
13534            eventDef.id = EventDef_1.default.normalizeId((eventDef.rawId = this.eventDefId));
13535        }
13536        // can't undo
13537        // TODO: more DRY with EventDef::applyManualStandardProps
13538        if (this.className) {
13539            eventDef.className = this.className;
13540        }
13541        // can't undo
13542        if (this.verbatimStandardProps) {
13543            SingleEventDef_1.default.copyVerbatimStandardProps(this.verbatimStandardProps, // src
13544            eventDef // dest
13545            );
13546        }
13547        // can't undo
13548        if (this.miscProps) {
13549            eventDef.applyMiscProps(this.miscProps);
13550        }
13551        if (origDateProfile) {
13552            return function () {
13553                eventDef.dateProfile = origDateProfile;
13554            };
13555        }
13556        else {
13557            return function () { };
13558        }
13559    };
13560    EventDefMutation.prototype.setDateMutation = function (dateMutation) {
13561        if (dateMutation && !dateMutation.isEmpty()) {
13562            this.dateMutation = dateMutation;
13563        }
13564        else {
13565            this.dateMutation = null;
13566        }
13567    };
13568    EventDefMutation.prototype.isEmpty = function () {
13569        return !this.dateMutation;
13570    };
13571    return EventDefMutation;
13572}());
13573exports.default = EventDefMutation;
13574
13575
13576/***/ }),
13577/* 40 */
13578/***/ (function(module, exports, __webpack_require__) {
13579
13580Object.defineProperty(exports, "__esModule", { value: true });
13581var util_1 = __webpack_require__(4);
13582var EventDateProfile_1 = __webpack_require__(16);
13583var EventDefDateMutation = /** @class */ (function () {
13584    function EventDefDateMutation() {
13585        this.clearEnd = false;
13586        this.forceTimed = false;
13587        this.forceAllDay = false;
13588    }
13589    EventDefDateMutation.createFromDiff = function (dateProfile0, dateProfile1, largeUnit) {
13590        var clearEnd = dateProfile0.end && !dateProfile1.end;
13591        var forceTimed = dateProfile0.isAllDay() && !dateProfile1.isAllDay();
13592        var forceAllDay = !dateProfile0.isAllDay() && dateProfile1.isAllDay();
13593        var dateDelta;
13594        var endDiff;
13595        var endDelta;
13596        var mutation;
13597        // subtracts the dates in the appropriate way, returning a duration
13598        function subtractDates(date1, date0) {
13599            if (largeUnit) {
13600                return util_1.diffByUnit(date1, date0, largeUnit); // poorly named
13601            }
13602            else if (dateProfile1.isAllDay()) {
13603                return util_1.diffDay(date1, date0); // poorly named
13604            }
13605            else {
13606                return util_1.diffDayTime(date1, date0); // poorly named
13607            }
13608        }
13609        dateDelta = subtractDates(dateProfile1.start, dateProfile0.start);
13610        if (dateProfile1.end) {
13611            // use unzonedRanges because dateProfile0.end might be null
13612            endDiff = subtractDates(dateProfile1.unzonedRange.getEnd(), dateProfile0.unzonedRange.getEnd());
13613            endDelta = endDiff.subtract(dateDelta);
13614        }
13615        mutation = new EventDefDateMutation();
13616        mutation.clearEnd = clearEnd;
13617        mutation.forceTimed = forceTimed;
13618        mutation.forceAllDay = forceAllDay;
13619        mutation.setDateDelta(dateDelta);
13620        mutation.setEndDelta(endDelta);
13621        return mutation;
13622    };
13623    /*
13624    returns an undo function.
13625    */
13626    EventDefDateMutation.prototype.buildNewDateProfile = function (eventDateProfile, calendar) {
13627        var start = eventDateProfile.start.clone();
13628        var end = null;
13629        var shouldRezone = false;
13630        if (eventDateProfile.end && !this.clearEnd) {
13631            end = eventDateProfile.end.clone();
13632        }
13633        else if (this.endDelta && !end) {
13634            end = calendar.getDefaultEventEnd(eventDateProfile.isAllDay(), start);
13635        }
13636        if (this.forceTimed) {
13637            shouldRezone = true;
13638            if (!start.hasTime()) {
13639                start.time(0);
13640            }
13641            if (end && !end.hasTime()) {
13642                end.time(0);
13643            }
13644        }
13645        else if (this.forceAllDay) {
13646            if (start.hasTime()) {
13647                start.stripTime();
13648            }
13649            if (end && end.hasTime()) {
13650                end.stripTime();
13651            }
13652        }
13653        if (this.dateDelta) {
13654            shouldRezone = true;
13655            start.add(this.dateDelta);
13656            if (end) {
13657                end.add(this.dateDelta);
13658            }
13659        }
13660        // do this before adding startDelta to start, so we can work off of start
13661        if (this.endDelta) {
13662            shouldRezone = true;
13663            end.add(this.endDelta);
13664        }
13665        if (this.startDelta) {
13666            shouldRezone = true;
13667            start.add(this.startDelta);
13668        }
13669        if (shouldRezone) {
13670            start = calendar.applyTimezone(start);
13671            if (end) {
13672                end = calendar.applyTimezone(end);
13673            }
13674        }
13675        // TODO: okay to access calendar option?
13676        if (!end && calendar.opt('forceEventDuration')) {
13677            end = calendar.getDefaultEventEnd(eventDateProfile.isAllDay(), start);
13678        }
13679        return new EventDateProfile_1.default(start, end, calendar);
13680    };
13681    EventDefDateMutation.prototype.setDateDelta = function (dateDelta) {
13682        if (dateDelta && dateDelta.valueOf()) {
13683            this.dateDelta = dateDelta;
13684        }
13685        else {
13686            this.dateDelta = null;
13687        }
13688    };
13689    EventDefDateMutation.prototype.setStartDelta = function (startDelta) {
13690        if (startDelta && startDelta.valueOf()) {
13691            this.startDelta = startDelta;
13692        }
13693        else {
13694            this.startDelta = null;
13695        }
13696    };
13697    EventDefDateMutation.prototype.setEndDelta = function (endDelta) {
13698        if (endDelta && endDelta.valueOf()) {
13699            this.endDelta = endDelta;
13700        }
13701        else {
13702            this.endDelta = null;
13703        }
13704    };
13705    EventDefDateMutation.prototype.isEmpty = function () {
13706        return !this.clearEnd && !this.forceTimed && !this.forceAllDay &&
13707            !this.dateDelta && !this.startDelta && !this.endDelta;
13708    };
13709    return EventDefDateMutation;
13710}());
13711exports.default = EventDefDateMutation;
13712
13713
13714/***/ }),
13715/* 41 */
13716/***/ (function(module, exports, __webpack_require__) {
13717
13718Object.defineProperty(exports, "__esModule", { value: true });
13719var tslib_1 = __webpack_require__(2);
13720var $ = __webpack_require__(3);
13721var util_1 = __webpack_require__(4);
13722var Class_1 = __webpack_require__(35);
13723/*
13724Embodies a div that has potential scrollbars
13725*/
13726var Scroller = /** @class */ (function (_super) {
13727    tslib_1.__extends(Scroller, _super);
13728    function Scroller(options) {
13729        var _this = _super.call(this) || this;
13730        options = options || {};
13731        _this.overflowX = options.overflowX || options.overflow || 'auto';
13732        _this.overflowY = options.overflowY || options.overflow || 'auto';
13733        return _this;
13734    }
13735    Scroller.prototype.render = function () {
13736        this.el = this.renderEl();
13737        this.applyOverflow();
13738    };
13739    Scroller.prototype.renderEl = function () {
13740        return (this.scrollEl = $('<div class="fc-scroller"></div>'));
13741    };
13742    // sets to natural height, unlocks overflow
13743    Scroller.prototype.clear = function () {
13744        this.setHeight('auto');
13745        this.applyOverflow();
13746    };
13747    Scroller.prototype.destroy = function () {
13748        this.el.remove();
13749    };
13750    // Overflow
13751    // -----------------------------------------------------------------------------------------------------------------
13752    Scroller.prototype.applyOverflow = function () {
13753        this.scrollEl.css({
13754            'overflow-x': this.overflowX,
13755            'overflow-y': this.overflowY
13756        });
13757    };
13758    // Causes any 'auto' overflow values to resolves to 'scroll' or 'hidden'.
13759    // Useful for preserving scrollbar widths regardless of future resizes.
13760    // Can pass in scrollbarWidths for optimization.
13761    Scroller.prototype.lockOverflow = function (scrollbarWidths) {
13762        var overflowX = this.overflowX;
13763        var overflowY = this.overflowY;
13764        scrollbarWidths = scrollbarWidths || this.get
13764ScrollbarWidths();
13765        if (overflowX === 'auto') {
13766            overflowX = (scrollbarWidths.top || scrollbarWidths.bottom || // horizontal scrollbars?
13767                // OR scrolling pane with massless scrollbars?
13768                this.scrollEl[0].scrollWidth - 1 > this.scrollEl[0].clientWidth
13769            // subtract 1 because of IE off-by-one issue
13770            ) ? 'scroll' : 'hidden';
13771        }
13772        if (overflowY === 'auto') {
13773            overflowY = (scrollbarWidths.left || scrollbarWidths.right || // vertical scrollbars?
13774                // OR scrolling pane with massless scrollbars?
13775                this.scrollEl[0].scrollHeight - 1 > this.scrollEl[0].clientHeight
13776            // subtract 1 because of IE off-by-one issue
13777            ) ? 'scroll' : 'hidden';
13778        }
13779        this.scrollEl.css({ 'overflow-x': overflowX, 'overflow-y': overflowY });
13780    };
13781    // Getters / Setters
13782    // -----------------------------------------------------------------------------------------------------------------
13783    Scroller.prototype.setHeight = function (height) {
13784        this.scrollEl.height(height);
13785    };
13786    Scroller.prototype.getScrollTop = function () {
13787        return this.scrollEl.scrollTop();
13788    };
13789    Scroller.prototype.setScrollTop = function (top) {
13790        this.scrollEl.scrollTop(top);
13791    };
13792    Scroller.prototype.getClientWidth = function () {
13793        return this.scrollEl[0].clientWidth;
13794    };
13795    Scroller.prototype.getClientHeight = function () {
13796        return this.scrollEl[0].clientHeight;
13797    };
13798    Scroller.prototype.getScrollbarWidths = function () {
13799        return util_1.getScrollbarWidths(this.scrollEl);
13800    };
13801    return Scroller;
13802}(Class_1.default));
13803exports.default = Scroller;
13804
13805
13806/***/ }),
13807/* 42 */
13808/***/ (function(module, exports, __webpack_require__) {
13809
13810Object.defineProperty(exports, "__esModule", { value: true });
13811var tslib_1 = __webpack_require__(2);
13812var $ = __webpack_require__(3);
13813var util_1 = __webpack_require__(4);
13814var DateComponent_1 = __webpack_require__(231);
13815var GlobalEmitter_1 = __webpack_require__(23);
13816var InteractiveDateComponent = /** @class */ (function (_super) {
13817    tslib_1.__extends(InteractiveDateComponent, _super);
13818    function InteractiveDateComponent(_view, _options) {
13819        var _this = _super.call(this, _view, _options) || this;
13820        // self-config, overridable by subclasses
13821        _this.segSelector = '.fc-event-container > *'; // what constitutes an event element?
13822        if (_this.dateSelectingClass) {
13823            _this.dateClicking = new _this.dateClickingClass(_this);
13824        }
13825        if (_this.dateSelectingClass) {
13826            _this.dateSelecting = new _this.dateSelectingClass(_this);
13827        }
13828        if (_this.eventPointingClass) {
13829            _this.eventPointing = new _this.eventPointingClass(_this);
13830        }
13831        if (_this.eventDraggingClass && _this.eventPointing) {
13832            _this.eventDragging = new _this.eventDraggingClass(_this, _this.eventPointing);
13833        }
13834        if (_this.eventResizingClass && _this.eventPointing) {
13835            _this.eventResizing = new _this.eventResizingClass(_this, _this.eventPointing);
13836        }
13837        if (_this.externalDroppingClass) {
13838            _this.externalDropping = new _this.externalDroppingClass(_this);
13839        }
13840        return _this;
13841    }
13842    // Sets the container element that the view should render inside of, does global DOM-related initializations,
13843    // and renders all the non-date-related content inside.
13844    InteractiveDateComponent.prototype.setElement = function (el) {
13845        _super.prototype.setElement.call(this, el);
13846        if (this.dateClicking) {
13847            this.dateClicking.bindToEl(el);
13848        }
13849        if (this.dateSelecting) {
13850            this.dateSelecting.bindToEl(el);
13851        }
13852        this.bindAllSegHandlersToEl(el);
13853    };
13854    InteractiveDateComponent.prototype.removeElement = function () {
13855        this.endInteractions();
13856        _super.prototype.removeElement.call(this);
13857    };
13858    InteractiveDateComponent.prototype.executeEventUnrender = function () {
13859        this.endInteractions();
13860        _super.prototype.executeEventUnrender.call(this);
13861    };
13862    InteractiveDateComponent.prototype.bindGlobalHandlers = function () {
13863        _super.prototype.bindGlobalHandlers.call(this);
13864        if (this.externalDropping) {
13865            this.externalDropping.bindToDocument();
13866        }
13867    };
13868    InteractiveDateComponent.prototype.unbindGlobalHandlers = function () {
13869        _super.prototype.unbindGlobalHandlers.call(this);
13870        if (this.externalDropping) {
13871            this.externalDropping.unbindFromDocument();
13872        }
13873    };
13874    InteractiveDateComponent.prototype.bindDateHandlerToEl = function (el, name, handler) {
13875        var _this = this;
13876        // attach a handler to the grid's root element.
13877        // jQuery will take care of unregistering them when removeElement gets called.
13878        this.el.on(name, function (ev) {
13879            if (!$(ev.target).is(_this.segSelector + ':not(.fc-helper),' + // directly on an event element
13880                _this.segSelector + ':not(.fc-helper) *,' + // within an event element
13881                '.fc-more,' + // a "more.." link
13882                'a[data-goto]' // a clickable nav link
13883            )) {
13884                return handler.call(_this, ev);
13885            }
13886        });
13887    };
13888    InteractiveDateComponent.prototype.bindAllSegHandlersToEl = function (el) {
13889        [
13890            this.eventPointing,
13891            this.eventDragging,
13892            this.eventResizing
13893        ].forEach(function (eventInteraction) {
13894            if (eventInteraction) {
13895                eventInteraction.bindToEl(el);
13896            }
13897        });
13898    };
13899    InteractiveDateComponent.prototype.bindSegHandlerToEl = function (el, name, handler) {
13900        var _this = this;
13901        el.on(name, this.segSelector, function (ev) {
13902            var segEl = $(ev.currentTarget);
13903            if (!segEl.is('.fc-helper')) {
13904                var seg = segEl.data('fc-seg'); // grab segment data. put there by View::renderEventsPayload
13905                if (seg && !_this.shouldIgnoreEventPointing()) {
13906                    return handler.call(_this, seg, ev); // context will be the Grid
13907                }
13908            }
13909        });
13910    };
13911    InteractiveDateComponent.prototype.shouldIgnoreMouse = function () {
13912        // HACK
13913        // This will still work even though bindDateHandlerToEl doesn't use GlobalEmitter.
13914        return GlobalEmitter_1.default.get().shouldIgnoreMouse();
13915    };
13916    InteractiveDateComponent.prototype.shouldIgnoreTouch = function () {
13917        var view = this._getView();
13918        // On iOS (and Android?) when a new selection is initiated overtop another selection,
13919        // the touchend never fires because the elements gets removed mid-touch-interaction (my theory).
13920        // HACK: simply don't allow this to happen.
13921        // ALSO: prevent selection when an *event* is already raised.
13922        return view.isSelected || view.selectedEvent;
13923    };
13924    InteractiveDateComponent.prototype.shouldIgnoreEventPointing = function () {
13925        // only call the handlers if there is not a drag/resize in progress
13926        return (this.eventDragging && this.eventDragging.isDragging) ||
13927            (this.eventResizing && this.eventResizing.isResizing);
13928    };
13929    InteractiveDateComponent.prototype.canStartSelection = function (seg, ev) {
13930        return util_1.getEvIsTouch(ev) &&
13931            !this.canStartResize(seg, ev) &&
13932            (this.isEventDefDraggable(seg.footprint.eventDef) ||
13933                this.isEventDefResizable(seg.footprint.eventDef));
13934    };
13935    InteractiveDateComponent.prototype.canStartDrag = function (seg, ev) {
13936        return !this.canStartResize(seg, ev) &&
13937            this.isEventDefDraggable(seg.footprint.eventDef);
13938    };
13939    InteractiveDateComponent.prototype.canStartResize = function (seg, ev) {
13940        var view = this._getView();
13941        var eventDef = seg.footprint.eventDef;
13942        return (!util_1.getEvIsTouch(ev) || view.isEventDefSelected(eventDef)) &&
13943            this.isEventDefResizable(eventDef) &&
13944            $(ev.target).is('.fc-resizer');
13945    };
13946    // Kills all in-progress dragging.
13947    // Useful for when public API methods that result in re-rendering are invoked during a drag.
13948    // Also useful for when touch devices misbehave and don't fire their touchend.
13949    InteractiveDateComponent.prototype.endInteractions = function () {
13950        [
13951            this.dateClicking,
13952            this.dateSelecting,
13953            this.eventPointing,
13954            this.eventDragging,
13955            this.eventResizing
13956        ].forEach(function (interaction) {
13957            if (interaction) {
13958                interaction.end();
13959            }
13960        });
13961    };
13962    // Event Drag-n-Drop
13963    // ---------------------------------------------------------------------------------------------------------------
13964    // Computes if the given event is allowed to be dragged by the user
13965    InteractiveDateComponent.prototype.isEventDefDraggable = function (eventDef) {
13966        return this.isEventDefStartEditable(eventDef);
13967    };
13968    InteractiveDateComponent.prototype.isEventDefStartEditable = function (eventDef) {
13969        var isEditable = eventDef.isStartExplicitlyEditable();
13970        if (isEditable == null) {
13971            isEditable = this.opt('eventStartEditable');
13972            if (isEditable == null) {
13973                isEditable = this.isEventDefGenerallyEditable(eventDef);
13974            }
13975        }
13976        return isEditable;
13977    };
13978    InteractiveDateComponent.prototype.isEventDefGenerallyEditable = function (eventDef) {
13979        var isEditable = eventDef.isExplicitlyEditable();
13980        if (isEditable == null) {
13981            isEditable = this.opt('editable');
13982        }
13983        return isEditable;
13984    };
13985    // Event Resizing
13986    // ---------------------------------------------------------------------------------------------------------------
13987    // Computes if the given event is allowed to be resized from its starting edge
13988    InteractiveDateComponent.prototype.isEventDefResizableFromStart = function (eventDef) {
13989        return this.opt('eventResizableFromStart') && this.isEventDefResizable(eventDef);
13990    };
13991    // Computes if the given event is allowed to be resized from its ending edge
13992    InteractiveDateComponent.prototype.isEventDefResizableFromEnd = function (eventDef) {
13993        return this.isEventDefResizable(eventDef);
13994    };
13995    // Computes if the given event is allowed to be resized by the user at all
13996    InteractiveDateComponent.prototype.isEventDefResizable = function (eventDef) {
13997        var isResizable = eventDef.isDurationExplicitlyEditable();
13998        if (isResizable == null) {
13999            isResizable = this.opt('eventDurationEditable');
14000            if (isResizable == null) {
14001                isResizable = this.isEventDefGenerallyEditable(eventDef);
14002            }
14003        }
14004        return isResizable;
14005    };
14006    // Event Mutation / Constraints
14007    // ---------------------------------------------------------------------------------------------------------------
14008    // Diffs the two dates, returning a duration, based on granularity of the grid
14009    // TODO: port isTimeScale into this system?
14010    InteractiveDateComponent.prototype.diffDates = function (a, b) {
14011        if (this.largeUnit) {
14012            return util_1.diffByUnit(a, b, this.largeUnit);
14013        }
14014        else {
14015            return util_1.diffDayTime(a, b);
14016        }
14017    };
14018    // is it allowed, in relation to the view's validRange?
14019    // NOTE: very similar to isExternalInstanceGroupAllowed
14020    InteractiveDateComponent.prototype.isEventInstanceGroupAllowed = function (eventInstanceGroup) {
14021        var view = this._getView();
14022        var dateProfile = this.dateProfile;
14023        var eventFootprints = this.eventRangesToEventFootprints(eventInstanceGroup.getAllEventRanges());
14024        var i;
14025        for (i = 0; i < eventFootprints.length; i++) {
14026            // TODO: just use getAllEventRanges directly
14027            if (!dateProfile.validUnzonedRange.containsRange(eventFootprints[i].componentFootprint.unzonedRange)) {
14028                return false;
14029            }
14030        }
14031        return view.calendar.constraints.isEventInstanceGroupAllowed(eventInstanceGroup);
14032    };
14033    // NOTE: very similar to isEventInstanceGroupAllowed
14034    // when it's a completely anonymous external drag, no event.
14035    InteractiveDateComponent.prototype.isExternalInstanceGroupAllowed = function (eventInstanceGroup) {
14036        var view = this._getView();
14037        var dateProfile = this.dateProfile;
14038        var eventFootprints = this.eventRangesToEventFootprints(eventInstanceGroup.getAllEventRanges());
14039        var i;
14040        for (i = 0; i < eventFootprints.length; i++) {
14041            if (!dateProfile.validUnzonedRange.containsRange(eventFootprints[i].componentFootprint.unzonedRange)) {
14042                return false;
14043            }
14044        }
14045        for (i = 0; i < eventFootprints.length; i++) {
14046            // treat it as a selection
14047            // TODO: pass in eventInstanceGroup instead
14048            //  because we don't want calendar's constraint system to depend on a component's
14049            //  determination of footprints.
14050            if (!view.calendar.constraints.isSelectionFootprintAllowed(eventFootprints[i].componentFootprint)) {
14051                return false;
14052            }
14053        }
14054        return true;
14055    };
14056    return InteractiveDateComponent;
14057}(DateComponent_1.default));
14058exports.default = InteractiveDateComponent;
14059
14060
14061/***/ }),
14062/* 43 */
14063/***/ (function(module, exports, __webpack_require__) {
14064
14065Object.defineProperty(exports, "__esModule", { value: true });
14066var tslib_1 = __webpack_require__(2);
14067var $ = __webpack_require__(3);
14068var moment = __webpack_require__(0);
14069var util_1 = __webpack_require__(4);
14070var RenderQueue_1 = __webpack_require__(229);
14071var DateProfileGenerator_1 = __webpack_require__(55);
14072var InteractiveDateComponent_1 = __webpack_require__(42);
14073var GlobalEmitter_1 = __webpack_require__(23);
14074var UnzonedRange_1 = __webpack_require__(5);
14075/* An abstract class from which other views inherit from
14076----------------------------------------------------------------------------------------------------------------------*/
14077var View = /** @class */ (function (_super) {
14078    tslib_1.__extends(View, _super);
14079    function View(calendar, viewSpec) {
14080        var _this = _super.call(this, null, viewSpec.options) || this;
14081        _this.batchRenderDepth = 0;
14082        _this.isSelected = false; // boolean whether a range of time is user-selected or not
14083        _this.calendar = calendar;
14084        _this.viewSpec = viewSpec;
14085        // shortcuts
14086        _this.type = viewSpec.type;
14087        // .name is deprecated
14088        _this.name = _this.type;
14089        _this.initRenderQueue();
14090        _this.initHiddenDays();
14091        _this.dateProfileGenerator = new _this.dateProfileGeneratorClass(_this);
14092        _this.bindBaseRenderHandlers();
14093        _this.eventOrderSpecs = util_1.parseFieldSpecs(_this.opt('eventOrder'));
14094        // legacy
14095        if (_this['initialize']) {
14096            _this['initialize']();
14097        }
14098        return _this;
14099    }
14100    View.prototype._getView = function () {
14101        return this;
14102    };
14103    // Retrieves an option with the given name
14104    View.prototype.opt = function (name) {
14105        return this.options[name];
14106    };
14107    /* Render Queue
14108    ------------------------------------------------------------------------------------------------------------------*/
14109    View.prototype.initRenderQueue = function () {
14110        this.renderQueue = new RenderQueue_1.default({
14111            event: this.opt('eventRenderWait')
14112        });
14113        this.renderQueue.on('start', this.onRenderQueueStart.bind(this));
14114        this.renderQueue.on('stop', this.onRenderQueueStop.bind(this));
14115        this.on('before:change', this.startBatchRender);
14116        this.on('change', this.stopBatchRender);
14117    };
14118    View.prototype.onRenderQueueStart = function () {
14119        this.calendar.freezeContentHeight();
14120        this.addScroll(this.queryScroll());
14121    };
14122    View.prototype.onRenderQueueStop = function () {
14123        if (this.calendar.updateViewSize()) { // success?
14124            this.popScroll();
14125        }
14126        this.calendar.thawContentHeight();
14127    };
14128    View.prototype.startBatchRender = function () {
14129        if (!(this.batchRenderDepth++)) {
14130            this.renderQueue.pause();
14131        }
14132    };
14133    View.prototype.stopBatchRender = function () {
14134        if (!(--this.batchRenderDepth)) {
14135            this.renderQueue.resume();
14136        }
14137    };
14138    View.prototype.requestRender = function (func, namespace, actionType) {
14139        this.renderQueue.queue(func, namespace, actionType);
14140    };
14141    // given func will auto-bind to `this`
14142    View.prototype.whenSizeUpdated = function (func) {
14143        if (this.renderQueue.isRunning) {
14144            this.renderQueue.one('stop', func.bind(this));
14145        }
14146        else {
14147            func.call(this);
14148        }
14149    };
14150    /* Title and Date Formatting
14151    ------------------------------------------------------------------------------------------------------------------*/
14152    // Computes what the title at the top of the calendar should be for this view
14153    View.prototype.computeTitle = function (dateProfile) {
14154        var unzonedRange;
14155        // for views that span a large unit of time, show the proper interval, ignoring stray days before and after
14156        if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) {
14157            unzonedRange = dateProfile.currentUnzonedRange;
14158        }
14159        else { // for day units or smaller, use the actual day range
14160            unzonedRange = dateProfile.activeUnzonedRange;
14161        }
14162        return this.formatRange({
14163            start: this.calendar.msToMoment(unzonedRange.startMs, dateProfile.isRangeAllDay),
14164            end: this.calendar.msToMoment(unzonedRange.endMs, dateProfile.isRangeAllDay)
14165        }, dateProfile.isRangeAllDay, this.opt('titleFormat') || this.computeTitleFormat(dateProfile), this.opt('titleRangeSeparator'));
14166    };
14167    // Generates the format string that should be used to generate the title for the current date range.
14168    // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.
14169    View.prototype.computeTitleFormat = function (dateProfile) {
14170        var currentRangeUnit = dateProfile.currentRangeUnit;
14171        if (currentRangeUnit === 'year') {
14172            return 'YYYY';
14173        }
14174        else if (currentRangeUnit === 'month') {
14175            return this.opt('monthYearFormat'); // like "September 2014"
14176        }
14177        else if (dateProfile.currentUnzonedRange.as('days') > 1) {
14178            return 'll'; // multi-day range. shorter, like "Sep 9 - 10 2014"
14179        }
14180        else {
14181            return 'LL'; // one day. longer, like "September 9 2014"
14182        }
14183    };
14184    // Date Setting/Unsetting
14185    // -----------------------------------------------------------------------------------------------------------------
14186    View.prototype.setDate = function (date) {
14187        var currentDateProfile = this.get('dateProfile');
14188        var newDateProfile = this.dateProfileGenerator.build(date, undefined, true); // forceToValid=true
14189        if (!currentDateProfile ||
14190            !currentDateProfile.activeUnzonedRange.equals(newDateProfile.activeUnzonedRange)) {
14191            this.set('dateProfile', newDateProfile);
14192        }
14193    };
14194    View.prototype.unsetDate = function () {
14195        this.unset('dateProfile');
14196    };
14197    // Event Data
14198    // -----------------------------------------------------------------------------------------------------------------
14199    View.prototype.fetchInitialEvents = function (dateProfile) {
14200        var calendar = this.calendar;
14201        var forceAllDay = dateProfile.isRangeAllDay && !this.usesMinMaxTime;
14202        return calendar.requestEvents(calendar.msToMoment(dateProfile.activeUnzonedRange.startMs, forceAllDay), calendar.msToMoment(dateProfile.activeUnzonedRange.endMs, forceAllDay));
14203    };
14204    View.prototype.bindEventChanges = function () {
14205        this.listenTo(this.calendar, 'eventsReset', this.resetEvents); // TODO: make this a real event
14206    };
14207    View.prototype.unbindEventChanges = function () {
14208        this.stopListeningTo(this.calendar, 'eventsReset');
14209    };
14210    View.prototype.setEvents = function (eventsPayload) {
14211        this.set('currentEvents', eventsPayload);
14212        this.set('hasEvents', true);
14213    };
14214    View.prototype.unsetEvents = function () {
14215        this.unset('currentEvents');
14216        this.unset('hasEvents');
14217    };
14218    View.prototype.resetEvents = function (eventsPayload) {
14219        this.startBatchRender();
14220        this.unsetEvents();
14221        this.setEvents(eventsPayload);
14222        this.stopBatchRender();
14223    };
14224    // Date High-level Rendering
14225    // -----------------------------------------------------------------------------------------------------------------
14226    View.prototype.requestDateRender = function (dateProfile) {
14227        var _this = this;
14228        this.requestRender(function () {
14229            _this.executeDateRender(dateProfile);
14230        }, 'date', 'init');
14231    };
14232    View.prototype.requestDateUnrender = function () {
14233        var _this = this;
14234        this.requestRender(function () {
14235            _this.executeDateUnrender();
14236        }, 'date', 'destroy');
14237    };
14238    // if dateProfile not specified, uses current
14239    View.prototype.executeDateRender = function (dateProfile) {
14240        _super.prototype.executeDateRender.call(this, dateProfile);
14241        if (this['render']) {
14242            this['render'](); // TODO: deprecate
14243        }
14244        this.trigger('datesRendered');
14245        this.addScroll({ isDateInit: true });
14246        this.startNowIndicator(); // shouldn't render yet because updateSize will be called soon
14247    };
14248    View.prototype.executeDateUnrender = function () {
14249        this.unselect();
14250        this.stopNowIndicator();
14251        this.trigger('before:datesUnrendered');
14252        if (this['destroy']) {
14253            this['destroy'](); // TODO: deprecate
14254        }
14255        _super.prototype.executeDateUnrender.call(this);
14256    };
14257    // "Base" rendering
14258    // -----------------------------------------------------------------------------------------------------------------
14259    View.prototype.bindBaseRenderHandlers = function () {
14260        var _this = this;
14261        this.on('datesRendered', function () {
14262            _this.whenSizeUpdated(_this.triggerViewRender);
14263        });
14264        this.on('before:datesUnrendered', function () {
14265            _this.triggerViewDestroy();
14266        });
14267    };
14268    View.prototype.triggerViewRender = function () {
14269        this.publiclyTrigger('viewRender', {
14270            context: this,
14271            args: [this, this.el]
14272        });
14273    };
14274    View.prototype.triggerViewDestroy = function () {
14275        this.publiclyTrigger('viewDestroy', {
14276            context: this,
14277            args: [this, this.el]
14278        });
14279    };
14280    // Event High-level Rendering
14281    // -----------------------------------------------------------------------------------------------------------------
14282    View.prototype.requestEventsRender = function (eventsPayload) {
14283        var _this = this;
14284        this.requestRender(function () {
14285            _this.executeEventRender(eventsPayload);
14286            _this.whenSizeUpdated(_this.triggerAfterEventsRendered);
14287        }, 'event', 'init');
14288    };
14289    View.prototype.requestEventsUnrender = function () {
14290        var _this = this;
14291        this.requestRender(function () {
14292            _this.triggerBeforeEventsDestroyed();
14293            _this.executeEventUnrender();
14294        }, 'event', 'destroy');
14295    };
14296    // Business Hour High-level Rendering
14297    // -----------------------------------------------------------------------------------------------------------------
14298    View.prototype.requestBusinessHoursRender = function (businessHourGenerator) {
14299        var _this = this;
14300        this.requestRender(function () {
14301            _this.renderBusinessHours(businessHourGenerator);
14302        }, 'businessHours', 'init');
14303    };
14304    View.prototype.requestBusinessHoursUnrender = function () {
14305        var _this = this;
14306        this.requestRender(function () {
14307            _this.unrenderBusinessHours();
14308        }, 'businessHours', 'destroy');
14309    };
14310    // Misc view rendering utils
14311    // -----------------------------------------------------------------------------------------------------------------
14312    // Binds DOM handlers to elements that reside outside the view container, such as the document
14313    View.prototype.bindGlobalHandlers = function () {
14314        _super.prototype.bindGlobalHandlers.call(this);
14315        this.listenTo(GlobalEmitter_1.default.get(), {
14316            touchstart: this.processUnselect,
14317            mousedown: this.handleDocumentMousedown
14318        });
14319    };
14320    // Unbinds DOM handlers from elements that reside outside the view container
14321    View.prototype.unbindGlobalHandlers = function () {
14322        _super.prototype.unbindGlobalHandlers.call(this);
14323        this.stopListeningTo(GlobalEmitter_1.default.get());
14324    };
14325    /* Now Indicator
14326    ------------------------------------------------------------------------------------------------------------------*/
14327    // Immediately render the current time indicator and begins re-rendering it at an interval,
14328    // which is defined by this.getNowIndicatorUnit().
14329    // TODO: somehow do this for the current whole day's background too
14330    View.prototype.startNowIndicator = function () {
14331        var _this = this;
14332        var unit;
14333        var update;
14334        var delay; // ms wait value
14335        if (this.opt('nowIndicator')) {
14336            unit = this.getNowIndicatorUnit();
14337            if (unit) {
14338                update = util_1.proxy(this, 'updateNowIndicator'); // bind to `this`
14339                this.initialNowDate = this.calendar.getNow();
14340                this.initialNowQueriedMs = new Date().valueOf();
14341                // wait until the beginning of the next interval
14342                delay = this.initialNowDate.clone().startOf(unit).add(1, unit).valueOf() - this.initialNowDate.valueOf();
14343                this.nowIndicatorTimeoutID = setTimeout(function () {
14344                    _this.nowIndicatorTimeoutID = null;
14345                    update();
14346                    delay = +moment.duration(1, unit);
14347                    delay = Math.max(100, delay); // prevent too frequent
14348                    _this.nowIndicatorIntervalID = setInterval(update, delay); // update every interval
14349                }, delay);
14350            }
14351            // rendering will be initiated in updateSize
14352        }
14353    };
14354    // rerenders the now indicator, computing the new current time from the amount of time that has passed
14355    // since the initial getNow call.
14356    View.prototype.updateNowIndicator = function () {
14357        if (this.isDatesRendered &&
14358            this.initialNowDate // activated before?
14359        ) {
14360            this.unrenderNowIndicator(); // won't unrender if unnecessary
14361            this.renderNowIndicator(this.initialNowDate.clone().add(new Date().valueOf() - this.initialNowQueriedMs) // add ms
14362            );
14363            this.isNowIndicatorRendered = true;
14364        }
14365    };
14366    // Immediately unrenders the view's current time indicator and stops any re-rendering timers.
14367    // Won't cause side effects if indicator isn't rendered.
14368    View.prototype.stopNowIndicator = function () {
14369        if (this.isNowIndicatorRendered) {
14370            if (this.nowIndicatorTimeoutID) {
14371                clearTimeout(this.nowIndicatorTimeoutID);
14372                this.nowIndicatorTimeoutID = null;
14373            }
14374            if (this.nowIndicatorIntervalID) {
14375                clearInterval(this.nowIndicatorIntervalID);
14376                this.nowIndicatorIntervalID = null;
14377            }
14378            this.unrenderNowIndicator();
14379            this.isNowIndicatorRendered = false;
14380        }
14381    };
14382    /* Dimensions
14383    ------------------------------------------------------------------------------------------------------------------*/
14384    View.prototype.updateSize = function (totalHeight, isAuto, isResize) {
14385        if (this['setHeight']) { // for legacy API
14386            this['setHeight'](totalHeight, isAuto);
14387        }
14388        else {
14389            _super.prototype.updateSize.call(this, totalHeight, isAuto, isResize);
14390        }
14391        this.updateNowIndicator();
14392    };
14393    /* Scroller
14394    ------------------------------------------------------------------------------------------------------------------*/
14395    View.prototype.addScroll = function (scroll) {
14396        var queuedScroll = this.queuedScroll || (this.queuedScroll = {});
14397        $.extend(queuedScroll, scroll);
14398    };
14399    View.prototype.popScroll = function () {
14400        this.applyQueuedScroll();
14401        this.queuedScroll = null;
14402    };
14403    View.prototype.applyQueuedScroll = function () {
14404        if (this.queuedScroll) {
14405            this.applyScroll(this.queuedScroll);
14406        }
14407    };
14408    View.prototype.queryScroll = function () {
14409        var scroll = {};
14410        if (this.isDatesRendered) {
14411            $.extend(scroll, this.queryDateScroll());
14412        }
14413        return scroll;
14414    };
14415    View.prototype.applyScroll = function (scroll) {
14416        if (scroll.isDateInit && this.isDatesRendered) {
14417            $.extend(scroll, this.computeInitialDateScroll());
14418        }
14419        if (this.isDatesRendered) {
14420            this.applyDateScroll(scroll);
14421        }
14422    };
14423    View.prototype.computeInitialDateScroll = function () {
14424        return {}; // subclasses must implement
14425    };
14426    View.prototype.queryDateScroll = function () {
14427        return {}; // subclasses must implement
14428    };
14429    View.prototype.applyDateScroll = function (scroll) {
14430        // subclasses must implement
14431    };
14432    /* Event Drag-n-Drop
14433    ------------------------------------------------------------------------------------------------------------------*/
14434    View.prototype.reportEventDrop = function (eventInstance, eventMutation, el, ev) {
14435        var eventManager = this.calendar.eventManager;
14436        var undoFunc = eventManager.mutateEventsWithId(eventInstance.def.id, eventMutation);
14437        var dateMutation = eventMutation.dateMutation;
14438        // update the EventInstance, for handlers
14439        if (dateMutation) {
14440            eventInstance.dateProfile = dateMutation.buildNewDateProfile(eventInstance.dateProfile, this.calendar);
14441        }
14442        this.triggerEventDrop(eventInstance, 
14443        // a drop doesn't necessarily mean a date mutation (ex: resource change)
14444        (dateMutation && dateMutation.dateDelta) || moment.duration(), undoFunc, el, ev);
14445    };
14446    // Triggers event-drop handlers that have subscribed via the API
14447    View.prototype.triggerEventDrop = function (eventInstance, dateDelta, undoFunc, el, ev) {
14448        this.publiclyTrigger('eventDrop', {
14449            context: el[0],
14450            args: [
14451                eventInstance.toLegacy(),
14452                dateDelta,
14453                undoFunc,
14454                ev,
14455                {},
14456                this
14457            ]
14458        });
14459    };
14460    /* External Element Drag-n-Drop
14461    ------------------------------------------------------------------------------------------------------------------*/
14462    // Must be called when an external element, via jQuery UI, has been dropped onto the calendar.
14463    // `meta` is the parsed data that has been embedded into the dragging event.
14464    // `dropLocation` is an object that contains the new zoned start/end/allDay values for the event.
14465    View.prototype.reportExternalDrop = function (singleEventDef, isEvent, isSticky, el, ev, ui) {
14466        if (isEvent) {
14467            this.calendar.eventManager.addEventDef(singleEventDef, isSticky);
14468        }
14469        this.triggerExternalDrop(singleEventDef, isEvent, el, ev, ui);
14470    };
14471    // Triggers external-drop handlers that have subscribed via the API
14472    View.prototype.triggerExternalDrop = function (singleEventDef, isEvent, el, ev, ui) {
14473        // trigger 'drop' regardless of whether element represents an event
14474        this.publiclyTrigger('drop', {
14475            context: el[0],
14476            args: [
14477                singleEventDef.dateProfile.start.clone(),
14478                ev,
14479                ui,
14480                this
14481            ]
14482        });
14483        if (isEvent) {
14484            // signal an external event landed
14485            this.publiclyTrigger('eventReceive', {
14486                context: this,
14487                args: [
14488                    singleEventDef.buildInstance().toLegacy(),
14489                    this
14490                ]
14491            });
14492        }
14493    };
14494    /* Event Resizing
14495    ------------------------------------------------------------------------------------------------------------------*/
14496    // Must be called when an event in the view has been resized to a new length
14497    View.prototype.reportEventResize = function (eventInstance, eventMutation, el, ev) {
14498        var eventManager = this.calendar.eventManager;
14499        var undoFunc = eventManager.mutateEventsWithId(eventInstance.def.id, eventMutation);
14500        // update the EventInstance, for handlers
14501        eventInstance.dateProfile = eventMutation.dateMutation.buildNewDateProfile(eventInstance.dateProfile, this.calendar);
14502        var resizeDelta = eventMutation.dateMutation.endDelta || eventMutation.dateMutation.startDelta;
14503        this.triggerEventResize(eventInstance, resizeDelta, undoFunc, el, ev);
14504    };
14505    // Triggers event-resize handlers that have subscribed via the API
14506    View.prototype.triggerEventResize = function (eventInstance, resizeDelta, undoFunc, el, ev) {
14507        this.publiclyTrigger('eventResize', {
14508            context: el[0],
14509            args: [
14510                eventInstance.toLegacy(),
14511                resizeDelta,
14512                undoFunc,
14513                ev,
14514                {},
14515                this
14516            ]
14517        });
14518    };
14519    /* Selection (time range)
14520    ------------------------------------------------------------------------------------------------------------------*/
14521    // Selects a date span on the view. `start` and `end` are both Moments.
14522    // `ev` is the native mouse event that begin the interaction.
14523    View.prototype.select = function (footprint, ev) {
14524        this.unselect(ev);
14525        this.renderSelectionFootprint(footprint);
14526        this.reportSelection(footprint, ev);
14527    };
14528    View.prototype.renderSelectionFootprint = function (footprint) {
14529        if (this['renderSelection']) { // legacy method in custom view classes
14530            this['renderSelection'](footprint.toLegacy(this.calendar));
14531        }
14532        else {
14533            _super.prototype.renderSelectionFootprint.call(this, footprint);
14534        }
14535    };
14536    // Called when a new selection is made. Updates internal state and triggers handlers.
14537    View.prototype.reportSelection = function (footprint, ev) {
14538        this.isSelected = true;
14539        this.triggerSelect(footprint, ev);
14540    };
14541    // Triggers handlers to 'select'
14542    View.prototype.triggerSelect = function (footprint, ev) {
14543        var dateProfile = this.calendar.footprintToDateProfile(footprint); // abuse of "Event"DateProfile?
14544        this.publiclyTrigger('select', {
14545            context: this,
14546            args: [
14547                dateProfile.start,
14548                dateProfile.end,
14549                ev,
14550                this
14551            ]
14552        });
14553    };
14554    // Undoes a selection. updates in the internal state and triggers handlers.
14555    // `ev` is the native mouse event that began the interaction.
14556    View.prototype.unselect = function (ev) {
14557        if (this.isSelected) {
14558            this.isSelected = false;
14559            if (this['destroySelection']) {
14560                this['destroySelection'](); // TODO: deprecate
14561            }
14562            this.unrenderSelection();
14563            this.publiclyTrigger('unselect', {
14564                context: this,
14565                args: [ev, this]
14566            });
14567        }
14568    };
14569    /* Event Selection
14570    ------------------------------------------------------------------------------------------------------------------*/
14571    View.prototype.selectEventInstance = function (eventInstance) {
14572        if (!this.selectedEventInstance ||
14573            this.selectedEventInstance !== eventInstance) {
14574            this.unselectEventInstance();
14575            this.getEventSegs().forEach(function (seg) {
14576                if (seg.footprint.eventInstance === eventInstance &&
14577                    seg.el // necessary?
14578                ) {
14579                    seg.el.addClass('fc-selected');
14580                }
14581            });
14582            this.selectedEventInstance = eventInstance;
14583        }
14584    };
14585    View.prototype.unselectEventInstance = function () {
14586        if (this.selectedEventInstance) {
14587            this.getEventSegs().forEach(function (seg) {
14588                if (seg.el) { // necessary?
14589                    seg.el.removeClass('fc-selected');
14590                }
14591            });
14592            this.selectedEventInstance = null;
14593        }
14594    };
14595    View.prototype.isEventDefSelected = function (eventDef) {
14596        // event references might change on refetchEvents(), while selectedEventInstance doesn't,
14597        // so compare IDs
14598        return this.selectedEventInstance && this.selectedEventInstance.def.id === eventDef.id;
14599    };
14600    /* Mouse / Touch Unselecting (time range & event unselection)
14601    ------------------------------------------------------------------------------------------------------------------*/
14602    // TODO: move consistently to down/start or up/end?
14603    // TODO: don't kill previous selection if touch scrolling
14604    View.prototype.handleDocumentMousedown = function (ev) {
14605        if (util_1.isPrimaryMouseButton(ev)) {
14606            this.processUnselect(ev);
14607        }
14608    };
14609    View.prototype.processUnselect = function (ev) {
14610        this.processRangeUnselect(ev);
14611        this.processEventUnselect(ev);
14612    };
14613    View.prototype.processRangeUnselect = function (ev) {
14614        var ignore;
14615        // is there a time-range selection?
14616        if (this.isSelected && this.opt('unselectAuto')) {
14617            // only unselect if the clicked element is not identical to or inside of an 'unselectCancel' element
14618            ignore = this.opt('unselectCancel');
14619            if (!ignore || !$(ev.target).closest(ignore).length) {
14620                this.unselect(ev);
14621            }
14622        }
14623    };
14624    View.prototype.processEventUnselect = function (ev) {
14625        if (this.selectedEventInstance) {
14626            if (!$(ev.target).closest('.fc-selected').length) {
14627                this.unselectEventInstance();
14628            }
14629        }
14630    };
14631    /* Triggers
14632    ------------------------------------------------------------------------------------------------------------------*/
14633    View.prototype.triggerBaseRendered = function () {
14634        this.publiclyTrigger('viewRender', {
14635            context: this,
14636            args: [this, this.el]
14637        });
14638    };
14639    View.prototype.triggerBaseUnrendered = function () {
14640        this.publiclyTrigger('viewDestroy', {
14641            context: this,
14642            args: [this, this.el]
14643        });
14644    };
14645    // Triggers handlers to 'dayClick'
14646    // Span has start/end of the clicked area. Only the start is useful.
14647    View.prototype.triggerDayClick = function (footprint, dayEl, ev) {
14648        var dateProfile = this.calendar.footprintToDateProfile(footprint); // abuse of "Event"DateProfile?
14649        this.publiclyTrigger('dayClick', {
14650            context: dayEl,
14651            args: [dateProfile.start, ev, this]
14652        });
14653    };
14654    /* Date Utils
14655    ------------------------------------------------------------------------------------------------------------------*/
14656    // For DateComponent::getDayClasses
14657    View.prototype.isDateInOtherMonth = function (date, dateProfile) {
14658        return false;
14659    };
14660    // Arguments after name will be forwarded to a hypothetical function value
14661    // WARNING: passed-in arguments will be given to generator functions as-is and can cause side-effects.
14662    // Always clone your objects if you fear mutation.
14663    View.prototype.getUnzonedRangeOption = function (name) {
14664        var val = this.opt(name);
14665        if (typeof val === 'function') {
14666            val = val.apply(null, Array.prototype.slice.call(arguments, 1));
14667        }
14668        if (val) {
14669            return this.calendar.parseUnzonedRange(val);
14670        }
14671    };
14672    /* Hidden Days
14673    ------------------------------------------------------------------------------------------------------------------*/
14674    // Initializes internal variables related to calculating hidden days-of-week
14675    View.prototype.initHiddenDays = function () {
14676        var hiddenDays = this.opt('hiddenDays') || []; // array of day-of-week indices that are hidden
14677        var isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool)
14678        var dayCnt = 0;
14679        var i;
14680        if (this.opt('weekends') === false) {
14681            hiddenDays.push(0, 6); // 0=sunday, 6=saturday
14682        }
14683        for (i = 0; i < 7; i++) {
14684            if (!(isHiddenDayHash[i] = $.inArray(i, hiddenDays) !== -1)) {
14685                dayCnt++;
14686            }
14687        }
14688        if (!dayCnt) {
14689            throw new Error('invalid hiddenDays'); // all days were hidden? bad.
14690        }
14691        this.isHiddenDayHash = isHiddenDayHash;
14692    };
14693    // Remove days from the beginning and end of the range that are computed as hidden.
14694    // If the whole range is trimmed off, returns null
14695    View.prototype.trimHiddenDays = function (inputUnzonedRange) {
14696        var start = inputUnzonedRange.getStart();
14697        var end = inputUnzonedRange.getEnd();
14698        if (start) {
14699            start = this.skipHiddenDays(start);
14700        }
14701        if (end) {
14702            end = this.skipHiddenDays(end, -1, true);
14703        }
14704        if (start === null || end === null || start < end) {
14705            return new UnzonedRange_1.default(start, end);
14706        }
14707        return null;
14708    };
14709    // Is the current day hidden?
14710    // `day` is a day-of-week index (0-6), or a Moment
14711    View.prototype.isHiddenDay = function (day) {
14712        if (moment.isMoment(day)) {
14713            day = day.day();
14714        }
14715        return this.isHiddenDayHash[day];
14716    };
14717    // Incrementing the current day until it is no longer a hidden day, returning a copy.
14718    // DOES NOT CONSIDER validUnzonedRange!
14719    // If the initial value of `date` is not a hidden day, don't do anything.
14720    // Pass `isExclusive` as `true` if you are dealing with an end date.
14721    // `inc` defaults to `1` (increment one day forward each time)
14722    View.prototype.skipHiddenDays = function (date, inc, isExclusive) {
14723        if (inc === void 0) { inc = 1; }
14724        if (isExclusive === void 0) { isExclusive = false; }
14725        var out = date.clone();
14726        while (this.isHiddenDayHash[(out.day() + (isExclusive ? inc : 0) + 7) % 7]) {
14727            out.add(inc, 'days');
14728        }
14729        return out;
14730    };
14731    return View;
14732}(InteractiveDateComponent_1.default));
14733exports.default = View;
14734View.prototype.usesMinMaxTime = false;
14735View.prototype.dateProfileGeneratorClass = DateProfileGenerator_1.default;
14736View.watch('displayingDates', ['isInDom', 'dateProfile'], function (deps) {
14737    this.requestDateRender(deps.dateProfile);
14738}, function () {
14739    this.requestDateUnrender();
14740});
14741View.watch('displayingBusinessHours', ['displayingDates', 'businessHourGenerator'], function (deps) {
14742    this.requestBusinessHoursRender(deps.businessHourGenerator);
14743}, function () {
14744    this.requestBusinessHoursUnrender();
14745});
14746View.watch('initialEvents', ['dateProfile'], function (deps) {
14747    return this.fetchInitialEvents(deps.dateProfile);
14748});
14749View.watch('bindingEvents', ['initialEvents'], function (deps) {
14750    this.setEvents(deps.initialEvents);
14751    this.bindEventChanges();
14752}, function () {
14753    this.unbindEventChanges();
14754    this.unsetEvents();
14755});
14756View.watch('displayingEvents', ['displayingDates', 'hasEvents'], function () {
14757    this.requestEventsRender(this.get('currentEvents'));
14758}, function () {
14759    this.requestEventsUnrender();
14760});
14761View.watch('title', ['dateProfile'], function (deps) {
14762    return (this.title = this.computeTitle(deps.dateProfile)); // assign to View for legacy reasons
14763});
14764View.watch('legacyDateProps', ['dateProfile'], function (deps) {
14765    var calendar = this.calendar;
14766    var dateProfile = deps.dateProfile;
14767    // DEPRECATED, but we need to keep it updated...
14768    this.start = calendar.msToMoment(dateProfile.activeUnzonedRange.startMs, dateProfile.isRangeAllDay);
14769    this.end = calendar.msToMoment(dateProfile.activeUnzonedRange.endMs, dateProfile.isRangeAllDay);
14770    this.intervalStart = calendar.msToMoment(dateProfile.currentUnzonedRange.startMs, dateProfile.isRangeAllDay);
14771    this.intervalEnd = calendar.msToMoment(dateProfile.currentUnzonedRange.endMs, dateProfile.isRangeAllDay);
14772});
14773
14774
14775/***/ }),
14776/* 44 */
14777/***/ (function(module, exports, __webpack_require__) {
14778
14779Object.defineProperty(exports, "__esModule", { value: true });
14780var $ = __webpack_require__(3);
14781var util_1 = __webpack_require__(4);
14782var EventRenderer = /** @class */ (function () {
14783    function EventRenderer(component, fillRenderer) {
14784        this.view = component._getView();
14785        this.component = component;
14786        this.fillRenderer = fillRenderer;
14787    }
14788    EventRenderer.prototype.opt = function (name) {
14789        return this.view.opt(name);
14790    };
14791    // Updates values that rely on options and also relate to range
14792    EventRenderer.prototype.rangeUpdated = function () {
14793        var displayEventTime;
14794        var displayEventEnd;
14795        this.eventTimeFormat =
14796            this.opt('eventTimeFormat') ||
14797                this.opt('timeFormat') || // deprecated
14798                this.computeEventTimeFormat();
14799        displayEventTime = this.opt('displayEventTime');
14800        if (displayEventTime == null) {
14801            displayEventTime = this.computeDisplayEventTime(); // might be based off of range
14802        }
14803        displayEventEnd = this.opt('displayEventEnd');
14804        if (displayEventEnd == null) {
14805            displayEventEnd = this.computeDisplayEventEnd(); // might be based off of range
14806        }
14807        this.displayEventTime = displayEventTime;
14808        this.displayEventEnd = displayEventEnd;
14809    };
14810    EventRenderer.prototype.render = function (eventsPayload) {
14811        var dateProfile = this.component._getDateProfile();
14812        var eventDefId;
14813        var instanceGroup;
14814        var eventRanges;
14815        var bgRanges = [];
14816        var fgRanges = [];
14817        for (eventDefId in eventsPayload) {
14818            instanceGroup = eventsPayload[eventDefId];
14819            eventRanges = instanceGroup.sliceRenderRanges(dateProfile.activeUnzonedRange);
14820            if (instanceGroup.getEventDef().hasBgRendering()) {
14821                bgRanges.push.apply(bgRanges, eventRanges);
14822            }
14823            else {
14824                fgRanges.push.apply(fgRanges, eventRanges);
14825            }
14826        }
14827        this.renderBgRanges(bgRanges);
14828        this.renderFgRanges(fgRanges);
14829    };
14830    EventRenderer.prototype.unrender = function () {
14831        this.unrenderBgRanges();
14832        this.unrenderFgRanges();
14833    };
14834    EventRenderer.prototype.renderFgRanges = function (eventRanges) {
14835        var eventFootprints = this.component.eventRangesToEventFootprints(eventRanges);
14836        var segs = this.component.eventFootprintsToSegs(eventFootprints);
14837        // render an `.el` on each seg
14838        // returns a subset of the segs. segs that were actually rendered
14839        segs = this.renderFgSegEls(segs);
14840        if (this.renderFgSegs(segs) !== false) { // no failure?
14841            this.fgSegs = segs;
14842        }
14843    };
14844    EventRenderer.prototype.unrenderFgRanges = function () {
14845        this.unrenderFgSegs(this.fgSegs || []);
14846        this.fgSegs = null;
14847    };
14848    EventRenderer.prototype.renderBgRanges = function (eventRanges) {
14849        var eventFootprints = this.component.eventRangesToEventFootprints(eventRanges);
14850        var segs = this.component.eventFootprintsToSegs(eventFootprints);
14851        if (this.renderBgSegs(segs) !== false) { // no failure?
14852            this.bgSegs = segs;
14853        }
14854    };
14855    EventRenderer.prototype.unrenderBgRanges = function () {
14856        this.unrenderBgSegs();
14857        this.bgSegs = null;
14858    };
14859    EventRenderer.prototype.getSegs = function () {
14860        return (this.bgSegs || []).concat(this.fgSegs || []);
14861    };
14862    // Renders foreground event segments onto the grid
14863    EventRenderer.prototype.renderFgSegs = function (segs) {
14864        // subclasses must implement
14865        // segs already has rendered els, and has been filtered.
14866        return false; // signal failure if not implemented
14867    };
14868    // Unrenders all currently rendered foreground segments
14869    EventRenderer.prototype.unrenderFgSegs = function (segs) {
14870        // subclasses must implement
14871    };
14872    EventRenderer.prototype.renderBgSegs = function (segs) {
14873        var _this = this;
14874        if (this.fillRenderer) {
14875            this.fillRenderer.renderSegs('bgEvent', segs, {
14876                getClasses: function (seg) {
14877                    return _this.getBgClasses(seg.footprint.eventDef);
14878                },
14879                getCss: function (seg) {
14880                    return {
14881                        'background-color': _this.getBgColor(seg.footprint.eventDef)
14882                    };
14883                },
14884                filterEl: function (seg, el) {
14885                    return _this.filterEventRenderEl(seg.footprint, el);
14886                }
14887            });
14888        }
14889        else {
14890            return false; // signal failure if no fillRenderer
14891        }
14892    };
14893    EventRenderer.prototype.unrenderBgSegs = function () {
14894        if (this.fillRenderer) {
14895            this.fillRenderer.unrender('bgEvent');
14896        }
14897    };
14898    // Renders and assigns an `el` property for each foreground event segment.
14899    // Only returns segments that successfully rendered.
14900    EventRenderer.prototype.renderFgSegEls = function (segs, disableResizing) {
14901        var _this = this;
14902        if (disableResizing === void 0) { disableResizing = false; }
14903        var hasEventRenderHandlers = this.view.hasPublicHandlers('eventRender');
14904        var html = '';
14905        var renderedSegs = [];
14906        var i;
14907        if (segs.length) { // don't build an empty html string
14908            // build a large concatenation of event segment HTML
14909            for (i = 0; i < segs.length; i++) {
14910                this.beforeFgSegHtml(segs[i]);
14911                html += this.fgSegHtml(segs[i], disableResizing);
14912            }
14913            // Grab individual elements from the combined HTML string. Use each as the default rendering.
14914            // Then, compute the 'el' for each segment. An el might be null if the eventRender callback returned false.
14915            $(html).each(function (i, node) {
14916                var seg = segs[i];
14917                var el = $(node);
14918                if (hasEventRenderHandlers) { // optimization
14919                    el = _this.filterEventRenderEl(seg.footprint, el);
14920                }
14921                if (el) {
14922                    el.data('fc-seg', seg); // used by handlers
14923                    seg.el = el;
14924                    renderedSegs.push(seg);
14925                }
14926            });
14927        }
14928        return renderedSegs;
14929    };
14930    EventRenderer.prototype.beforeFgSegHtml = function (seg) {
14931    };
14932    // Generates the HTML for the default rendering of a foreground event segment. Used by renderFgSegEls()
14933    EventRenderer.prototype.fgSegHtml = function (seg, disableResizing) {
14934        // subclasses should implement
14935    };
14936    // Generic utility for generating the HTML classNames for an event segment's element
14937    EventRenderer.prototype.getSegClasses = function (seg, isDraggable, isResizable) {
14938        var classes = [
14939            'fc-event',
14940            seg.isStart ? 'fc-start' : 'fc-not-start',
14941            seg.isEnd ? 'fc-end' : 'fc-not-end'
14942        ].concat(this.getClasses(seg.footprint.eventDef));
14943        if (isDraggable) {
14944            classes.push('fc-draggable');
14945        }
14946        if (isResizable) {
14947            classes.push('fc-resizable');
14948        }
14949        // event is currently selected? attach a className.
14950        if (this.view.isEventDefSelected(seg.footprint.eventDef)) {
14951            classes.push('fc-selected');
14952        }
14953        return classes;
14954    };
14955    // Given an event and the default element used for rendering, returns the element that should actually be used.
14956    // Basically runs events and elements through the eventRender hook.
14957    EventRenderer.prototype.filterEventRenderEl = function (eventFootprint, el) {
14958        var legacy = eventFootprint.getEventLegacy();
14959        var custom = this.view.publiclyTrigger('eventRender', {
14960            context: legacy,
14961            args: [legacy, el, this.view]
14962        });
14963        if (custom === false) { // means don't render at all
14964            el = null;
14965        }
14966        else if (custom && custom !== true) {
14967            el = $(custom);
14968        }
14969        return el;
14970    };
14971    // Compute the text that should be displayed on an event's element.
14972    // `range` can be the Event object itself, or something range-like, with at least a `start`.
14973    // If event times are disabled, or the event has no time, will return a blank string.
14974    // If not specified, formatStr will default to the eventTimeFormat setting,
14975    // and displayEnd will default to the displayEventEnd setting.
14976    EventRenderer.prototype.getTimeText = function (eventFootprint, formatStr, displayEnd) {
14977        return this._getTimeText(eventFootprint.eventInstance.dateProfile.start, eventFootprint.eventInstance.dateProfile.end, eventFootprint.componentFootprint.isAllDay, formatStr, displayEnd);
14978    };
14979    EventRenderer.prototype._getTimeText = function (start, end, isAllDay, formatStr, displayEnd) {
14980        if (formatStr == null) {
14981            formatStr = this.eventTimeFormat;
14982        }
14983        if (displayEnd == null) {
14984            displayEnd = this.displayEventEnd;
14985        }
14986        if (this.displayEventTime && !isAllDay) {
14987            if (displayEnd && end) {
14988                return this.view.formatRange({ start: start, end: end }, false, // allDay
14989                formatStr);
14990            }
14991            else {
14992                return start.format(formatStr);
14993            }
14994        }
14995        return '';
14996    };
14997    EventRenderer.prototype.computeEventTimeFormat = function () {
14998        return this.opt('smallTimeFormat');
14999    };
15000    EventRenderer.prototype.computeDisplayEventTime = function () {
15001        return true;
15002    };
15003    EventRenderer.prototype.computeDisplayEventEnd = function () {
15004        return true;
15005    };
15006    EventRenderer.prototype.getBgClasses = function (eventDef) {
15007        var classNames = this.getClasses(eventDef);
15008        classNames.push('fc-bgevent');
15009        return classNames;
15010    };
15011    EventRenderer.prototype.getClasses = function (eventDef) {
15012        var objs = this.getStylingObjs(eventDef);
15013        var i;
15014        var classNames = [];
15015        for (i = 0; i < objs.length; i++) {
15016            classNames.push.apply(// append
15017            classNames, objs[i].eventClassName || objs[i].className || []);
15018        }
15019        return classNames;
15020    };
15021    // Utility for generating event skin-related CSS properties
15022    EventRenderer.prototype.getSkinCss = function (eventDef) {
15023        return {
15024            'background-color': this.getBgColor(eventDef),
15025            'border-color': this.getBorderColor(eventDef),
15026            color: this.getTextColor(eventDef)
15027        };
15028    };
15029    // Queries for caller-specified color, then falls back to default
15030    EventRenderer.prototype.getBgColor = function (eventDef) {
15031        var objs = this.getStylingObjs(eventDef);
15032        var i;
15033        var val;
15034        for (i = 0; i < objs.length && !val; i++) {
15035            val = objs[i].eventBackgroundColor || objs[i].eventColor ||
15036                objs[i].backgroundColor || objs[i].color;
15037        }
15038        if (!val) {
15039            val = this.opt('eventBackgroundColor') || this.opt('eventColor');
15040        }
15041        return val;
15042    };
15043    // Queries for caller-specified color, then falls back to default
15044    EventRenderer.prototype.getBorderColor = function (eventDef) {
15045        var objs = this.getStylingObjs(eventDef);
15046        var i;
15047        var val;
15048        for (i = 0; i < objs.length && !val; i++) {
15049            val = objs[i].eventBorderColor || objs[i].eventColor ||
15050                objs[i].borderColor || objs[i].color;
15051        }
15052        if (!val) {
15053            val = this.opt('eventBorderColor') || this.opt('eventColor');
15054        }
15055        return val;
15056    };
15057    // Queries for caller-specified color, then falls back to default
15058    EventRenderer.prototype.getTextColor = function (eventDef) {
15059        var objs = this.getStylingObjs(eventDef);
15060        var i;
15061        var val;
15062        for (i = 0; i < objs.length && !val; i++) {
15063            val = objs[i].eventTextColor ||
15064                objs[i].textColor;
15065        }
15066        if (!val) {
15067            val = this.opt('eventTextColor');
15068        }
15069        return val;
15070    };
15071    EventRenderer.prototype.getStylingObjs = function (eventDef) {
15072        var objs = this.getFallbackStylingObjs(eventDef);
15073        objs.unshift(eventDef);
15074        return objs;
15075    };
15076    EventRenderer.prototype.getFallbackStylingObjs = function (eventDef) {
15077        return [eventDef.source];
15078    };
15079    EventRenderer.prototype.sortEventSegs = function (segs) {
15080        segs.sort(util_1.proxy(this, 'compareEventSegs'));
15081    };
15082    // A cmp function for determining which segments should take visual priority
15083    EventRenderer.prototype.compareEventSegs = function (seg1, seg2) {
15084        var f1 = seg1.footprint;
15085        var f2 = seg2.footprint;
15086        var cf1 = f1.componentFootprint;
15087        var cf2 = f2.componentFootprint;
15088        var r1 = cf1.unzonedRange;
15089        var r2 = cf2.unzonedRange;
15090        return r1.startMs - r2.startMs || // earlier events go first
15091            (r2.endMs - r2.startMs) - (r1.endMs - r1.startMs) || // tie? longer events go first
15092            cf2.isAllDay - cf1.isAllDay || // tie? put all-day events first (booleans cast to 0/1)
15093            util_1.compareByFieldSpecs(f1.eventDef, f2.eventDef, this.view.eventOrderSpecs, f1.eventDef.miscProps, f2.eventDef.miscProps);
15094    };
15095    return EventRenderer;
15096}());
15097exports.default = EventRenderer;
15098
15099
15100/***/ }),
15101/* 45 */,
15102/* 46 */,
15103/* 47 */,
15104/* 48 */,
15105/* 49 */
15106/***/ (function(module, exports, __webpack_require__) {
15107
15108Object.defineProperty(exports, "__esModule", { value: true });
15109var moment_ext_1 = __webpack_require__(11);
15110// Plugin
15111// -------------------------------------------------------------------------------------------------
15112moment_ext_1.newMomentProto.format = function () {
15113    if (this._fullCalendar && arguments[0]) { // an enhanced moment? and a format string provided?
15114        return formatDate(this, arguments[0]); // our extended formatting
15115    }
15116    if (this._ambigTime) {
15117        return moment_ext_1.oldMomentFormat(englishMoment(this), 'YYYY-MM-DD');
15118    }
15119    if (this._ambigZone) {
15120        return moment_ext_1.oldMomentFormat(englishMoment(this), 'YYYY-MM-DD[T]HH:mm:ss');
15121    }
15122    if (this._fullCalendar) { // enhanced non-ambig moment?
15123        // moment.format() doesn't ensure english, but we want to.
15124        return moment_ext_1.oldMomentFormat(englishMoment(this));
15125    }
15126    return moment_ext_1.oldMomentProto.format.apply(this, arguments);
15127};
15128moment_ext_1.newMomentProto.toISOString = function () {
15129    if (this._ambigTime) {
15130        return moment_ext_1.oldMomentFormat(englishMoment(this), 'YYYY-MM-DD');
15131    }
15132    if (this._ambigZone) {
15133        return moment_ext_1.oldMomentFormat(englishMoment(this), 'YYYY-MM-DD[T]HH:mm:ss');
15134    }
15135    if (this._fullCalendar) { // enhanced non-ambig moment?
15136        // depending on browser, moment might not output english. ensure english.
15137        // https://github.com/moment/moment/blob/2.18.1/src/lib/moment/format.js#L22
15138        return moment_ext_1.oldMomentProto.toISOString.apply(englishMoment(this), arguments);
15139    }
15140    return moment_ext_1.oldMomentProto.toISOString.apply(this, arguments);
15141};
15142function englishMoment(mom) {
15143    if (mom.locale() !== 'en') {
15144        return mom.clone().locale('en');
15145    }
15146    return mom;
15147}
15148// Config
15149// ---------------------------------------------------------------------------------------------------------------------
15150/*
15151Inserted between chunks in the fake ("intermediate") formatting string.
15152Important that it passes as whitespace (\s) because moment often identifies non-standalone months
15153via a regexp with an \s.
15154*/
15155var PART_SEPARATOR = '\u000b'; // vertical tab
15156/*
15157Inserted as the first character of a literal-text chunk to indicate that the literal text is not actually literal text,
15158but rather, a "special" token that has custom rendering (see specialTokens map).
15159*/
15160var SPECIAL_TOKEN_MARKER = '\u001f'; // information separator 1
15161/*
15162Inserted at the beginning and end of a span of text that must have non-zero numeric characters.
15163Handling of these markers is done in a post-processing step at the very end of text rendering.
15164*/
15165var MAYBE_MARKER = '\u001e'; // information separator 2
15166var MAYBE_REGEXP = new RegExp(MAYBE_MARKER + '([^' + MAYBE_MARKER + ']*)' + MAYBE_MARKER, 'g'); // must be global
15167/*
15168Addition formatting tokens we want recognized
15169*/
15170var specialTokens = {
15171    t: function (date) {
15172        return moment_ext_1.oldMomentFormat(date, 'a').charAt(0);
15173    },
15174    T: function (date) {
15175        return moment_ext_1.oldMomentFormat(date, 'A').charAt(0);
15176    }
15177};
15178/*
15179The first characters of formatting tokens for units that are 1 day or larger.
15180`value` is for ranking relative size (lower means bigger).
15181`unit` is a normalized unit, used for comparing moments.
15182*/
15183var largeTokenMap = {
15184    Y: { value: 1, unit: 'year' },
15185    M: { value: 2, unit: 'month' },
15186    W: { value: 3, unit: 'week' },
15187    w: { value: 3, unit: 'week' },
15188    D: { value: 4, unit: 'day' },
15189    d: { value: 4, unit: 'day' } // day of week
15190};
15191// Single Date Formatting
15192// ---------------------------------------------------------------------------------------------------------------------
15193/*
15194Formats `date` with a Moment formatting string, but allow our non-zero areas and special token
15195*/
15196function formatDate(date, formatStr) {
15197    return renderFakeFormatString(getParsedFormatString(formatStr).fakeFormatString, date);
15198}
15199exports.formatDate = formatDate;
15200// Date Range Formatting
15201// -------------------------------------------------------------------------------------------------
15202// TODO: make it work with timezone offset
15203/*
15204Using a formatting string meant for a single date, generate a range string, like
15205"Sep 2 - 9 2013", that intelligently inserts a separator where the dates differ.
15206If the dates are the same as far as the format string is concerned, just return a single
15207rendering of one date, without any separator.
15208*/
15209function formatRange(date1, date2, formatStr, separator, isRTL) {
15210    var localeData;
15211    date1 = moment_ext_1.default.parseZone(date1);
15212    date2 = moment_ext_1.default.parseZone(date2);
15213    localeData = date1.localeData();
15214    // Expand localized format strings, like "LL" -> "MMMM D YYYY".
15215    // BTW, this is not important for `formatDate` because it is impossible to put custom tokens
15216    // or non-zero areas in Moment's localized format strings.
15217    formatStr = localeData.longDateFormat(formatStr) || formatStr;
15218    return renderParsedFormat(getParsedFormatString(formatStr), date1, date2, separator || ' - ', isRTL);
15219}
15220exports.formatRange = formatRange;
15221/*
15222Renders a range with an already-parsed format string.
15223*/
15224function renderParsedFormat(parsedFormat, date1, date2, separator, isRTL) {
15225    var sameUnits = parsedFormat.sameUnits;
15226    var unzonedDate1 = date1.clone().stripZone(); // for same-unit comparisons
15227    var unzonedDate2 = date2.clone().stripZone(); // "
15228    var renderedParts1 = renderFakeFormatStringParts(parsedFormat.fakeFormatString, date1);
15229    var renderedParts2 = renderFakeFormatStringParts(parsedFormat.fakeFormatString, date2);
15230    var leftI;
15231    var leftStr = '';
15232    var rightI;
15233    var rightStr = '';
15234    var middleI;
15235    var middleStr1 = '';
15236    var middleStr2 = '';
15237    var middleStr = '';
15238    // Start at the leftmost side of the formatting string and continue until you hit a token
15239    // that is not the same between dates.
15240    for (leftI = 0; leftI < sameUnits.length && (!sameUnits[leftI] || unzonedDate1.isSame(unzonedDate2, sameUnits[leftI])); leftI++) {
15241        leftStr += renderedParts1[leftI];
15242    }
15243    // Similarly, start at the rightmost side of the formatting string and move left
15244    for (rightI = sameUnits.length - 1; rightI > leftI && (!sameUnits[rightI] || unzonedDate1.isSame(unzonedDate2, sameUnits[rightI])); rightI--) {
15245        // If current chunk is on the boundary of unique date-content, and is a special-case
15246        // date-formatting postfix character, then don't consume it. Consider it unique date-content.
15247        // TODO: make configurable
15248        if (rightI - 1 === leftI && renderedParts1[rightI] === '.') {
15249            break;
15250        }
15251        rightStr = renderedParts1[rightI] + rightStr;
15252    }
15253    // The area in the middle is different for both of the dates.
15254    // Collect them distinctly so we can jam them together later.
15255    for (middleI = leftI; middleI <= rightI; middleI++) {
15256        middleStr1 += renderedParts1[middleI];
15257        middleStr2 += renderedParts2[middleI];
15258    }
15259    if (middleStr1 || middleStr2) {
15260        if (isRTL) {
15261            middleStr = middleStr2 + separator + middleStr1;
15262        }
15263        else {
15264            middleStr = middleStr1 + separator + middleStr2;
15265        }
15266    }
15267    return processMaybeMarkers(leftStr + middleStr + rightStr);
15268}
15269// Format String Parsing
15270// ---------------------------------------------------------------------------------------------------------------------
15271var parsedFormatStrCache = {};
15272/*
15273Returns a parsed format string, leveraging a cache.
15274*/
15275function getParsedFormatString(formatStr) {
15276    return parsedFormatStrCache[formatStr] ||
15277        (parsedFormatStrCache[formatStr] = parseFormatString(formatStr));
15278}
15279/*
15280Parses a format string into the following:
15281- fakeFormatString: a momentJS formatting string, littered with special control characters that get post-processed.
15282- sameUnits: for every part in fakeFormatString, if the part is a token, the value will be a unit string (like "day"),
15283  that indicates how similar a range's start & end must be in order to share the same formatted text.
15284  If not a token, then the value is null.
15285  Always a flat array (not nested liked "chunks").
15286*/
15287function parseFormatString(formatStr) {
15288    var chunks = chunkFormatString(formatStr);
15289    return {
15290        fakeFormatString: buildFakeFormatString(chunks),
15291        sameUnits: buildSameUnits(chunks)
15292    };
15293}
15294/*
15295Break the formatting string into an array of chunks.
15296A 'maybe' chunk will have nested chunks.
15297*/
15298function chunkFormatString(formatStr) {
15299    var chunks = [];
15300    var match;
15301    // TODO: more descrimination
15302    // \4 is a backreference to the first character of a multi-character set.
15303    var chunker = /\[([^\]]*)\]|\(([^\)]*)\)|(LTS|LT|(\w)\4*o?)|([^\w\[\(]+)/g;
15304    while ((match = chunker.exec(formatStr))) {
15305        if (match[1]) { // a literal string inside [ ... ]
15306            chunks.push.apply(chunks, // append
15307            splitStringLiteral(match[1]));
15308        }
15309        else if (match[2]) { // non-zero formatting inside ( ... )
15310            chunks.push({ maybe: chunkFormatString(match[2]) });
15311        }
15312        else if (match[3]) { // a formatting token
15313            chunks.push({ token: match[3] });
15314        }
15315        else if (match[5]) { // an unenclosed literal string
15316            chunks.push.apply(chunks, // append
15317            splitStringLiteral(match[5]));
15318        }
15319    }
15320    return chunks;
15321}
15322/*
15323Potentially splits a literal-text string into multiple parts. For special cases.
15324*/
15325function splitStringLiteral(s) {
15326    if (s === '. ') {
15327        return ['.', ' ']; // for locales with periods bound to the end of each year/month/date
15328    }
15329    else {
15330        return [s];
15331    }
15332}
15333/*
15334Given chunks parsed from a real format string, generate a fake (aka "intermediate") format string with special control
15335characters that will eventually be given to moment for formatting, and then post-processed.
15336*/
15337function buildFakeFormatString(chunks) {
15338    var parts = [];
15339    var i;
15340    var chunk;
15341    for (i = 0; i < chunks.length; i++) {
15342        chunk = chunks[i];
15343        if (typeof chunk === 'string') {
15344            parts.push('[' + chunk + ']');
15345        }
15346        else if (chunk.token) {
15347            if (chunk.token in specialTokens) {
15348                parts.push(SPECIAL_TOKEN_MARKER + // useful during post-processing
15349                    '[' + chunk.token + ']' // preserve as literal text
15350                );
15351            }
15352            else {
15353                parts.push(chunk.token); // unprotected text implies a format string
15354            }
15355        }
15356        else if (chunk.maybe) {
15357            parts.push(MAYBE_MARKER + // useful during post-processing
15358                buildFakeFormatString(chunk.maybe) +
15359                MAYBE_MARKER);
15360        }
15361    }
15362    return parts.join(PART_SEPARATOR);
15363}
15364/*
15365Given parsed chunks from a real formatting string, generates an array of unit strings (like "day") that indicate
15366in which regard two dates must be similar in order to share range formatting text.
15367The `chunks` can be nested (because of "maybe" chunks), however, the returned array will be flat.
15368*/
15369function buildSameUnits(chunks) {
15370    var units = [];
15371    var i;
15372    var chunk;
15373    var tokenInfo;
15374    for (i = 0; i < chunks.length; i++) {
15375        chunk = chunks[i];
15376        if (chunk.token) {
15377            tokenInfo = largeTokenMap[chunk.token.charAt(0)];
15378            units.push(tokenInfo ? tokenInfo.unit : 'second'); // default to a very strict same-second
15379        }
15380        else if (chunk.maybe) {
15381            units.push.apply(units, // append
15382            buildSameUnits(chunk.maybe));
15383        }
15384        else {
15385            units.push(null);
15386        }
15387    }
15388    return units;
15389}
15390// Rendering to text
15391// ---------------------------------------------------------------------------------------------------------------------
15392/*
15393Formats a date with a fake format string, post-processes the control characters, then returns.
15394*/
15395function renderFakeFormatString(fakeFormatString, date) {
15396    return processMaybeMarkers(renderFakeFormatStringParts(fakeFormatString, date).join(''));
15397}
15398/*
15399Formats a date into parts that will have been post-processed, EXCEPT for the "maybe" markers.
15400*/
15401function renderFakeFormatStringParts(fakeFormatString, date) {
15402    var parts = [];
15403    var fakeRender = moment_ext_1.oldMomentFormat(date, fakeFormatString);
15404    var fakeParts = fakeRender.split(PART_SEPARATOR);
15405    var i;
15406    var fakePart;
15407    for (i = 0; i < fakeParts.length; i++) {
15408        fakePart = fakeParts[i];
15409        if (fakePart.charAt(0) === SPECIAL_TOKEN_MARKER) {
15410            parts.push(
15411            // the literal string IS the token's name.
15412            // call special token's registered function.
15413            specialTokens[fakePart.substring(1)](date));
15414        }
15415        else {
15416            parts.push(fakePart);
15417        }
15418    }
15419    return parts;
15420}
15421/*
15422Accepts an almost-finally-formatted string and processes the "maybe" control characters, returning a new string.
15423*/
15424function processMaybeMarkers(s) {
15425    return s.replace(MAYBE_REGEXP, function (m0, m1) {
15426        if (m1.match(/[1-9]/)) { // any non-zero numeric characters?
15427            return m1;
15428        }
15429        else {
15430            return '';
15431        }
15432    });
15433}
15434// Misc Utils
15435// -------------------------------------------------------------------------------------------------
15436/*
15437Returns a unit string, either 'year', 'month', 'day', or null for the most granular formatting token in the string.
15438*/
15439function queryMostGranularFormatUnit(formatStr) {
15440    var chunks = chunkFormatString(formatStr);
15441    var i;
15442    var chunk;
15443    var candidate;
15444    var best;
15445    for (i = 0; i < chunks.length; i++) {
15446        chunk = chunks[i];
15447        if (chunk.token) {
15448            candidate = largeTokenMap[chunk.token.charAt(0)];
15449            if (candidate) {
15450                if (!best || candidate.value > best.value) {
15451                    best = candidate;
15452                }
15453            }
15454        }
15455    }
15456    if (best) {
15457        return best.unit;
15458    }
15459    return null;
15460}
15461exports.queryMostGranularFormatUnit = queryMostGranularFormatUnit;
15462
15463
15464/***/ }),
15465/* 50 */
15466/***/ (function(module, exports) {
15467
15468Object.defineProperty(exports, "__esModule", { value: true });
15469var EventRange = /** @class */ (function () {
15470    function EventRange(unzonedRange, eventDef, eventInstance) {
15471        this.unzonedRange = unzonedRange;
15472        this.eventDef = eventDef;
15473        if (eventInstance) {
15474            this.eventInstance = eventInstance;
15475        }
15476    }
15477    return EventRange;
15478}());
15479exports.default = EventRange;
15480
15481
15482/***/ }),
15483/* 51 */
15484/***/ (function(module, exports, __webpack_require__) {
15485
15486Object.defineProperty(exports, "__esModule", { value: true });
15487var tslib_1 = __webpack_require__(2);
15488var Class_1 = __webpack_require__(35);
15489var EmitterMixin_1 = __webpack_require__(13);
15490var ListenerMixin_1 = __webpack_require__(7);
15491var Model = /** @class */ (function (_super) {
15492    tslib_1.__extends(Model, _super);
15493    function Model() {
15494        var _this = _super.call(this) || this;
15495        _this._watchers = {};
15496        _this._props = {};
15497        _this.applyGlobalWatchers();
15498        _this.constructed();
15499        return _this;
15500    }
15501    Model.watch = function (name) {
15502        var args = [];
15503        for (var _i = 1; _i < arguments.length; _i++) {
15504            args[_i - 1] = arguments[_i];
15505        }
15506        // subclasses should make a masked-copy of the superclass's map
15507        // TODO: write test
15508        if (!this.prototype.hasOwnProperty('_globalWatchArgs')) {
15509            this.prototype._globalWatchArgs = Object.create(this.prototype._globalWatchArgs);
15510        }
15511        this.prototype._globalWatchArgs[name] = args;
15512    };
15513    Model.prototype.constructed = function () {
15514        // useful for monkeypatching. TODO: BaseClass?
15515    };
15516    Model.prototype.applyGlobalWatchers = function () {
15517        var map = this._globalWatchArgs;
15518        var name;
15519        for (name in map) {
15520            this.watch.apply(this, [name].concat(map[name]));
15521        }
15522    };
15523    Model.prototype.has = function (name) {
15524        return name in this._props;
15525    };
15526    Model.prototype.get = function (name) {
15527        if (name === undefined) {
15528            return this._props;
15529        }
15530        return this._props[name];
15531    };
15532    Model.prototype.set = function (name, val) {
15533        var newProps;
15534        if (typeof name === 'string') {
15535            newProps = {};
15536            newProps[name] = val === undefined ? null : val;
15537        }
15538        else {
15539            newProps = name;
15540        }
15541        this.setProps(newProps);
15542    };
15543    Model.prototype.reset = function (newProps) {
15544        var oldProps = this._props;
15545        var changeset = {}; // will have undefined's to signal unsets
15546        var name;
15547        for (name in oldProps) {
15548            changeset[name] = undefined;
15549        }
15550        for (name in newProps) {
15551            changeset[name] = newProps[name];
15552        }
15553        this.setProps(changeset);
15554    };
15555    Model.prototype.unset = function (name) {
15556        var newProps = {};
15557        var names;
15558        var i;
15559        if (typeof name === 'string') {
15560            names = [name];
15561        }
15562        else {
15563            names = name;
15564        }
15565        for (i = 0; i < names.length; i++) {
15566            newProps[names[i]] = undefined;
15567        }
15568        this.setProps(newProps);
15569    };
15570    Model.prototype.setProps = function (newProps) {
15571        var changedProps = {};
15572        var changedCnt = 0;
15573        var name;
15574        var val;
15575        for (name in newProps) {
15576            val = newProps[name];
15577            // a change in value?
15578            // if an object, don't check equality, because might have been mutated internally.
15579            // TODO: eventually enforce immutability.
15580            if (typeof val === 'object' ||
15581                val !== this._props[name]) {
15582                changedProps[name] = val;
15583                changedCnt++;
15584            }
15585        }
15586        if (changedCnt) {
15587            this.trigger('before:batchChange', changedProps);
15588            for (name in changedProps) {
15589                val = changedProps[name];
15590                this.trigger('before:change', name, val);
15591                this.trigger('before:change:' + name, val);
15592            }
15593            for (name in changedProps) {
15594                val = changedProps[name];
15595                if (val === undefined) {
15596                    delete this._props[name];
15597                }
15598                else {
15599                    this._props[name] = val;
15600                }
15601                this.trigger('change:' + name, val);
15602                this.trigger('change', name, val);
15603            }
15604            this.trigger('batchChange', changedProps);
15605        }
15606    };
15607    Model.prototype.watch = function (name, depList, startFunc, stopFunc) {
15608        var _this = this;
15609        this.unwatch(name);
15610        this._watchers[name] = this._watchDeps(depList, function (deps) {
15611            var res = startFunc.call(_this, deps);
15612            if (res && res.then) {
15613                _this.unset(name); // put in an unset state while resolving
15614                res.then(function (val) {
15615                    _this.set(name, val);
15616                });
15617            }
15618            else {
15619                _this.set(name, res);
15620            }
15621        }, function (deps) {
15622            _this.unset(name);
15623            if (stopFunc) {
15624                stopFunc.call(_this, deps);
15625            }
15626        });
15627    };
15628    Model.prototype.unwatch = function (name) {
15629        var watcher = this._watchers[name];
15630        if (watcher) {
15631            delete this._watchers[name];
15632            watcher.teardown();
15633        }
15634    };
15635    Model.prototype._watchDeps = function (depList, startFunc, stopFunc) {
15636        var _this = this;
15637        var queuedChangeCnt = 0;
15638        var depCnt = depList.length;
15639        var satisfyCnt = 0;
15640        var values = {}; // what's passed as the `deps` arguments
15641        var bindTuples = []; // array of [ eventName, handlerFunc ] arrays
15642        var isCallingStop = false;
15643        var onBeforeDepChange = function (depName, val, isOptional) {
15644            queuedChangeCnt++;
15645            if (queuedChangeCnt === 1) { // first change to cause a "stop" ?
15646                if (satisfyCnt === depCnt) { // all deps previously satisfied?
15647                    isCallingStop = true;
15648                    stopFunc(values);
15649                    isCallingStop = false;
15650                }
15651            }
15652        };
15653        var onDepChange = function (depName, val, isOptional) {
15654            if (val === undefined) { // unsetting a value?
15655                // required dependency that was previously set?
15656                if (!isOptional && values[depName] !== undefined) {
15657                    satisfyCnt--;
15658                }
15659                delete values[depName];
15660            }
15661            else { // setting a value?
15662                // required dependency that was previously unset?
15663                if (!isOptional && values[depName] === undefined) {
15664                    satisfyCnt++;
15665                }
15666                values[depName] = val;
15667            }
15668            queuedChangeCnt--;
15669            if (!queuedChangeCnt) { // last change to cause a "start"?
15670                // now finally satisfied or satisfied all along?
15671                if (satisfyCnt === depCnt) {
15672                    // if the stopFunc initiated another value change, ignore it.
15673                    // it will be processed by another change event anyway.
15674                    if (!isCallingStop) {
15675                        startFunc(values);
15676                    }
15677                }
15678            }
15679        };
15680        // intercept for .on() that remembers handlers
15681        var bind = function (eventName, handler) {
15682            _this.on(eventName, handler);
15683            bindTuples.push([eventName, handler]);
15684        };
15685        // listen to dependency changes
15686        depList.forEach(function (depName) {
15687            var isOptional = false;
15688            if (depName.charAt(0) === '?') { // TODO: more DRY
15689                depName = depName.substring(1);
15690                isOptional = true;
15691            }
15692            bind('before:change:' + depName, function (val) {
15693                onBeforeDepChange(depName, val, isOptional);
15694            });
15695            bind('change:' + depName, function (val) {
15696                onDepChange(depName, val, isOptional);
15697            });
15698        });
15699        // process current dependency values
15700        depList.forEach(function (depName) {
15701            var isOptional = false;
15702            if (depName.charAt(0) === '?') { // TODO: more DRY
15703                depName = depName.substring(1);
15704                isOptional = true;
15705            }
15706            if (_this.has(depName)) {
15707                values[depName] = _this.get(depName);
15708                satisfyCnt++;
15709            }
15710            else if (isOptional) {
15711                satisfyCnt++;
15712            }
15713        });
15714        // initially satisfied
15715        if (satisfyCnt === depCnt) {
15716            startFunc(values);
15717        }
15718        return {
15719            teardown: function () {
15720                // remove all handlers
15721                for (var i = 0; i < bindTuples.length; i++) {
15722                    _this.off(bindTuples[i][0], bindTuples[i][1]);
15723                }
15724                bindTuples = null;
15725                // was satisfied, so call stopFunc
15726                if (satisfyCnt === depCnt) {
15727                    stopFunc();
15728                }
15729            },
15730            flash: function () {
15731                if (satisfyCnt === depCnt) {
15732                    stopFunc();
15733                    startFunc(values);
15734                }
15735            }
15736        };
15737    };
15738    Model.prototype.flash = function (name) {
15739        var watcher = this._watchers[name];
15740        if (watcher) {
15741            watcher.flash();
15742        }
15743    };
15744    return Model;
15745}(Class_1.default));
15746exports.default = Model;
15747Model.prototype._globalWatchArgs = {}; // mutation protection in Model.watch
15748EmitterMixin_1.default.mixInto(Model);
15749ListenerMixin_1.default.mixInto(Model);
15750
15751
15752/***/ }),
15753/* 52 */
15754/***/ (function(module, exports, __webpack_require__) {
15755
15756/*
15757USAGE:
15758  import { default as ParsableModelMixin, ParsableModelInterface } from './ParsableModelMixin'
15759in class:
15760  applyProps: ParsableModelInterface['applyProps']
15761  applyManualStandardProps: ParsableModelInterface['applyManualStandardProps']
15762  applyMiscProps: ParsableModelInterface['applyMiscProps']
15763  isStandardProp: ParsableModelInterface['isStandardProp']
15764  static defineStandardProps = ParsableModelMixin.defineStandardProps
15765  static copyVerbatimStandardProps = ParsableModelMixin.copyVerbatimStandardProps
15766after class:
15767  ParsableModelMixin.mixInto(TheClass)
15768*/
15769Object.defineProperty(exports, "__esModule", { value: true });
15770var tslib_1 = __webpack_require__(2);
15771var util_1 = __webpack_require__(4);
15772var Mixin_1 = __webpack_require__(15);
15773var ParsableModelMixin = /** @class */ (function (_super) {
15774    tslib_1.__extends(ParsableModelMixin, _super);
15775    function ParsableModelMixin() {
15776        return _super !== null && _super.apply(this, arguments) || this;
15777    }
15778    ParsableModelMixin.defineStandardProps = function (propDefs) {
15779        var proto = this.prototype;
15780        if (!proto.hasOwnProperty('standardPropMap')) {
15781            proto.standardPropMap = Object.create(proto.standardPropMap);
15782        }
15783        util_1.copyOwnProps(propDefs, proto.standardPropMap);
15784    };
15785    ParsableModelMixin.copyVerbatimStandardProps = function (src, dest) {
15786        var map = this.prototype.standardPropMap;
15787        var propName;
15788        for (propName in map) {
15789            if (src[propName] != null && // in the src object?
15790                map[propName] === true // false means "copy verbatim"
15791            ) {
15792                dest[propName] = src[propName];
15793            }
15794        }
15795    };
15796    /*
15797    Returns true/false for success.
15798    Meant to be only called ONCE, at object creation.
15799    */
15800    ParsableModelMixin.prototype.applyProps = function (rawProps) {
15801        var standardPropMap = this.standardPropMap;
15802        var manualProps = {};
15803        var miscProps = {};
15804        var propName;
15805        for (propName in rawProps) {
15806            if (standardPropMap[propName] === true) { // copy verbatim
15807                this[propName] = rawProps[propName];
15808            }
15809            else if (standardPropMap[propName] === false) {
15810                manualProps[propName] = rawProps[propName];
15811            }
15812            else {
15813                miscProps[propName] = rawProps[propName];
15814            }
15815        }
15816        this.applyMiscProps(miscProps);
15817        return this.applyManualStandardProps(manualProps);
15818    };
15819    /*
15820    If subclasses override, they must call this supermethod and return the boolean response.
15821    Meant to be only called ONCE, at object creation.
15822    */
15823    ParsableModelMixin.prototype.applyManualStandardProps = function (rawProps) {
15824        return true;
15825    };
15826    /*
15827    Can be called even after initial object creation.
15828    */
15829    ParsableModelMixin.prototype.applyMiscProps = function (rawProps) {
15830        // subclasses can implement
15831    };
15832    /*
15833    TODO: why is this a method when defineStandardProps is static
15834    */
15835    ParsableModelMixin.prototype.isStandardProp = function (propName) {
15836        return propName in this.standardPropMap;
15837    };
15838    return ParsableModelMixin;
15839}(Mixin_1.default));
15840exports.default = ParsableModelMixin;
15841ParsableModelMixin.prototype.standardPropMap = {}; // will be cloned by defineStandardProps
15842
15843
15844/***/ }),
15845/* 53 */
15846/***/ (function(module, exports) {
15847
15848Object.defineProperty(exports, "__esModule", { value: true });
15849var EventInstance = /** @class */ (function () {
15850    function EventInstance(def, dateProfile) {
15851        this.def = def;
15852        this.dateProfile = dateProfile;
15853    }
15854    EventInstance.prototype.toLegacy = function () {
15855        var dateProfile = this.dateProfile;
15856        var obj = this.def.toLegacy();
15857        obj.start = dateProfile.start.clone();
15858        obj.end = dateProfile.end ? dateProfile.end.clone() : null;
15859        return obj;
15860    };
15861    return EventInstance;
15862}());
15863exports.default = EventInstance;
15864
15865
15866/***/ }),
15867/* 54 */
15868/***/ (function(module, exports, __webpack_require__) {
15869
15870Object.defineProperty(exports, "__esModule", { value: true });
15871var tslib_1 = __webpack_require__(2);
15872var $ = __webpack_require__(3);
15873var moment = __webpack_require__(0);
15874var EventDef_1 = __webpack_require__(37);
15875var EventInstance_1 = __webpack_require__(53);
15876var EventDateProfile_1 = __webpack_require__(16);
15877var RecurringEventDef = /** @class */ (function (_super) {
15878    tslib_1.__extends(RecurringEventDef, _super);
15879    function RecurringEventDef() {
15880        return _super !== null && _super.apply(this, arguments) || this;
15881    }
15882    RecurringEventDef.prototype.isAllDay = function () {
15883        return !this.startTime && !this.endTime;
15884    };
15885    RecurringEventDef.prototype.buildInstances = function (unzonedRange) {
15886        var calendar = this.source.calendar;
15887        var unzonedDate = unzonedRange.getStart();
15888        var unzonedEnd = unzonedRange.getEnd();
15889        var zonedDayStart;
15890        var instanceStart;
15891        var instanceEnd;
15892        var instances = [];
15893        while (unzonedDate.isBefore(unzonedEnd)) {
15894            // if everyday, or this particular day-of-week
15895            if (!this.dowHash || this.dowHash[unzonedDate.day()]) {
15896                zonedDayStart = calendar.applyTimezone(unzonedDate);
15897                instanceStart = zonedDayStart.clone();
15898                instanceEnd = null;
15899                if (this.startTime) {
15900                    instanceStart.time(this.startTime);
15901                }
15902                else {
15903                    instanceStart.stripTime();
15904                }
15905                if (this.endTime) {
15906                    instanceEnd = zonedDayStart.clone().time(this.endTime);
15907                }
15908                instances.push(new EventInstance_1.default(this, // definition
15909                new EventDateProfile_1.default(instanceStart, instanceEnd, calendar)));
15910            }
15911            unzonedDate.add(1, 'days');
15912        }
15913        return instances;
15914    };
15915    RecurringEventDef.prototype.setDow = function (dowNumbers) {
15916        if (!this.dowHash) {
15917            this.dowHash = {};
15918        }
15919        for (var i = 0; i < dowNumbers.length; i++) {
15920            this.dowHash[dowNumbers[i]] = true;
15921        }
15922    };
15923    RecurringEventDef.prototype.clone = function () {
15924        var def = _super.prototype.clone.call(this);
15925        if (def.startTime) {
15926            def.startTime = moment.duration(this.startTime);
15927        }
15928        if (def.endTime) {
15929            def.endTime = moment.duration(this.endTime);
15930        }
15931        if (this.dowHash) {
15932            def.dowHash = $.extend({}, this.dowHash);
15933        }
15934        return def;
15935    };
15936    return RecurringEventDef;
15937}(EventDef_1.default));
15938exports.default = RecurringEventDef;
15939/*
15940HACK to work with TypeScript mixins
15941NOTE: if super-method fails, should still attempt to apply
15942*/
15943RecurringEventDef.prototype.applyProps = function (rawProps) {
15944    var superSuccess = EventDef_1.default.prototype.applyProps.call(this, rawProps);
15945    if (rawProps.start) {
15946        this.startTime = moment.duration(rawProps.start);
15947    }
15948    if (rawProps.end) {
15949        this.endTime = moment.duration(rawProps.end);
15950    }
15951    if (rawProps.dow) {
15952        this.setDow(rawProps.dow);
15953    }
15954    return superSuccess;
15955};
15956// Parsing
15957// ---------------------------------------------------------------------------------------------------------------------
15958RecurringEventDef.defineStandardProps({
15959    start: false,
15960    end: false,
15961    dow: false
15962});
15963
15964
15965/***/ }),
15966/* 55 */
15967/***/ (function(module, exports, __webpack_require__) {
15968
15969Object.defineProperty(exports, "__esModule", { value: true });
15970var moment = __webpack_require__(0);
15971var util_1 = __webpack_require__(4);
15972var UnzonedRange_1 = __webpack_require__(5);
15973var DateProfileGenerator = /** @class */ (function () {
15974    function DateProfileGenerator(_view) {
15975        this._view = _view;
15976    }
15977    DateProfileGenerator.prototype.opt = function (name) {
15978        return this._view.opt(name);
15979    };
15980    DateProfileGenerator.prototype.trimHiddenDays = function (unzonedRange) {
15981        return this._view.trimHiddenDays(unzonedRange);
15982    };
15983    DateProfileGenerator.prototype.msToUtcMoment = function (ms, forceAllDay) {
15984        return this._view.calendar.msToUtcMoment(ms, forceAllDay);
15985    };
15986    /* Date Range Computation
15987    ------------------------------------------------------------------------------------------------------------------*/
15988    // Builds a structure with info about what the dates/ranges will be for the "prev" view.
15989    DateProfileGenerator.prototype.buildPrev = function (currentDateProfile) {
15990        var prevDate = currentDateProfile.date.clone()
15991            .startOf(currentDateProfile.currentRangeUnit)
15992            .subtract(currentDateProfile.dateIncrement);
15993        return this.build(prevDate, -1);
15994    };
15995    // Builds a structure with info about what the dates/ranges will be for the "next" view.
15996    DateProfileGenerator.prototype.buildNext = function (currentDateProfile) {
15997        var nextDate = currentDateProfile.date.clone()
15998            .startOf(currentDateProfile.currentRangeUnit)
15999            .add(currentDateProfile.dateIncrement);
16000        return this.build(nextDate, 1);
16001    };
16002    // Builds a structure holding dates/ranges for rendering around the given date.
16003    // Optional direction param indicates whether the date is being incremented/decremented
16004    // from its previous value. decremented = -1, incremented = 1 (default).
16005    DateProfileGenerator.prototype.build = function (date, direction, forceToValid) {
16006        if (forceToValid === void 0) { forceToValid = false; }
16007        var isDateAllDay = !date.hasTime();
16008        var validUnzonedRange;
16009        var minTime = null;
16010        var maxTime = null;
16011        var currentInfo;
16012        var isRangeAllDay;
16013        var renderUnzonedRange;
16014        var activeUnzonedRange;
16015        var isValid;
16016        validUnzonedRange = this.buildValidRange();
16017        validUnzonedRange = this.trimHiddenDays(validUnzonedRange);
16018        if (forceToValid) {
16019            date = this.msToUtcMoment(validUnzonedRange.constrainDate(date), // returns MS
16020            isDateAllDay);
16021        }
16022        currentInfo = this.buildCurrentRangeInfo(date, direction);
16023        isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit);
16024        renderUnzonedRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.unzonedRange), currentInfo.unit, isRangeAllDay);
16025        renderUnzonedRange = this.trimHiddenDays(renderUnzonedRange);
16026        activeUnzonedRange = renderUnzonedRange.clone();
16027        if (!this.opt('showNonCurrentDates')) {
16028            activeUnzonedRange = activeUnzonedRange.intersect(currentInfo.unzonedRange);
16029        }
16030        minTime = moment.duration(this.opt('minTime'));
16031        maxTime = moment.duration(this.opt('maxTime'));
16032        activeUnzonedRange = this.adjustActiveRange(activeUnzonedRange, minTime, maxTime);
16033        activeUnzonedRange = activeUnzonedRange.intersect(validUnzonedRange); // might return null
16034        if (activeUnzonedRange) {
16035            date = this.msToUtcMoment(activeUnzonedRange.constrainDate(date), // returns MS
16036            isDateAllDay);
16037        }
16038        // it's invalid if the originally requested date is not contained,
16039        // or if the range is completely outside of the valid range.
16040        isValid = currentInfo.unzonedRange.intersectsWith(validUnzonedRange);
16041        return {
16042            // constraint for where prev/next operations can go and where events can be dragged/resized to.
16043            // an object with optional start and end properties.
16044            validUnzonedRange: validUnzonedRange,
16045            // range the view is formally responsible for.
16046            // for example, a month view might have 1st-31st, excluding padded dates
16047            currentUnzonedRange: currentInfo.unzonedRange,
16048            // name of largest unit being displayed, like "month" or "week"
16049            currentRangeUnit: currentInfo.unit,
16050            isRangeAllDay: isRangeAllDay,
16051            // dates that display events and accept drag-n-drop
16052            // will be `null` if no dates accept events
16053            activeUnzonedRange: activeUnzonedRange,
16054            // date range with a rendered skeleton
16055            // includes not-active days that need some sort of DOM
16056            renderUnzonedRange: renderUnzonedRange,
16057            // Duration object that denotes the first visible time of any given day
16058            minTime: minTime,
16059            // Duration object that denotes the exclusive visible end time of any given day
16060            maxTime: maxTime,
16061            isValid: isValid,
16062            date: date,
16063            // how far the current date will move for a prev/next operation
16064            dateIncrement: this.buildDateIncrement(currentInfo.duration)
16065            // pass a fallback (might be null) ^
16066        };
16067    };
16068    // Builds an object with optional start/end properties.
16069    // Indicates the minimum/maximum dates to display.
16070    // not responsible for trimming hidden days.
16071    DateProfileGenerator.prototype.buildValidRange = function () {
16072        return this._view.getUnzonedRangeOption('validRange', this._view.calendar.getNow()) ||
16073            new UnzonedRange_1.default(); // completely open-ended
16074    };
16075    // Builds a structure with info about the "current" range, the range that is
16076    // highlighted as being the current month for example.
16077    // See build() for a description of `direction`.
16078    // Guaranteed to have `range` and `unit` properties. `duration` is optional.
16079    // TODO: accept a MS-time instead of a moment `date`?
16080    DateProfileGenerator.prototype.buildCurrentRangeInfo = function (date, direction) {
16081        var viewSpec = this._view.viewSpec;
16082        var duration = null;
16083        var unit = null;
16084        var unzonedRange = null;
16085        var dayCount;
16086        if (viewSpec.duration) {
16087            duration = viewSpec.duration;
16088            unit = viewSpec.durationUnit;
16089            unzonedRange = this.buildRangeFromDuration(date, direction, duration, unit);
16090        }
16091        else if ((dayCount = this.opt('dayCount'))) {
16092            unit = 'day';
16093            unzonedRange = this.buildRangeFromDayCount(date, direction, dayCount);
16094        }
16095        else if ((unzonedRange = this.buildCustomVisibleRange(date))) {
16096            unit = util_1.computeGreatestUnit(unzonedRange.getStart(), unzonedRange.getEnd());
16097        }
16098        else {
16099            duration = this.getFallbackDuration();
16100            unit = util_1.computeGreatestUnit(duration);
16101            unzonedRange = this.buildRangeFromDuration(date, direction, duration, unit);
16102        }
16103        return { duration: duration, unit: unit, unzonedRange: unzonedRange };
16104    };
16105    DateProfileGenerator.prototype.getFallbackDuration = function () {
16106        return moment.duration({ days: 1 });
16107    };
16108    // Returns a new activeUnzonedRange to have time values (un-ambiguate)
16109    // minTime or maxTime causes the range to expand.
16110    DateProfileGenerator.prototype.adjustActiveRange = function (unzonedRange, minTime, maxTime) {
16111        var start = unzonedRange.getStart();
16112        var end = unzonedRange.getEnd();
16113        if (this._view.usesMinMaxTime) {
16114            if (minTime < 0) {
16115                start.time(0).add(minTime);
16116            }
16117            if (maxTime > 24 * 60 * 60 * 1000) { // beyond 24 hours?
16118                end.time(maxTime - (24 * 60 * 60 * 1000));
16119            }
16120        }
16121        return new UnzonedRange_1.default(start, end);
16122    };
16123    // Builds the "current" range when it is specified as an explicit duration.
16124    // `unit` is the already-computed computeGreatestUnit value of duration.
16125    // TODO: accept a MS-time instead of a moment `date`?
16126    DateProfileGenerator.prototype.buildRangeFromDuration = function (date, direction, duration, unit) {
16127        var alignment = this.opt('dateAlignment');
16128        var dateIncrementInput;
16129        var dateIncrementDuration;
16130        var start;
16131        var end;
16132        var res;
16133        // compute what the alignment should be
16134        if (!alignment) {
16135            dateIncrementInput = this.opt('dateIncrement');
16136            if (dateIncrementInput) {
16137                dateIncrementDuration = moment.duration(dateIncrementInput);
16138                // use the smaller of the two units
16139                if (dateIncrementDuration < duration) {
16140                    alignment = util_1.computeDurationGreatestUnit(dateIncrementDuration, dateIncrementInput);
16141                }
16142                else {
16143                    alignment = unit;
16144                }
16145            }
16146            else {
16147                alignment = unit;
16148            }
16149        }
16150        // if the view displays a single day or smaller
16151        if (duration.as('days') <= 1) {
16152            if (this._view.isHiddenDay(start)) {
16153                start = this._view.skipHiddenDays(start, direction);
16154                start.startOf('day');
16155            }
16156        }
16157        function computeRes() {
16158            start = date.clone().startOf(alignment);
16159            end = start.clone().add(duration);
16160            res = new UnzonedRange_1.default(start, end);
16161        }
16162        computeRes();
16163        // if range is completely enveloped by hidden days, go past the hidden days
16164        if (!this.trimHiddenDays(res)) {
16165            date = this._view.skipHiddenDays(date, direction);
16166            computeRes();
16167        }
16168        return res;
16169    };
16170    // Builds the "current" range when a dayCount is specified.
16171    // TODO: accept a MS-time instead of a moment `date`?
16172    DateProfileGenerator.prototype.buildRangeFromDayCount = function (date, direction, dayCount) {
16173        var customAlignment = this.opt('dateAlignment');
16174        var runningCount = 0;
16175        var start;
16176        var end;
16177        if (customAlignment || direction !== -1) {
16178            start = date.clone();
16179            if (customAlignment) {
16180                start.startOf(customAlignment);
16181            }
16182            start.startOf('day');
16183            start = this._view.skipHiddenDays(start);
16184            end = start.clone();
16185            do {
16186                end.add(1, 'day');
16187                if (!this._view.isHiddenDay(end)) {
16188                    runningCount++;
16189                }
16190            } while (runningCount < dayCount);
16191        }
16192        else {
16193            end = date.clone().startOf('day').add(1, 'day');
16194            end = this._view.skipHiddenDays(end, -1, true);
16195            start = end.clone();
16196            do {
16197                start.add(-1, 'day');
16198                if (!this._view.isHiddenDay(start)) {
16199                    runningCount++;
16200                }
16201            } while (runningCount < dayCount);
16202        }
16203        return new UnzonedRange_1.default(start, end);
16204    };
16205    // Builds a normalized range object for the "visible" range,
16206    // which is a way to define the currentUnzonedRange and activeUnzonedRange at the same time.
16207    // TODO: accept a MS-time instead of a moment `date`?
16208    DateProfileGenerator.prototype.buildCustomVisibleRange = function (date) {
16209        var visibleUnzonedRange = this._view.getUnzonedRangeOption('visibleRange', this._view.calendar.applyTimezone(date) // correct zone. also generates new obj that avoids mutations
16210        );
16211        if (visibleUnzonedRange && (visibleUnzonedRange.startMs == null || visibleUnzonedRange.endMs == null)) {
16212            return null;
16213        }
16214        return visibleUnzonedRange;
16215    };
16216    // Computes the range that will represent the element/cells for *rendering*,
16217    // but which may have voided days/times.
16218    // not responsible for trimming hidden days.
16219    DateProfileGenerator.prototype.buildRenderRange = function (currentUnzonedRange, currentRangeUnit, isRangeAllDay) {
16220        return currentUnzonedRange.clone();
16221    };
16222    // Compute the duration value that should be added/substracted to the current date
16223    // when a prev/next operation happens.
16224    DateProfileGenerator.prototype.buildDateIncrement = function (fallback) {
16225        var dateIncrementInput = this.opt('dateIncrement');
16226        var customAlignment;
16227        if (dateIncrementInput) {
16228            return moment.duration(dateIncrementInput);
16229        }
16230        else if ((customAlignment = this.opt('dateAlignment'))) {
16231            return moment.duration(1, customAlignment);
16232        }
16233        else if (fallback) {
16234            return fallback;
16235        }
16236        else {
16237            return moment.duration({ days: 1 });
16238        }
16239    };
16240    return DateProfileGenerator;
16241}());
16242exports.default = DateProfileGenerator;
16243
16244
16245/***/ }),
16246/* 56 */
16247/***/ (function(module, exports, __webpack_require__) {
16248
16249Object.defineProperty(exports, "__esModule", { value: true });
16250var tslib_1 = __webpack_require__(2);
16251var $ = __webpack_require__(3);
16252var util_1 = __webpack_require__(4);
16253var Promise_1 = __webpack_require__(21);
16254var EventSource_1 = __webpack_require__(6);
16255var SingleEventDef_1 = __webpack_require__(9);
16256var ArrayEventSource = /** @class */ (function (_super) {
16257    tslib_1.__extends(ArrayEventSource, _super);
16258    function ArrayEventSource(calendar) {
16259        var _this = _super.call(this, calendar) || this;
16260        _this.eventDefs = []; // for if setRawEventDefs is never called
16261        return _this;
16262    }
16263    ArrayEventSource.parse = function (rawInput, calendar) {
16264        var rawProps;
16265        // normalize raw input
16266        if ($.isArray(rawInput.events)) { // extended form
16267            rawProps = rawInput;
16268        }
16269        else if ($.isArray(rawInput)) { // short form
16270            rawProps = { events: rawInput };
16271        }
16272        if (rawProps) {
16273            return EventSource_1.default.parse.call(this, rawProps, calendar);
16274        }
16275        return false;
16276    };
16277    ArrayEventSource.prototype.setRawEventDefs = function (rawEventDefs) {
16278        this.rawEventDefs = rawEventDefs;
16279        this.eventDefs = this.parseEventDefs(rawEventDefs);
16280    };
16281    ArrayEventSource.prototype.fetch = function (start, end, timezone) {
16282        var eventDefs = this.eventDefs;
16283        var i;
16284        if (this.currentTimezone != null &&
16285            this.currentTimezone !== timezone) {
16286            for (i = 0; i < eventDefs.length; i++) {
16287                if (eventDefs[i] instanceof SingleEventDef_1.default) {
16288                    eventDefs[i].rezone();
16289                }
16290            }
16291        }
16292        this.currentTimezone = timezone;
16293        return Promise_1.default.resolve(eventDefs);
16294    };
16295    ArrayEventSource.prototype.addEventDef = function (eventDef) {
16296        this.eventDefs.push(eventDef);
16297    };
16298    /*
16299    eventDefId already normalized to a string
16300    */
16301    ArrayEventSource.prototype.removeEventDefsById = function (eventDefId) {
16302        return util_1.removeMatching(this.eventDefs, function (eventDef) {
16303            return eventDef.id === eventDefId;
16304        });
16305    };
16306    ArrayEventSource.prototype.removeAllEventDefs = function () {
16307        this.eventDefs = [];
16308    };
16309    ArrayEventSource.prototype.getPrimitive = function () {
16310        return this.rawEventDefs;
16311    };
16312    ArrayEventSource.prototype.applyManualStandardProps = function (rawProps) {
16313        var superSuccess = _super.prototype.applyManualStandardProps.call(this, rawProps);
16314        this.setRawEventDefs(rawProps.events);
16315        return superSuccess;
16316    };
16317    return ArrayEventSource;
16318}(EventSource_1.default));
16319exports.default = ArrayEventSource;
16320ArrayEventSource.defineStandardProps({
16321    events: false // don't automatically transfer
16322});
16323
16324
16325/***/ }),
16326/* 57 */
16327/***/ (function(module, exports, __webpack_require__) {
16328
16329Object.defineProperty(exports, "__esModule", { value: true });
16330var StandardTheme_1 = __webpack_require__(221);
16331var JqueryUiTheme_1 = __webpack_require__(222);
16332var themeClassHash = {};
16333function defineThemeSystem(themeName, themeClass) {
16334    themeClassHash[themeName] = themeClass;
16335}
16336exports.defineThemeSystem = defineThemeSystem;
16337function getThemeSystemClass(themeSetting) {
16338    if (!themeSetting) {
16339        return StandardTheme_1.default;
16340    }
16341    else if (themeSetting === true) {
16342        return JqueryUiTheme_1.default;
16343    }
16344    else {
16345        return themeClassHash[themeSetting];
16346    }
16347}
16348exports.getThemeSystemClass = getThemeSystemClass;
16349
16350
16351/***/ }),
16352/* 58 */
16353/***/ (function(module, exports, __webpack_require__) {
16354
16355Object.defineProperty(exports, "__esModule", { value: true });
16356var $ = __webpack_require__(3);
16357var util_1 = __webpack_require__(4);
16358/*
16359A cache for the left/right/top/bottom/width/height values for one or more elements.
16360Works with both offset (from topleft document) and position (from offsetParent).
16361
16362options:
16363- els
16364- isHorizontal
16365- isVertical
16366*/
16367var CoordCache = /** @class */ (function () {
16368    function CoordCache(options) {
16369        this.isHorizontal = false; // whether to query for left/right/width
16370        this.isVertical = false; // whether to query for top/bottom/height
16371        this.els = $(options.els);
16372        this.isHorizontal = options.isHorizontal;
16373        this.isVertical = options.isVertical;
16374        this.forcedOffsetParentEl = options.offsetParent ? $(options.offsetParent) : null;
16375    }
16376    // Queries the els for coordinates and stores them.
16377    // Call this method before using and of the get* methods below.
16378    CoordCache.prototype.build = function () {
16379        var offsetParentEl = this.forcedOffsetParentEl;
16380        if (!offsetParentEl && this.els.length > 0) {
16381            offsetParentEl = this.els.eq(0).offsetParent();
16382        }
16383        this.origin = offsetParentEl ?
16384            offsetParentEl.offset() :
16385            null;
16386        this.boundingRect = this.queryBoundingRect();
16387        if (this.isHorizontal) {
16388            this.buildElHorizontals();
16389        }
16390        if (this.isVertical) {
16391            this.buildElVerticals();
16392        }
16393    };
16394    // Destroys all internal data about coordinates, freeing memory
16395    CoordCache.prototype.clear = function () {
16396        this.origin = null;
16397        this.boundingRect = null;
16398        this.lefts = null;
16399        this.rights = null;
16400        this.tops = null;
16401        this.bottoms = null;
16402    };
16403    // When called, if coord caches aren't built, builds them
16404    CoordCache.prototype.ensureBuilt = function () {
16405        if (!this.origin) {
16406            this.build();
16407        }
16408    };
16409    // Populates the left/right internal coordinate arrays
16410    CoordCache.prototype.buildElHorizontals = function () {
16411        var lefts = [];
16412        var rights = [];
16413        this.els.each(function (i, node) {
16414            var el = $(node);
16415            var left = el.offset().left;
16416            var width = el.outerWidth();
16417            lefts.push(left);
16418            rights.push(left + width);
16419        });
16420        this.lefts = lefts;
16421        this.rights = rights;
16422    };
16423    // Populates the top/bottom internal coordinate arrays
16424    CoordCache.prototype.buildElVerticals = function () {
16425        var tops = [];
16426        var bottoms = [];
16427        this.els.each(function (i, node) {
16428            var el = $(node);
16429            var top = el.offset().top;
16430            var height = el.outerHeight();
16431            tops.push(top);
16432            bottoms.push(top + height);
16433        });
16434        this.tops = tops;
16435        this.bottoms = bottoms;
16436    };
16437    // Given a left offset (from document left), returns the index of the el that it horizontally intersects.
16438    // If no intersection is made, returns undefined.
16439    CoordCache.prototype.getHorizontalIndex = function (leftOffset) {
16440        this.ensureBuilt();
16441        var lefts = this.lefts;
16442        var rights = this.rights;
16443        var len = lefts.length;
16444        var i;
16445        for (i = 0; i < len; i++) {
16446            if (leftOffset >= lefts[i] && leftOffset < rights[i]) {
16447                return i;
16448            }
16449        }
16450    };
16451    // Given a top offset (from document top), returns the index of the el that it vertically intersects.
16452    // If no intersection is made, returns undefined.
16453    CoordCache.prototype.getVerticalIndex = function (topOffset) {
16454        this.ensureBuilt();
16455        var tops = this.tops;
16456        var bottoms = this.bottoms;
16457        var len = tops.length;
16458        var i;
16459        for (i = 0; i < len; i++) {
16460            if (topOffset >= tops[i] && topOffset < bottoms[i]) {
16461                return i;
16462            }
16463        }
16464    };
16465    // Gets the left offset (from document left) of the element at the given index
16466    CoordCache.prototype.getLeftOffset = function (leftIndex) {
16467        this.ensureBuilt();
16468        return this.lefts[leftIndex];
16469    };
16470    // Gets the left position (from offsetParent left) of the element at the given index
16471    CoordCache.prototype.getLeftPosition = function (leftIndex) {
16472        this.ensureBuilt();
16473        return this.lefts[leftIndex] - this.origin.left;
16474    };
16475    // Gets the right offset (from document left) of the element at the given index.
16476    // This value is NOT relative to the document's right edge, like the CSS concept of "right" would be.
16477    CoordCache.prototype.getRightOffset = function (leftIndex) {
16478        this.ensureBuilt();
16479        return this.rights[leftIndex];
16480    };
16481    // Gets the right position (from offsetParent left) of the element at the given index.
16482    // This value is NOT relative to the offsetParent's right edge, like the CSS concept of "right" would be.
16483    CoordCache.prototype.getRightPosition = function (leftIndex) {
16484        this.ensureBuilt();
16485        return this.rights[leftIndex] - this.origin.left;
16486    };
16487    // Gets the width of the element at the given index
16488    CoordCache.prototype.getWidth = function (leftIndex) {
16489        this.ensureBuilt();
16490        return this.rights[leftIndex] - this.lefts[leftIndex];
16491    };
16492    // Gets the top offset (from document top) of the element at the given index
16493    CoordCache.prototype.getTopOffset = function (topIndex) {
16494        this.ensureBuilt();
16495        return this.tops[topIndex];
16496    };
16497    // Gets the top position (from offsetParent top) of the element at the given position
16498    CoordCache.prototype.getTopPosition = function (topIndex) {
16499        this.ensureBuilt();
16500        return this.tops[topIndex] - this.origin.top;
16501    };
16502    // Gets the bottom offset (from the document top) of the element at the given index.
16503    // This value is NOT relative to the offsetParent's bottom edge, like the CSS concept of "bottom" would be.
16504    CoordCache.prototype.getBottomOffset = function (topIndex) {
16505        this.ensureBuilt();
16506        return this.bottoms[topIndex];
16507    };
16508    // Gets the bottom position (from the offsetParent top) of the element at the given index.
16509    // This value is NOT relative to the offsetParent's bottom edge, like the CSS concept of "bottom" would be.
16510    CoordCache.prototype.getBottomPosition = function (topIndex) {
16511        this.ensureBuilt();
16512        return this.bottoms[topIndex] - this.origin.top;
16513    };
16514    // Gets the height of the element at the given index
16515    CoordCache.prototype.getHeight = function (topIndex) {
16516        this.ensureBuilt();
16517        return this.bottoms[topIndex] - this.tops[topIndex];
16518    };
16519    // Bounding Rect
16520    // TODO: decouple this from CoordCache
16521    // Compute and return what the elements' bounding rectangle is, from the user's perspective.
16522    // Right now, only returns a rectangle if constrained by an overflow:scroll element.
16523    // Returns null if there are no elements
16524    CoordCache.prototype.queryBoundingRect = function () {
16525        var scrollParentEl;
16526        if (this.els.length > 0) {
16527            scrollParentEl = util_1.getScrollParent(this.els.eq(0));
16528            if (!scrollParentEl.is(document) &&
16529                !scrollParentEl.is('html,body') // don't consider these bounding rects. solves issue 3615
16530            ) {
16531                return util_1.getClientRect(scrollParentEl);
16532            }
16533        }
16534        return null;
16535    };
16536    CoordCache.prototype.isPointInBounds = function (leftOffset, topOffset) {
16537        return this.isLeftInBounds(leftOffset) && this.isTopInBounds(topOffset);
16538    };
16539    CoordCache.prototype.isLeftInBounds = function (leftOffset) {
16540        return !this.boundingRect || (leftOffset >= this.boundingRect.left && leftOffset < this.boundingRect.right);
16541    };
16542    CoordCache.prototype.isTopInBounds = function (topOffset) {
16543        return !this.boundingRect || (topOffset >= this.boundingRect.top && topOffset < this.boundingRect.bottom);
16544    };
16545    return CoordCache;
16546}());
16547exports.default = CoordCache;
16548
16549
16550/***/ }),
16551/* 59 */
16552/***/ (function(module, exports, __webpack_require__) {
16553
16554Object.defineProperty(exports, "__esModule", { value: true });
16555var $ = __webpack_require__(3);
16556var util_1 = __webpack_require__(4);
16557var ListenerMixin_1 = __webpack_require__(7);
16558var GlobalEmitter_1 = __webpack_require__(23);
16559/* Tracks a drag's mouse movement, firing various handlers
16560----------------------------------------------------------------------------------------------------------------------*/
16561// TODO: use Emitter
16562var DragListener = /** @class */ (function () {
16563    function DragListener(options) {
16564        this.isInteracting = false;
16565        this.isDistanceSurpassed = false;
16566        this.isDelayEnded = false;
16567        this.isDragging = false;
16568        this.isTouch = false;
16569        this.isGeneric = false; // initiated by 'dragstart' (jqui)
16570        this.shouldCancelTouchScroll = true;
16571        this.scrollAlwaysKills = false;
16572        this.isAutoScroll = false;
16573        // defaults
16574        this.scrollSensitivity = 30; // pixels from edge for scrolling to start
16575        this.scrollSpeed = 200; // pixels per second, at maximum speed
16576        this.scrollIntervalMs = 50; // millisecond wait between scroll increment
16577        this.options = options || {};
16578    }
16579    // Interaction (high-level)
16580    // -----------------------------------------------------------------------------------------------------------------
16581    DragListener.prototype.startInteraction = function (ev, extraOptions) {
16582        if (extraOptions === void 0) { extraOptions = {}; }
16583        if (ev.type === 'mousedown') {
16584            if (GlobalEmitter_1.default.get().shouldIgnoreMouse()) {
16585                return;
16586            }
16587            else if (!util_1.isPrimaryMouseButton(ev)) {
16588                return;
16589            }
16590            else {
16591                ev.preventDefault(); // prevents native selection in most browsers
16592            }
16593        }
16594        if (!this.isInteracting) {
16595            // process options
16596            this.delay = util_1.firstDefined(extraOptions.delay, this.options.delay, 0);
16597            this.minDistance = util_1.firstDefined(extraOptions.distance, this.options.distance, 0);
16598            this.subjectEl = this.options.subjectEl;
16599            util_1.preventSelection($('body'));
16600            this.isInteracting = true;
16601            this.isTouch = util_1.getEvIsTouch(ev);
16602            this.isGeneric = ev.type === 'dragstart';
16603            this.isDelayEnded = false;
16604            this.isDistanceSurpassed = false;
16605            this.originX = util_1.getEvX(ev);
16606            this.originY = util_1.getEvY(ev);
16607            this.scrollEl = util_1.getScrollParent($(ev.target));
16608            this.bindHandlers();
16609            this.initAutoScroll();
16610            this.handleInteractionStart(ev);
16611            this.startDelay(ev);
16612            if (!this.minDistance) {
16613                this.handleDistanceSurpassed(ev);
16614            }
16615        }
16616    };
16617    DragListener.prototype.handleInteractionStart = function (ev) {
16618        this.trigger('interactionStart', ev);
16619    };
16620    DragListener.prototype.endInteraction = function (ev, isCancelled) {
16621        if (this.isInteracting) {
16622            this.endDrag(ev);
16623            if (this.delayTimeoutId) {
16624                clearTimeout(this.delayTimeoutId);
16625                this.delayTimeoutId = null;
16626            }
16627            this.destroyAutoScroll();
16628            this.unbindHandlers();
16629            this.isInteracting = false;
16630            this.handleInteractionEnd(ev, isCancelled);
16631            util_1.allowSelection($('body'));
16632        }
16633    };
16634    DragListener.prototype.handleInteractionEnd = function (ev, isCancelled) {
16635        this.trigger('interactionEnd', ev, isCancelled || false);
16636    };
16637    // Binding To DOM
16638    // -----------------------------------------------------------------------------------------------------------------
16639    DragListener.prototype.bindHandlers = function () {
16640        // some browsers (Safari in iOS 10) don't allow preventDefault on touch events that are bound after touchstart,
16641        // so listen to the GlobalEmitter singleton, which is always bound, instead of the document directly.
16642        var globalEmitter = GlobalEmitter_1.default.get();
16643        if (this.isGeneric) {
16644            this.listenTo($(document), {
16645                drag: this.handleMove,
16646                dragstop: this.endInteraction
16647            });
16648        }
16649        else if (this.isTouch) {
16650            this.listenTo(globalEmitter, {
16651                touchmove: this.handleTouchMove,
16652                touchend: this.endInteraction,
16653                scroll: this.handleTouchScroll
16654            });
16655        }
16656        else {
16657            this.listenTo(globalEmitter, {
16658                mousemove: this.handleMouseMove,
16659                mouseup: this.endInteraction
16660            });
16661        }
16662        this.listenTo(globalEmitter, {
16663            selectstart: util_1.preventDefault,
16664            contextmenu: util_1.preventDefault // long taps would open menu on Chrome dev tools
16665        });
16666    };
16667    DragListener.prototype.unbindHandlers = function () {
16668        this.stopListeningTo(GlobalEmitter_1.default.get());
16669        this.stopListeningTo($(document)); // for isGeneric
16670    };
16671    // Drag (high-level)
16672    // -----------------------------------------------------------------------------------------------------------------
16673    // extraOptions ignored if drag already started
16674    DragListener.prototype.startDrag = function (ev, extraOptions) {
16675        this.startInteraction(ev, extraOptions); // ensure interaction began
16676        if (!this.isDragging) {
16677            this.isDragging = true;
16678            this.handleDragStart(ev);
16679        }
16680    };
16681    DragListener.prototype.handleDragStart = function (ev) {
16682        this.trigger('dragStart', ev);
16683    };
16684    DragListener.prototype.handleMove = function (ev) {
16685        var dx = util_1.getEvX(ev) - this.originX;
16686        var dy = util_1.getEvY(ev) - this.originY;
16687        var minDistance = this.minDistance;
16688        var distanceSq; // current distance from the origin, squared
16689        if (!this.isDistanceSurpassed) {
16690            distanceSq = dx * dx + dy * dy;
16691            if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem
16692                this.handleDistanceSurpassed(ev);
16693            }
16694        }
16695        if (this.isDragging) {
16696            this.handleDrag(dx, dy, ev);
16697        }
16698    };
16699    // Called while the mouse is being moved and when we know a legitimate drag is taking place
16700    DragListener.prototype.handleDrag = function (dx, dy, ev) {
16701        this.trigger('drag', dx, dy, ev);
16702        this.updateAutoScroll(ev); // will possibly cause scrolling
16703    };
16704    DragListener.prototype.endDrag = function (ev) {
16705        if (this.isDragging) {
16706            this.isDragging = false;
16707            this.handleDragEnd(ev);
16708        }
16709    };
16710    DragListener.prototype.handleDragEnd = function (ev) {
16711        this.trigger('dragEnd', ev);
16712    };
16713    // Delay
16714    // -----------------------------------------------------------------------------------------------------------------
16715    DragListener.prototype.startDelay = function (initialEv) {
16716        var _this = this;
16717        if (this.delay) {
16718            this.delayTimeoutId = setTimeout(function () {
16719                _this.handleDelayEnd(initialEv);
16720            }, this.delay);
16721        }
16722        else {
16723            this.handleDelayEnd(initialEv);
16724        }
16725    };
16726    DragListener.prototype.handleDelayEnd = function (initialEv) {
16727        this.isDelayEnded = true;
16728        if (this.isDistanceSurpassed) {
16729            this.startDrag(initialEv);
16730        }
16731    };
16732    // Distance
16733    // -----------------------------------------------------------------------------------------------------------------
16734    DragListener.prototype.handleDistanceSurpassed = function (ev) {
16735        this.isDistanceSurpassed = true;
16736        if (this.isDelayEnded) {
16737            this.startDrag(ev);
16738        }
16739    };
16740    // Mouse / Touch
16741    // -----------------------------------------------------------------------------------------------------------------
16742    DragListener.prototype.handleTouchMove = function (ev) {
16743        // prevent inertia and touchmove-scrolling while dragging
16744        if (this.isDragging && this.shouldCancelTouchScroll) {
16745            ev.preventDefault();
16746        }
16747        this.handleMove(ev);
16748    };
16749    DragListener.prototype.handleMouseMove = function (ev) {
16750        this.handleMove(ev);
16751    };
16752    // Scrolling (unrelated to auto-scroll)
16753    // -----------------------------------------------------------------------------------------------------------------
16754    DragListener.prototype.handleTouchScroll = function (ev) {
16755        // if the drag is being initiated by touch, but a scroll happens before
16756        // the drag-initiating delay is over, cancel the drag
16757        if (!this.isDragging || this.scrollAlwaysKills) {
16758            this.endInteraction(ev, true); // isCancelled=true
16759        }
16760    };
16761    // Utils
16762    // -----------------------------------------------------------------------------------------------------------------
16763    // Triggers a callback. Calls a function in the option hash of the same name.
16764    // Arguments beyond the first `name` are forwarded on.
16765    DragListener.prototype.trigger = function (name) {
16766        var args = [];
16767        for (var _i = 1; _i < arguments.length; _i++) {
16768            args[_i - 1] = arguments[_i];
16769        }
16770        if (this.options[name]) {
16771            this.options[name].apply(this, args);
16772        }
16773        // makes _methods callable by event name. TODO: kill this
16774        if (this['_' + name]) {
16775            this['_' + name].apply(this, args);
16776        }
16777    };
16778    // Auto-scroll
16779    // -----------------------------------------------------------------------------------------------------------------
16780    DragListener.prototype.initAutoScroll = function () {
16781        var scrollEl = this.scrollEl;
16782        this.isAutoScroll =
16783            this.options.scroll &&
16784                scrollEl &&
16785                !scrollEl.is(window) &&
16786                !scrollEl.is(document);
16787        if (this.isAutoScroll) {
16788            // debounce makes sure rapid calls don't happen
16789            this.listenTo(scrollEl, 'scroll', util_1.debounce(this.handleDebouncedScroll, 100));
16790        }
16791    };
16792    DragListener.prototype.destroyAutoScroll = function () {
16793        this.endAutoScroll(); // kill any animation loop
16794        // remove the scroll handler if there is a scrollEl
16795        if (this.isAutoScroll) {
16796            this.stopListeningTo(this.scrollEl, 'scroll'); // will probably get removed by unbindHandlers too :(
16797        }
16798    };
16799    // Computes and stores the bounding rectangle of scrollEl
16800    DragListener.prototype.computeScrollBounds = function () {
16801        if (this.isAutoScroll) {
16802            this.scrollBounds = util_1.getOuterRect(this.scrollEl);
16803            // TODO: use getClientRect in future. but prevents auto scrolling when on top of scrollbars
16804        }
16805    };
16806    // Called when the dragging is in progress and scrolling should be updated
16807    DragListener.prototype.updateAutoScroll = function (ev) {
16808        var sensitivity = this.scrollSensitivity;
16809        var bounds = this.scrollBounds;
16810        var topCloseness;
16811        var bottomCloseness;
16812        var leftCloseness;
16813        var rightCloseness;
16814        var topVel = 0;
16815        var leftVel = 0;
16816        if (bounds) { // only scroll if scrollEl exists
16817            // compute closeness to edges. valid range is from 0.0 - 1.0
16818            topCloseness = (sensitivity - (util_1.getEvY(ev) - bounds.top)) / sensitivity;
16819            bottomCloseness = (sensitivity - (bounds.bottom - util_1.getEvY(ev))) / sensitivity;
16820            leftCloseness = (sensitivity - (util_1.getEvX(ev) - bounds.left)) / sensitivity;
16821            rightCloseness = (sensitivity - (bounds.right - util_1.getEvX(ev))) / sensitivity;
16822            // translate vertical closeness into velocity.
16823            // mouse must be completely in bounds for velocity to happen.
16824            if (topCloseness >= 0 && topCloseness <= 1) {
16825                topVel = topCloseness * this.scrollSpeed * -1; // negative. for scrolling up
16826            }
16827            else if (bottomCloseness >= 0 && bottomCloseness <= 1) {
16828                topVel = bottomCloseness * this.scrollSpeed;
16829            }
16830            // translate horizontal closeness into velocity
16831            if (leftCloseness >= 0 && leftCloseness <= 1) {
16832                leftVel = leftCloseness * this.scrollSpeed * -1; // negative. for scrolling left
16833            }
16834            else if (rightCloseness >= 0 && rightCloseness <= 1) {
16835                leftVel = rightCloseness * this.scrollSpeed;
16836            }
16837        }
16838        this.setScrollVel(topVel, leftVel);
16839    };
16840    // Sets the speed-of-scrolling for the scrollEl
16841    DragListener.prototype.setScrollVel = function (topVel, leftVel) {
16842        this.scrollTopVel = topVel;
16843        this.scrollLeftVel = leftVel;
16844        this.constrainScrollVel(); // massages into realistic values
16845        // if there is non-zero velocity, and an animation loop hasn't already started, then START
16846        if ((this.scrollTopVel || this.scrollLeftVel) && !this.scrollIntervalId) {
16847            this.scrollIntervalId = setInterval(util_1.proxy(this, 'scrollIntervalFunc'), // scope to `this`
16848            this.scrollIntervalMs);
16849        }
16850    };
16851    // Forces scrollTopVel and scrollLeftVel to be zero if scrolling has already gone all the way
16852    DragListener.prototype.constrainScrollVel = function () {
16853        var el = this.scrollEl;
16854        if (this.scrollTopVel < 0) { // scrolling up?
16855            if (el.scrollTop() <= 0) { // already scrolled all the way up?
16856                this.scrollTopVel = 0;
16857            }
16858        }
16859        else if (this.scrollTopVel > 0) { // scrolling down?
16860            if (el.scrollTop() + el[0].clientHeight >= el[0].scrollHeight) { // already scrolled all the way down?
16861                this.scrollTopVel = 0;
16862            }
16863        }
16864        if (this.scrollLeftVel < 0) { // scrolling left?
16865            if (el.scrollLeft() <= 0) { // already scrolled all the left?
16866                this.scrollLeftVel = 0;
16867            }
16868        }
16869        else if (this.scrollLeftVel > 0) { // scrolling right?
16870            if (el.scrollLeft() + el[0].clientWidth >= el[0].scrollWidth) { // already scrolled all the way right?
16871                this.scrollLeftVel = 0;
16872            }
16873        }
16874    };
16875    // This function gets called during every iteration of the scrolling animation loop
16876    DragListener.prototype.scrollIntervalFunc = function () {
16877        var el = this.scrollEl;
16878        var frac = this.scrollIntervalMs / 1000; // considering animation frequency, what the vel should be mult'd by
16879        // change the value of scrollEl's scroll
16880        if (this.scrollTopVel) {
16881            el.scrollTop(el.scrollTop() + this.scrollTopVel * frac);
16882        }
16883        if (this.scrollLeftVel) {
16884            el.scrollLeft(el.scrollLeft() + this.scrollLeftVel * frac);
16885        }
16886        this.constrainScrollVel(); // since the scroll values changed, recompute the velocities
16887        // if scrolled all the way, which causes the vels to be zero, stop the animation loop
16888        if (!this.scrollTopVel && !this.scrollLeftVel) {
16889            this.endAutoScroll();
16890        }
16891    };
16892    // Kills any existing scrolling animation loop
16893    DragListener.prototype.endAutoScroll = function () {
16894        if (this.scrollIntervalId) {
16895            clearInterval(this.scrollIntervalId);
16896            this.scrollIntervalId = null;
16897            this.handleScrollEnd();
16898        }
16899    };
16900    // Get called when the scrollEl is scrolled (NOTE: this is delayed via debounce)
16901    DragListener.prototype.handleDebouncedScroll = function () {
16902        // recompute all coordinates, but *only* if this is *not* part of our scrolling animation
16903        if (!this.scrollIntervalId) {
16904            this.handleScrollEnd();
16905        }
16906    };
16907    DragListener.prototype.handleScrollEnd = function () {
16908        // Called when scrolling has stopped, whether through auto scroll, or the user scrolling
16909    };
16910    return DragListener;
16911}());
16912exports.default = DragListener;
16913ListenerMixin_1.default.mixInto(DragListener);
16914
16915
16916/***/ }),
16917/* 60 */
16918/***/ (function(module, exports, __webpack_require__) {
16919
16920Object.defineProperty(exports, "__esModule", { value: true });
16921var tslib_1 = __webpack_require__(2);
16922var util_1 = __webpack_require__(4);
16923var Mixin_1 = __webpack_require__(15);
16924/*
16925A set of rendering and date-related methods for a visual component comprised of one or more rows of day columns.
16926Prerequisite: the object being mixed into needs to be a *Grid*
16927*/
16928var DayTableMixin = /** @class */ (function (_super) {
16929    tslib_1.__extends(DayTableMixin, _super);
16930    function DayTableMixin() {
16931        return _super !== null && _super.apply(this, arguments) || this;
16932    }
16933    // Populates internal variables used for date calculation and rendering
16934    DayTableMixin.prototype.updateDayTable = function () {
16935        var t = this;
16936        var view = t.view;
16937        var calendar = view.calendar;
16938        var date = calendar.msToUtcMoment(t.dateProfile.renderUnzonedRange.startMs, true);
16939        var end = calendar.msToUtcMoment(t.dateProfile.renderUnzonedRange.endMs, true);
16940        var dayIndex = -1;
16941        var dayIndices = [];
16942        var dayDates = [];
16943        var daysPerRow;
16944        var firstDay;
16945        var rowCnt;
16946        while (date.isBefore(end)) { // loop each day from start to end
16947            if (view.isHiddenDay(date)) {
16948                dayIndices.push(dayIndex + 0.5); // mark that it's between indices
16949            }
16950            else {
16951                dayIndex++;
16952                dayIndices.push(dayIndex);
16953                dayDates.push(date.clone());
16954            }
16955            date.add(1, 'days');
16956        }
16957        if (this.breakOnWeeks) {
16958            // count columns until the day-of-week repeats
16959            firstDay = dayDates[0].day();
16960            for (daysPerRow = 1; daysPerRow < dayDates.length; daysPerRow++) {
16961                if (dayDates[daysPerRow].day() === firstDay) {
16962                    break;
16963                }
16964            }
16965            rowCnt = Math.ceil(dayDates.length / daysPerRow);
16966        }
16967        else {
16968            rowCnt = 1;
16969            daysPerRow = dayDates.length;
16970        }
16971        this.dayDates = dayDates;
16972        this.dayIndices = dayIndices;
16973        this.daysPerRow = daysPerRow;
16974        this.rowCnt = rowCnt;
16975        this.updateDayTableCols();
16976    };
16977    // Computes and assigned the colCnt property and updates any options that may be computed from it
16978    DayTableMixin.prototype.updateDayTableCols = function () {
16979        this.colCnt = this.computeColCnt();
16980        this.colHeadFormat =
16981            this.opt('columnHeaderFormat') ||
16982                this.opt('columnFormat') || // deprecated
16983                this.computeColHeadFormat();
16984    };
16985    // Determines how many columns there should be in the table
16986    DayTableMixin.prototype.computeColCnt = function () {
16987        return this.daysPerRow;
16988    };
16989    // Computes the ambiguously-timed moment for the given cell
16990    DayTableMixin.prototype.getCellDate = function (row, col) {
16991        return this.dayDates[this.getCellDayIndex(row, col)].clone();
16992    };
16993    // Computes the ambiguously-timed date range for the given cell
16994    DayTableMixin.prototype.getCellRange = function (row, col) {
16995        var start = this.getCellDate(row, col);
16996        var end = start.clone().add(1, 'days');
16997        return { start: start, end: end };
16998    };
16999    // Returns the number of day cells, chronologically, from the first of the grid (0-based)
17000    DayTableMixin.prototype.getCellDayIndex = function (row, col) {
17001        return row * this.daysPerRow + this.getColDayIndex(col);
17002    };
17003    // Returns the numner of day cells, chronologically, from the first cell in *any given row*
17004    DayTableMixin.prototype.getColDayIndex = function (col) {
17005        if (this.isRTL) {
17006            return this.colCnt - 1 - col;
17007        }
17008        else {
17009            return col;
17010        }
17011    };
17012    // Given a date, returns its chronolocial cell-index from the first cell of the grid.
17013    // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets.
17014    // If before the first offset, returns a negative number.
17015    // If after the last offset, returns an offset past the last cell offset.
17016    // Only works for *start* dates of cells. Will not work for exclusive end dates for cells.
17017    DayTableMixin.prototype.getDateDayIndex = function (date) {
17018        var dayIndices = this.dayIndices;
17019        var dayOffset = date.diff(this.dayDates[0], 'days');
17020        if (dayOffset < 0) {
17021            return dayIndices[0] - 1;
17022        }
17023        else if (dayOffset >= dayIndices.length) {
17024            return dayIndices[dayIndices.length - 1] + 1;
17025        }
17026        else {
17027            return dayIndices[dayOffset];
17028        }
17029    };
17030    /* Options
17031    ------------------------------------------------------------------------------------------------------------------*/
17032    // Computes a default column header formatting string if `colFormat` is not explicitly defined
17033    DayTableMixin.prototype.computeColHeadFormat = function () {
17034        // if more than one week row, or if there are a lot of columns with not much space,
17035        // put just the day numbers will be in each cell
17036        if (this.rowCnt > 1 || this.colCnt > 10) {
17037            return 'ddd'; // "Sat"
17038        }
17039        else if (this.colCnt > 1) {
17040            return this.opt('dayOfMonthFormat'); // "Sat 12/10"
17041        }
17042        else {
17043            return 'dddd'; // "Saturday"
17044        }
17045    };
17046    /* Slicing
17047    ------------------------------------------------------------------------------------------------------------------*/
17048    // Slices up a date range into a segment for every week-row it intersects with
17049    DayTableMixin.prototype.sliceRangeByRow = function (unzonedRange) {
17050        var daysPerRow = this.daysPerRow;
17051        var normalRange = this.view.computeDayRange(unzonedRange); // make whole-day range, considering nextDayThreshold
17052        var rangeFirst = this.getDateDayIndex(normalRange.start); // inclusive first index
17053        var rangeLast = this.getDateDayIndex(normalRange.end.clone().subtract(1, 'days')); // inclusive last index
17054        var segs = [];
17055        var row;
17056        var rowFirst;
17057        var rowLast; // inclusive day-index range for current row
17058        var segFirst;
17059        var segLast; // inclusive day-index range for segment
17060        for (row = 0; row < this.rowCnt; row++) {
17061            rowFirst = row * daysPerRow;
17062            rowLast = rowFirst + daysPerRow - 1;
17063            // intersect segment's offset range with the row's
17064            segFirst = Math.max(rangeFirst, rowFirst);
17065            segLast = Math.min(rangeLast, rowLast);
17066            // deal with in-between indices
17067            segFirst = Math.ceil(segFirst); // in-between starts round to next cell
17068            segLast = Math.floor(segLast); // in-between ends round to prev cell
17069            if (segFirst <= segLast) { // was there any intersection with the current row?
17070                segs.push({
17071                    row: row,
17072                    // normalize to start of row
17073                    firstRowDayIndex: segFirst - rowFirst,
17074                    lastRowDayIndex: segLast - rowFirst,
17075                    // must be matching integers to be the segment's start/end
17076                    isStart: segFirst === rangeFirst,
17077                    isEnd: segLast === rangeLast
17078                });
17079            }
17080        }
17081        return segs;
17082    };
17083    // Slices up a date range into a segment for every day-cell it intersects with.
17084    // TODO: make more DRY with sliceRangeByRow somehow.
17085    DayTableMixin.prototype.sliceRangeByDay = function (unzonedRange) {
17086        var daysPerRow = this.daysPerRow;
17087        var normalRange = this.view.computeDayRange(unzonedRange); // make whole-day range, considering nextDayThreshold
17088        var rangeFirst = this.getDateDayIndex(normalRange.start); // inclusive first index
17089        var rangeLast = this.getDateDayIndex(normalRange.end.clone().subtract(1, 'days')); // inclusive last index
17090        var segs = [];
17091        var row;
17092        var rowFirst;
17093        var rowLast; // inclusive day-index range for current row
17094        var i;
17095        var segFirst;
17096        var segLast; // inclusive day-index range for segment
17097        for (row = 0; row < this.rowCnt; row++) {
17098            rowFirst = row * daysPerRow;
17099            rowLast = rowFirst + daysPerRow - 1;
17100            for (i = rowFirst; i <= rowLast; i++) {
17101                // intersect segment's offset range with the row's
17102                segFirst = Math.max(rangeFirst, i);
17103                segLast = Math.min(rangeLast, i);
17104                // deal with in-between indices
17105                segFirst = Math.ceil(segFirst); // in-between starts round to next cell
17106                segLast = Math.floor(segLast); // in-between ends round to prev cell
17107                if (segFirst <= segLast) { // was there any intersection with the current row?
17108                    segs.push({
17109                        row: row,
17110                        // normalize to start of row
17111                        firstRowDayIndex: segFirst - rowFirst,
17112                        lastRowDayIndex: segLast - rowFirst,
17113                        // must be matching integers to be the segment's start/end
17114                        isStart: segFirst === rangeFirst,
17115                        isEnd: segLast === rangeLast
17116                    });
17117                }
17118            }
17119        }
17120        return segs;
17121    };
17122    /* Header Rendering
17123    ------------------------------------------------------------------------------------------------------------------*/
17124    DayTableMixin.prototype.renderHeadHtml = function () {
17125        var theme = this.view.calendar.theme;
17126        return '' +
17127            '<div class="fc-row ' + theme.getClass('headerRow') + '">' +
17128            '<table class="' + theme.getClass('tableGrid') + '">' +
17129            '<thead>' +
17130            this.renderHeadTrHtml() +
17131            '</thead>' +
17132            '</table>' +
17133            '</div>';
17134    };
17135    DayTableMixin.prototype.renderHeadIntroHtml = function () {
17136        return this.renderIntroHtml(); // fall back to generic
17137    };
17138    DayTableMixin.prototype.renderHeadTrHtml = function () {
17139        return '' +
17140            '<tr>' +
17141            (this.isRTL ? '' : this.renderHeadIntroHtml()) +
17142            this.renderHeadDateCellsHtml() +
17143            (this.isRTL ? this.renderHeadIntroHtml() : '') +
17144            '</tr>';
17145    };
17146    DayTableMixin.prototype.renderHeadDateCellsHtml = function () {
17147        var htmls = [];
17148        var col;
17149        var date;
17150        for (col = 0; col < this.colCnt; col++) {
17151            date = this.getCellDate(0, col);
17152            htmls.push(this.renderHeadDateCellHtml(date));
17153        }
17154        return htmls.join('');
17155    };
17156    // TODO: when internalApiVersion, accept an object for HTML attributes
17157    // (colspan should be no different)
17158    DayTableMixin.prototype.renderHeadDateCellHtml = function (date, colspan, otherAttrs) {
17159        var t = this;
17160        var view = t.view;
17161        var isDateValid = t.dateProfile.activeUnzonedRange.containsDate(date); // TODO: called too frequently. cache somehow.
17162        var classNames = [
17163            'fc-day-header',
17164            view.calendar.theme.getClass('widgetHeader')
17165        ];
17166        var innerHtml;
17167        if (typeof t.opt('columnHeaderHtml') === 'function') {
17168            innerHtml = t.opt('columnHeaderHtml')(date);
17169        }
17170        else if (typeof t.opt('columnHeaderText') === 'function') {
17171            innerHtml = util_1.htmlEscape(t.opt('columnHeaderText')(date));
17172        }
17173        else {
17174            innerHtml = util_1.htmlEscape(date.format(t.colHeadFormat));
17175        }
17176        // if only one row of days, the classNames on the header can represent the specific days beneath
17177        if (t.rowCnt === 1) {
17178            classNames = classNames.concat(
17179            // includes the day-of-week class
17180            // noThemeHighlight=true (don't highlight the header)
17181            t.getDayClasses(date, true));
17182        }
17183        else {
17184            classNames.push('fc-' + util_1.dayIDs[date.day()]); // only add the day-of-week class
17185        }
17186        return '' +
17187            '<th class="' + classNames.join(' ') + '"' +
17188            ((isDateValid && t.rowCnt) === 1 ?
17189                ' data-date="' + date.format('YYYY-MM-DD') + '"' :
17190                '') +
17191            (colspan > 1 ?
17192                ' colspan="' + colspan + '"' :
17193                '') +
17194            (otherAttrs ?
17195                ' ' + otherAttrs :
17196                '') +
17197            '>' +
17198            (isDateValid ?
17199                // don't make a link if the heading could represent multiple days, or if there's only one day (forceOff)
17200                view.buildGotoAnchorHtml({ date: date, forceOff: t.rowCnt > 1 || t.colCnt === 1 }, innerHtml) :
17201                // if not valid, display text, but no link
17202                innerHtml) +
17203            '</th>';
17204    };
17205    /* Background Rendering
17206    ------------------------------------------------------------------------------------------------------------------*/
17207    DayTableMixin.prototype.renderBgTrHtml = function (row) {
17208        return '' +
17209            '<tr>' +
17210            (this.isRTL ? '' : this.renderBgIntroHtml(row)) +
17211            this.renderBgCellsHtml(row) +
17212            (this.isRTL ? this.renderBgIntroHtml(row) : '') +
17213            '</tr>';
17214    };
17215    DayTableMixin.prototype.renderBgIntroHtml = function (row) {
17216        return this.renderIntroHtml(); // fall back to generic
17217    };
17218    DayTableMixin.prototype.renderBgCellsHtml = function (row) {
17219        var htmls = [];
17220        var col;
17221        var date;
17222        for (col = 0; col < this.colCnt; col++) {
17223            date = this.getCellDate(row, col);
17224            htmls.push(this.renderBgCellHtml(date));
17225        }
17226        return htmls.join('');
17227    };
17228    DayTableMixin.prototype.renderBgCellHtml = function (date, otherAttrs) {
17229        var t = this;
17230        var view = t.view;
17231        var isDateValid = t.dateProfile.activeUnzonedRange.containsDate(date); // TODO: called too frequently. cache somehow.
17232        var classes = t.getDayClasses(date);
17233        classes.unshift('fc-day', view.calendar.theme.getClass('widgetContent'));
17234        return '<td class="' + classes.join(' ') + '"' +
17235            (isDateValid ?
17236                ' data-date="' + date.format('YYYY-MM-DD') + '"' : // if date has a time, won't format it
17237                '') +
17238            (otherAttrs ?
17239                ' ' + otherAttrs :
17240                '') +
17241            '></td>';
17242    };
17243    /* Generic
17244    ------------------------------------------------------------------------------------------------------------------*/
17245    DayTableMixin.prototype.renderIntroHtml = function () {
17246        // Generates the default HTML intro for any row. User classes should override
17247    };
17248    // TODO: a generic method for dealing with <tr>, RTL, intro
17249    // when increment internalApiVersion
17250    // wrapTr (scheduler)
17251    /* Utils
17252    ------------------------------------------------------------------------------------------------------------------*/
17253    // Applies the generic "intro" and "outro" HTML to the given cells.
17254    // Intro means the leftmost cell when the calendar is LTR and the rightmost cell when RTL. Vice-versa for outro.
17255    DayTableMixin.prototype.bookendCells = function (trEl) {
17256        var introHtml = this.renderIntroHtml();
17257        if (introHtml) {
17258            if (this.isRTL) {
17259                trEl.append(introHtml);
17260            }
17261            else {
17262                trEl.prepend(introHtml);
17263            }
17264        }
17265    };
17266    return DayTableMixin;
17267}(Mixin_1.default));
17268exports.default = DayTableMixin;
17269
17270
17271/***/ }),
17272/* 61 */
17273/***/ (function(module, exports) {
17274
17275Object.defineProperty(exports, "__esModule", { value: true });
17276var BusinessHourRenderer = /** @class */ (function () {
17277    /*
17278    component implements:
17279      - eventRangesToEventFootprints
17280      - eventFootprintsToSegs
17281    */
17282    function BusinessHourRenderer(component, fillRenderer) {
17283        this.component = component;
17284        this.fillRenderer = fillRenderer;
17285    }
17286    BusinessHourRenderer.prototype.render = function (businessHourGenerator) {
17287        var component = this.component;
17288        var unzonedRange = component._getDateProfile().activeUnzonedRange;
17289        var eventInstanceGroup = businessHourGenerator.buildEventInstanceGroup(component.hasAllDayBusinessHours, unzonedRange);
17290        var eventFootprints = eventInstanceGroup ?
17291            component.eventRangesToEventFootprints(eventInstanceGroup.sliceRenderRanges(unzonedRange)) :
17292            [];
17293        this.renderEventFootprints(eventFootprints);
17294    };
17295    BusinessHourRenderer.prototype.renderEventFootprints = function (eventFootprints) {
17296        var segs = this.component.eventFootprintsToSegs(eventFootprints);
17297        this.renderSegs(segs);
17298        this.segs = segs;
17299    };
17300    BusinessHourRenderer.prototype.renderSegs = function (segs) {
17301        if (this.fillRenderer) {
17302            this.fillRenderer.renderSegs('businessHours', segs, {
17303                getClasses: function (seg) {
17304                    return ['fc-nonbusiness', 'fc-bgevent'];
17305                }
17306            });
17307        }
17308    };
17309    BusinessHourRenderer.prototype.unrender = function () {
17310        if (this.fillRenderer) {
17311            this.fillRenderer.unrender('businessHours');
17312        }
17313        this.segs = null;
17314    };
17315    BusinessHourRenderer.prototype.getSegs = function () {
17316        return this.segs || [];
17317    };
17318    return BusinessHourRenderer;
17319}());
17320exports.default = BusinessHourRenderer;
17321
17322
17323/***/ }),
17324/* 62 */
17325/***/ (function(module, exports, __webpack_require__) {
17326
17327Object.defineProperty(exports, "__esModule", { value: true });
17328var $ = __webpack_require__(3);
17329var util_1 = __webpack_require__(4);
17330var FillRenderer = /** @class */ (function () {
17331    function FillRenderer(component) {
17332        this.fillSegTag = 'div';
17333        this.component = component;
17334        this.elsByFill = {};
17335    }
17336    FillRenderer.prototype.renderFootprint = function (type, componentFootprint, props) {
17337        this.renderSegs(type, this.component.componentFootprintToSegs(componentFootprint), props);
17338    };
17339    FillRenderer.prototype.renderSegs = function (type, segs, props) {
17340        var els;
17341        segs = this.buildSegEls(type, segs, props); // assignes `.el` to each seg. returns successfully rendered segs
17342        els = this.attachSegEls(type, segs);
17343        if (els) {
17344            this.reportEls(type, els);
17345        }
17346        return segs;
17347    };
17348    // Unrenders a specific type of fill that is currently rendered on the grid
17349    FillRenderer.prototype.unrender = function (type) {
17350        var el = this.elsByFill[type];
17351        if (el) {
17352            el.remove();
17353            delete this.elsByFill[type];
17354        }
17355    };
17356    // Renders and assigns an `el` property for each fill segment. Generic enough to work with different types.
17357    // Only returns segments that successfully rendered.
17358    FillRenderer.prototype.buildSegEls = function (type, segs, props) {
17359        var _this = this;
17360        var html = '';
17361        var renderedSegs = [];
17362        var i;
17363        if (segs.length) {
17364            // build a large concatenation of segment HTML
17365            for (i = 0; i < segs.length; i++) {
17366                html += this.buildSegHtml(type, segs[i], props);
17367            }
17368            // Grab individual elements from the combined HTML string. Use each as the default rendering.
17369            // Then, compute the 'el' for each segment.
17370            $(html).each(function (i, node) {
17371                var seg = segs[i];
17372                var el = $(node);
17373                // allow custom filter methods per-type
17374                if (props.filterEl) {
17375                    el = props.filterEl(seg, el);
17376                }
17377                if (el) { // custom filters did not cancel the render
17378                    el = $(el); // allow custom filter to return raw DOM node
17379                    // correct element type? (would be bad if a non-TD were inserted into a table for example)
17380                    if (el.is(_this.fillSegTag)) {
17381                        seg.el = el;
17382                        renderedSegs.push(seg);
17383                    }
17384                }
17385            });
17386        }
17387        return renderedSegs;
17388    };
17389    // Builds the HTML needed for one fill segment. Generic enough to work with different types.
17390    FillRenderer.prototype.buildSegHtml = function (type, seg, props) {
17391        // custom hooks per-type
17392        var classes = props.getClasses ? props.getClasses(seg) : [];
17393        var css = util_1.cssToStr(props.getCss ? props.getCss(seg) : {});
17394        return '<' + this.fillSegTag +
17395            (classes.length ? ' class="' + classes.join(' ') + '"' : '') +
17396            (css ? ' style="' + css + '"' : '') +
17397            '></' + this.fillSegTag + '>';
17398    };
17399    // Should return wrapping DOM structure
17400    FillRenderer.prototype.attachSegEls = function (type, segs) {
17401        // subclasses must implement
17402    };
17403    FillRenderer.prototype.reportEls = function (type, nodes) {
17404        if (this.elsByFill[type]) {
17405            this.elsByFill[type] = this.elsByFill[type].add(nodes);
17406        }
17407        else {
17408            this.elsByFill[type] = $(nodes);
17409        }
17410    };
17411    return FillRenderer;
17412}());
17413exports.default = FillRenderer;
17414
17415
17416/***/ }),
17417/* 63 */
17418/***/ (function(module, exports, __webpack_require__) {
17419
17420Object.defineProperty(exports, "__esModule", { value: true });
17421var SingleEventDef_1 = __webpack_require__(9);
17422var EventFootprint_1 = __webpack_require__(34);
17423var EventSource_1 = __webpack_require__(6);
17424var HelperRenderer = /** @class */ (function () {
17425    function HelperRenderer(component, eventRenderer) {
17426        this.view = component._getView();
17427        this.component = component;
17428        this.eventRenderer = eventRenderer;
17429    }
17430    HelperRenderer.prototype.renderComponentFootprint = function (componentFootprint) {
17431        this.renderEventFootprints([
17432            this.fabricateEventFootprint(componentFootprint)
17433        ]);
17434    };
17435    HelperRenderer.prototype.renderEventDraggingFootprints = function (eventFootprints, sourceSeg, isTouch) {
17436        this.renderEventFootprints(eventFootprints, sourceSeg, 'fc-dragging', isTouch ? null : this.view.opt('dragOpacity'));
17437    };
17438    HelperRenderer.prototype.renderEventResizingFootprints = function (eventFootprints, sourceSeg, isTouch) {
17439        this.renderEventFootprints(eventFootprints, sourceSeg, 'fc-resizing');
17440    };
17441    HelperRenderer.prototype.renderEventFootprints = function (eventFootprints, sourceSeg, extraClassNames, opacity) {
17442        var segs = this.component.eventFootprintsToSegs(eventFootprints);
17443        var classNames = 'fc-helper ' + (extraClassNames || '');
17444        var i;
17445        // assigns each seg's el and returns a subset of segs that were rendered
17446        segs = this.eventRenderer.renderFgSegEls(segs);
17447        for (i = 0; i < segs.length; i++) {
17448            segs[i].el.addClass(classNames);
17449        }
17450        if (opacity != null) {
17451            for (i = 0; i < segs.length; i++) {
17452                segs[i].el.css('opacity', opacity);
17453            }
17454        }
17455        this.helperEls = this.renderSegs(segs, sourceSeg);
17456    };
17457    /*
17458    Must return all mock event elements
17459    */
17460    HelperRenderer.prototype.renderSegs = function (segs, sourceSeg) {
17461        // Subclasses must implement
17462    };
17463    HelperRenderer.prototype.unrender = function () {
17464        if (this.helperEls) {
17465            this.helperEls.remove();
17466            this.helperEls = null;
17467        }
17468    };
17469    HelperRenderer.prototype.fabricateEventFootprint = function (componentFootprint) {
17470        var calendar = this.view.calendar;
17471        var eventDateProfile = calendar.footprintToDateProfile(componentFootprint);
17472        var dummyEvent = new SingleEventDef_1.default(new EventSource_1.default(calendar));
17473        var dummyInstance;
17474        dummyEvent.dateProfile = eventDateProfile;
17475        dummyInstance = dummyEvent.buildInstance();
17476        return new EventFootprint_1.default(componentFootprint, dummyEvent, dummyInstance);
17477    };
17478    return HelperRenderer;
17479}());
17480exports.default = HelperRenderer;
17481
17482
17483/***/ }),
17484/* 64 */
17485/***/ (function(module, exports, __webpack_require__) {
17486
17487Object.defineProperty(exports, "__esModule", { value: true });
17488var tslib_1 = __webpack_require__(2);
17489var GlobalEmitter_1 = __webpack_require__(23);
17490var Interaction_1 = __webpack_require__(14);
17491var EventPointing = /** @class */ (function (_super) {
17492    tslib_1.__extends(EventPointing, _super);
17493    function EventPointing() {
17494        return _super !== null && _super.apply(this, arguments) || this;
17495    }
17496    /*
17497    component must implement:
17498      - publiclyTrigger
17499    */
17500    EventPointing.prototype.bindToEl = function (el) {
17501        var component = this.component;
17502        component.bindSegHandlerToEl(el, 'click', this.handleClick.bind(this));
17503        component.bindSegHandlerToEl(el, 'mouseenter', this.handleMouseover.bind(this));
17504        component.bindSegHandlerToEl(el, 'mouseleave', this.handleMouseout.bind(this));
17505    };
17506    EventPointing.prototype.handleClick = function (seg, ev) {
17507        var res = this.component.publiclyTrigger('eventClick', {
17508            context: seg.el[0],
17509            args: [seg.footprint.getEventLegacy(), ev, this.view]
17510        });
17511        if (res === false) {
17512            ev.preventDefault();
17513        }
17514    };
17515    // Updates internal state and triggers handlers for when an event element is moused over
17516    EventPointing.prototype.handleMouseover = function (seg, ev) {
17517        if (!GlobalEmitter_1.default.get().shouldIgnoreMouse() &&
17518            !this.mousedOverSeg) {
17519            this.mousedOverSeg = seg;
17520            // TODO: move to EventSelecting's responsibility
17521            if (this.view.isEventDefResizable(seg.footprint.eventDef)) {
17522                seg.el.addClass('fc-allow-mouse-resize');
17523            }
17524            this.component.publiclyTrigger('eventMouseover', {
17525                context: seg.el[0],
17526                args: [seg.footprint.getEventLegacy(), ev, this.view]
17527            });
17528        }
17529    };
17530    // Updates internal state and triggers handlers for when an event element is moused out.
17531    // Can be given no arguments, in which case it will mouseout the segment that was previously moused over.
17532    EventPointing.prototype.handleMouseout = function (seg, ev) {
17533        if (this.mousedOverSeg) {
17534            this.mousedOverSeg = null;
17535            // TODO: move to EventSelecting's responsibility
17536            if (this.view.isEventDefResizable(seg.footprint.eventDef)) {
17537                seg.el.removeClass('fc-allow-mouse-resize');
17538            }
17539            this.component.publiclyTrigger('eventMouseout', {
17540                context: seg.el[0],
17541                args: [
17542                    seg.footprint.getEventLegacy(),
17543                    ev || {},
17544                    this.view
17545                ]
17546            });
17547        }
17548    };
17549    EventPointing.prototype.end = function () {
17550        if (this.mousedOverSeg) {
17551            this.handleMouseout(this.mousedOverSeg);
17552        }
17553    };
17554    return EventPointing;
17555}(Interaction_1.default));
17556exports.default = EventPointing;
17557
17558
17559/***/ }),
17560/* 65 */
17561/***/ (function(module, exports, __webpack_require__) {
17562
17563Object.defineProperty(exports, "__esModule", { value: true });
17564var tslib_1 = __webpack_require__(2);
17565var Mixin_1 = __webpack_require__(15);
17566var DateClicking_1 = __webpack_require__(237);
17567var DateSelecting_1 = __webpack_require__(236);
17568var EventPointing_1 = __webpack_require__(64);
17569var EventDragging_1 = __webpack_require__(235);
17570var EventResizing_1 = __webpack_require__(234);
17571var ExternalDropping_1 = __webpack_require__(233);
17572var StandardInteractionsMixin = /** @class */ (function (_super) {
17573    tslib_1.__extends(StandardInteractionsMixin, _super);
17574    function StandardInteractionsMixin() {
17575        return _super !== null && _super.apply(this, arguments) || this;
17576    }
17577    return StandardInteractionsMixin;
17578}(Mixin_1.default));
17579exports.default = StandardInteractionsMixin;
17580StandardInteractionsMixin.prototype.dateClickingClass = DateClicking_1.default;
17581StandardInteractionsMixin.prototype.dateSelectingClass = DateSelecting_1.default;
17582StandardInteractionsMixin.prototype.eventPointingClass = EventPointing_1.default;
17583StandardInteractionsMixin.prototype.eventDraggingClass = EventDragging_1.default;
17584StandardInteractionsMixin.prototype.eventResizingClass = EventResizing_1.default;
17585StandardInteractionsMixin.prototype.externalDroppingClass = ExternalDropping_1.default;
17586
17587
17588/***/ }),
17589/* 66 */
17590/***/ (function(module, exports, __webpack_require__) {
17591
17592Object.defineProperty(exports, "__esModule", { value: true });
17593var tslib_1 = __webpack_require__(2);
17594var $ = __webpack_require__(3);
17595var util_1 = __webpack_require__(4);
17596var CoordCache_1 = __webpack_require__(58);
17597var Popover_1 = __webpack_require__(227);
17598var UnzonedRange_1 = __webpack_require__(5);
17599var ComponentFootprint_1 = __webpack_require__(12);
17600var EventFootprint_1 = __webpack_require__(34);
17601var BusinessHourRenderer_1 = __webpack_require__(61);
17602var StandardInteractionsMixin_1 = __webpack_require__(65);
17603var InteractiveDateComponent_1 = __webpack_require__(42);
17604var DayTableMixin_1 = __webpack_require__(60);
17605var DayGridEventRenderer_1 = __webpack_require__(243);
17606var DayGridHelperRenderer_1 = __webpack_require__(244);
17607var DayGridFillRenderer_1 = __webpack_require__(245);
17608/* A component that renders a grid of whole-days that runs horizontally. There can be multiple rows, one per week.
17609----------------------------------------------------------------------------------------------------------------------*/
17610var DayGrid = /** @class */ (function (_super) {
17611    tslib_1.__extends(DayGrid, _super);
17612    function DayGrid(view) {
17613        var _this = _super.call(this, view) || this;
17614        _this.cellWeekNumbersVisible = false; // display week numbers in day cell?
17615        _this.bottomCoordPadding = 0; // hack for extending the hit area for the last row of the coordinate grid
17616        // isRigid determines whether the individual rows should ignore the contents and be a constant height.
17617        // Relies on the view's colCnt and rowCnt. In the future, this component should probably be self-sufficient.
17618        _this.isRigid = false;
17619        _this.hasAllDayBusinessHours = true;
17620        return _this;
17621    }
17622    // Slices up the given span (unzoned start/end with other misc data) into an array of segments
17623    DayGrid.prototype.componentFootprintToSegs = function (componentFootprint) {
17624        var segs = this.sliceRangeByRow(componentFootprint.unzonedRange);
17625        var i;
17626        var seg;
17627        for (i = 0; i < segs.length; i++) {
17628            seg = segs[i];
17629            if (this.isRTL) {
17630                seg.leftCol = this.daysPerRow - 1 - seg.lastRowDayIndex;
17631                seg.rightCol = this.daysPerRow - 1 - seg.firstRowDayIndex;
17632            }
17633            else {
17634                seg.leftCol = seg.firstRowDayIndex;
17635                seg.rightCol = seg.lastRowDayIndex;
17636            }
17637        }
17638        return segs;
17639    };
17640    /* Date Rendering
17641    ------------------------------------------------------------------------------------------------------------------*/
17642    DayGrid.prototype.renderDates = function (dateProfile) {
17643        this.dateProfile = dateProfile;
17644        this.updateDayTable();
17645        this.renderGrid();
17646    };
17647    DayGrid.prototype.unrenderDates = function () {
17648        this.removeSegPopover();
17649    };
17650    // Renders the rows and columns into the component's `this.el`, which should already be assigned.
17651    DayGrid.prototype.renderGrid = function () {
17652        var view = this.view;
17653        var rowCnt = this.rowCnt;
17654        var colCnt = this.colCnt;
17655        var html = '';
17656        var row;
17657        var col;
17658        if (this.headContainerEl) {
17659            this.headContainerEl.html(this.renderHeadHtml());
17660        }
17661        for (row = 0; row < rowCnt; row++) {
17662            html += this.renderDayRowHtml(row, this.isRigid);
17663        }
17664        this.el.html(html);
17665        this.rowEls = this.el.find('.fc-row');
17666        this.cellEls = this.el.find('.fc-day, .fc-disabled-day');
17667        this.rowCoordCache = new CoordCache_1.default({
17668            els: this.rowEls,
17669            isVertical: true
17670        });
17671        this.colCoordCache = new CoordCache_1.default({
17672            els: this.cellEls.slice(0, this.colCnt),
17673            isHorizontal: true
17674        });
17675        // trigger dayRender with each cell's element
17676        for (row = 0; row < rowCnt; row++) {
17677            for (col = 0; col < colCnt; col++) {
17678                this.publiclyTrigger('dayRender', {
17679                    context: view,
17680                    args: [
17681                        this.getCellDate(row, col),
17682                        this.getCellEl(row, col),
17683                        view
17684                    ]
17685                });
17686            }
17687        }
17688    };
17689    // Generates the HTML for a single row, which is a div that wraps a table.
17690    // `row` is the row number.
17691    DayGrid.prototype.renderDayRowHtml = function (row, isRigid) {
17692        var theme = this.view.calendar.theme;
17693        var classes = ['fc-row', 'fc-week', theme.getClass('dayRow')];
17694        if (isRigid) {
17695            classes.push('fc-rigid');
17696        }
17697        return '' +
17698            '<div class="' + classes.join(' ') + '">' +
17699            '<div class="fc-bg">' +
17700            '<table class="' + theme.getClass('tableGrid') + '">' +
17701            this.renderBgTrHtml(row) +
17702            '</table>' +
17703            '</div>' +
17704            '<div class="fc-content-skeleton">' +
17705            '<table>' +
17706            (this.getIsNumbersVisible() ?
17707                '<thead>' +
17708                    this.renderNumberTrHtml(row) +
17709                    '</thead>' :
17710                '') +
17711            '</table>' +
17712            '</div>' +
17713            '</div>';
17714    };
17715    DayGrid.prototype.getIsNumbersVisible = function () {
17716        return this.getIsDayNumbersVisible() || this.cellWeekNumbersVisible;
17717    };
17718    DayGrid.prototype.getIsDayNumbersVisible = function () {
17719        return this.rowCnt > 1;
17720    };
17721    /* Grid Number Rendering
17722    ------------------------------------------------------------------------------------------------------------------*/
17723    DayGrid.prototype.renderNumberTrHtml = function (row) {
17724        return '' +
17725            '<tr>' +
17726            (this.isRTL ? '' : this.renderNumberIntroHtml(row)) +
17727            this.renderNumberCellsHtml(row) +
17728            (this.isRTL ? this.renderNumberIntroHtml(row) : '') +
17729            '</tr>';
17730    };
17731    DayGrid.prototype.renderNumberIntroHtml = function (row) {
17732        return this.renderIntroHtml();
17733    };
17734    DayGrid.prototype.renderNumberCellsHtml = function (row) {
17735        var htmls = [];
17736        var col;
17737        var date;
17738        for (col = 0; col < this.colCnt; col++) {
17739            date = this.getCellDate(row, col);
17740            htmls.push(this.renderNumberCellHtml(date));
17741        }
17742        return htmls.join('');
17743    };
17744    // Generates the HTML for the <td>s of the "number" row in the DayGrid's content skeleton.
17745    // The number row will only exist if either day numbers or week numbers are turned on.
17746    DayGrid.prototype.renderNumberCellHtml = function (date) {
17747        var view = this.view;
17748        var html = '';
17749        var isDateValid = this.dateProfile.activeUnzonedRange.containsDate(date); // TODO: called too frequently. cache somehow.
17750        var isDayNumberVisible = this.getIsDayNumbersVisible() && isDateValid;
17751        var classes;
17752        var weekCalcFirstDoW;
17753        if (!isDayNumberVisible && !this.cellWeekNumbersVisible) {
17754            // no numbers in day cell (week number must be along the side)
17755            return '<td></td>'; //  will create an empty space above events :(
17756        }
17757        classes = this.getDayClasses(date);
17758        classes.unshift('fc-day-top');
17759        if (this.cellWeekNumbersVisible) {
17760            // To determine the day of week number change under ISO, we cannot
17761            // rely on moment.js methods such as firstDayOfWeek() or weekday(),
17762            // because they rely on the locale's dow (possibly overridden by
17763            // our firstDay option), which may not be Monday. We cannot change
17764            // dow, because that would affect the calendar start day as well.
17765            if (date._locale._fullCalendar_weekCalc === 'ISO') {
17766                weekCalcFirstDoW = 1; // Monday by ISO 8601 definition
17767            }
17768            else {
17769                weekCalcFirstDoW = date._locale.firstDayOfWeek();
17770            }
17771        }
17772        html += '<td class="' + classes.join(' ') + '"' +
17773            (isDateValid ?
17774                ' data-date="' + date.format() + '"' :
17775                '') +
17776            '>';
17777        if (this.cellWeekNumbersVisible && (date.day() === weekCalcFirstDoW)) {
17778            html += view.buildGotoAnchorHtml({ date: date, type: 'week' }, { 'class': 'fc-week-number' }, date.format('w') // inner HTML
17779            );
17780        }
17781        if (isDayNumberVisible) {
17782            html += view.buildGotoAnchorHtml(date, { 'class': 'fc-day-number' }, date.format('D') // inner HTML
17783            );
17784        }
17785        html += '</td>';
17786        return html;
17787    };
17788    /* Hit System
17789    ------------------------------------------------------------------------------------------------------------------*/
17790    DayGrid.prototype.prepareHits = function () {
17791        this.colCoordCache.build();
17792        this.rowCoordCache.build();
17793        this.rowCoordCache.bottoms[this.rowCnt - 1] += this.bottomCoordPadding; // hack
17794    };
17795    DayGrid.prototype.releaseHits = function () {
17796        this.colCoordCache.clear();
17797        this.rowCoordCache.clear();
17798    };
17799    DayGrid.prototype.queryHit = function (leftOffset, topOffset) {
17800        if (this.colCoordCache.isLeftInBounds(leftOffset) && this.rowCoordCache.isTopInBounds(topOffset)) {
17801            var col = this.colCoordCache.getHorizontalIndex(leftOffset);
17802            var row = this.rowCoordCache.getVerticalIndex(topOffset);
17803            if (row != null && col != null) {
17804                return this.getCellHit(row, col);
17805            }
17806        }
17807    };
17808    DayGrid.prototype.getHitFootprint = function (hit) {
17809        var range = this.getCellRange(hit.row, hit.col);
17810        return new ComponentFootprint_1.default(new UnzonedRange_1.default(range.start, range.end), true // all-day?
17811        );
17812    };
17813    DayGrid.prototype.getHitEl = function (hit) {
17814        return this.getCellEl(hit.row, hit.col);
17815    };
17816    /* Cell System
17817    ------------------------------------------------------------------------------------------------------------------*/
17818    // FYI: the first column is the leftmost column, regardless of date
17819    DayGrid.prototype.getCellHit = function (row, col) {
17820        return {
17821            row: row,
17822            col: col,
17823            component: this,
17824            left: this.colCoordCache.getLeftOffset(col),
17825            right: this.colCoordCache.getRightOffset(col),
17826            top: this.rowCoordCache.getTopOffset(row),
17827            bottom: this.rowCoordCache.getBottomOffset(row)
17828        };
17829    };
17830    DayGrid.prototype.getCellEl = function (row, col) {
17831        return this.cellEls.eq(row * this.colCnt + col);
17832    };
17833    /* Event Rendering
17834    ------------------------------------------------------------------------------------------------------------------*/
17835    // Unrenders all events currently rendered on the grid
17836    DayGrid.prototype.executeEventUnrender = function () {
17837        this.removeSegPopover(); // removes the "more.." events popover
17838        _super.prototype.executeEventUnrender.call(this);
17839    };
17840    // Retrieves all rendered segment objects currently rendered on the grid
17841    DayGrid.prototype.getOwnEventSegs = function () {
17842        // append the segments from the "more..." popover
17843        return _super.prototype.getOwnEventSegs.call(this).concat(this.popoverSegs || []);
17844    };
17845    /* Event Drag Visualization
17846    ------------------------------------------------------------------------------------------------------------------*/
17847    // Renders a visual indication of an event or external element being dragged.
17848    // `eventLocation` has zoned start and end (optional)
17849    DayGrid.prototype.renderDrag = function (eventFootprints, seg, isTouch) {
17850        var i;
17851        for (i = 0; i < eventFootprints.length; i++) {
17852            this.renderHighlight(eventFootprints[i].componentFootprint);
17853        }
17854        // render drags from OTHER components as helpers
17855        if (eventFootprints.length && seg && seg.component !== this) {
17856            this.helperRenderer.renderEventDraggingFootprints(eventFootprints, seg, isTouch);
17857            return true; // signal helpers rendered
17858        }
17859    };
17860    // Unrenders any visual indication of a hovering event
17861    DayGrid.prototype.unrenderDrag = function () {
17862        this.unrenderHighlight();
17863        this.helperRenderer.unrender();
17864    };
17865    /* Event Resize Visualization
17866    ------------------------------------------------------------------------------------------------------------------*/
17867    // Renders a visual indication of an event being resized
17868    DayGrid.prototype.renderEventResize = function (eventFootprints, seg, isTouch) {
17869        var i;
17870        for (i = 0; i < eventFootprints.length; i++) {
17871            this.renderHighlight(eventFootprints[i].componentFootprint);
17872        }
17873        this.helperRenderer.renderEventResizingFootprints(eventFootprints, seg, isTouch);
17874    };
17875    // Unrenders a visual indication of an event being resized
17876    DayGrid.prototype.unrenderEventResize = function () {
17877        this.unrenderHighlight();
17878        this.helperRenderer.unrender();
17879    };
17880    /* More+ Link Popover
17881    ------------------------------------------------------------------------------------------------------------------*/
17882    DayGrid.prototype.removeSegPopover = function () {
17883        if (this.segPopover) {
17884            this.segPopover.hide(); // in handler, will call segPopover's removeElement
17885        }
17886    };
17887    // Limits the number of "levels" (vertically stacking layers of events) for each row of the grid.
17888    // `levelLimit` can be false (don't limit), a number, or true (should be computed).
17889    DayGrid.prototype.limitRows = function (levelLimit) {
17890        var rowStructs = this.eventRenderer.rowStructs || [];
17891        var row; // row #
17892        var rowLevelLimit;
17893        for (row = 0; row < rowStructs.length; row++) {
17894            this.unlimitRow(row);
17895            if (!levelLimit) {
17896                rowLevelLimit = false;
17897            }
17898            else if (typeof levelLimit === 'number') {
17899                rowLevelLimit = levelLimit;
17900            }
17901            else {
17902                rowLevelLimit = this.computeRowLevelLimit(row);
17903            }
17904            if (rowLevelLimit !== false) {
17905                this.limitRow(row, rowLevelLimit);
17906            }
17907        }
17908    };
17909    // Computes the number of levels a row will accomodate without going outside its bounds.
17910    // Assumes the row is "rigid" (maintains a constant height regardless of what is inside).
17911    // `row` is the row number.
17912    DayGrid.prototype.computeRowLevelLimit = function (row) {
17913        var rowEl = this.rowEls.eq(row); // the containing "fake" row div
17914        var rowHeight = rowEl.height(); // TODO: cache somehow?
17915        var trEls = this.eventRenderer.rowStructs[row].tbodyEl.children();
17916        var i;
17917        var trEl;
17918        var trHeight;
17919        function iterInnerHeights(i, childNode) {
17920            trHeight = Math.max(trHeight, $(childNode).outerHeight());
17921        }
17922        // Reveal one level <tr> at a time and stop when we find one out of bounds
17923        for (i = 0; i < trEls.length; i++) {
17924            trEl = trEls.eq(i).removeClass('fc-limited'); // reset to original state (reveal)
17925            // with rowspans>1 and IE8, trEl.outerHeight() would return the height of the largest cell,
17926            // so instead, find the tallest inner content element.
17927            trHeight = 0;
17928            trEl.find('> td > :first-child').each(iterInnerHeights);
17929            if (trEl.position().top + trHeight > rowHeight) {
17930                return i;
17931            }
17932        }
17933        return false; // should not limit at all
17934    };
17935    // Limits the given grid row to the maximum number of levels and injects "more" links if necessary.
17936    // `row` is the row number.
17937    // `levelLimit` is a number for the maximum (inclusive) number of levels allowed.
17938    DayGrid.prototype.limitRow = function (row, levelLimit) {
17939        var _this = this;
17940        var rowStruct = this.eventRenderer.rowStructs[row];
17941        var moreNodes = []; // array of "more" <a> links and <td> DOM nodes
17942        var col = 0; // col #, left-to-right (not chronologically)
17943        var levelSegs; // array of segment objects in the last allowable level, ordered left-to-right
17944        var cellMatrix; // a matrix (by level, then column) of all <td> jQuery elements in the row
17945        var limitedNodes; // array of temporarily hidden level <tr> and segment <td> DOM nodes
17946        var i;
17947        var seg;
17948        var segsBelow; // array of segment objects below `seg` in the current `col`
17949        var totalSegsBelow; // total number of segments below `seg` in any of the columns `seg` occupies
17950        var colSegsBelow; // array of segment arrays, below seg, one for each column (offset from segs's first column)
17951        var td;
17952        var rowspan;
17953        var segMoreNodes; // array of "more" <td> cells that will stand-in for the current seg's cell
17954        var j;
17955        var moreTd;
17956        var moreWrap;
17957        var moreLink;
17958        // Iterates through empty level cells and places "more" links inside if need be
17959        var emptyCellsUntil = function (endCol) {
17960            while (col < endCol) {
17961                segsBelow = _this.getCellSegs(row, col, levelLimit);
17962                if (segsBelow.length) {
17963                    td = cellMatrix[levelLimit - 1][col];
17964                    moreLink = _this.renderMoreLink(row, col, segsBelow);
17965                    moreWrap = $('<div>').append(moreLink);
17966                    td.append(moreWrap);
17967                    moreNodes.push(moreWrap[0]);
17968                }
17969                col++;
17970            }
17971        };
17972        if (levelLimit && levelLimit < rowStruct.segLevels.length) { // is it actually over the limit?
17973            levelSegs = rowStruct.segLevels[levelLimit - 1];
17974            cellMatrix = rowStruct.cellMatrix;
17975            limitedNodes = rowStruct.tbodyEl.children().slice(levelLimit) // get level <tr> elements past the limit
17976                .addClass('fc-limited').get(); // hide elements and get a simple DOM-nodes array
17977            // iterate though segments in the last allowable level
17978            for (i = 0; i < levelSegs.length; i++) {
17979                seg = levelSegs[i];
17980                emptyCellsUntil(seg.leftCol); // process empty cells before the segment
17981                // determine *all* segments below `seg` that occupy the same columns
17982                colSegsBelow = [];
17983                totalSegsBelow = 0;
17984                while (col <= seg.rightCol) {
17985                    segsBelow = this.getCellSegs(row, col, levelLimit);
17986                    colSegsBelow.push(segsBelow);
17987                    totalSegsBelow += segsBelow.length;
17988                    col++;
17989                }
17990                if (totalSegsBelow) { // do we need to replace this segment with one or many "more" links?
17991                    td = cellMatrix[levelLimit - 1][seg.leftCol]; // the segment's parent cell
17992                    rowspan = td.attr('rowspan') || 1;
17993                    segMoreNodes = [];
17994                    // make a replacement <td> for each column the segment occupies. will be one for each colspan
17995                    for (j = 0; j < colSegsBelow.length; j++) {
17996                        moreTd = $('<td class="fc-more-cell">').attr('rowspan', rowspan);
17997                        segsBelow = colSegsBelow[j];
17998                        moreLink = this.renderMoreLink(row, seg.leftCol + j, [seg].concat(segsBelow) // count seg as hidden too
17999                        );
18000                        moreWrap = $('<div>').append(moreLink);
18001                        moreTd.append(moreWrap);
18002                        segMoreNodes.push(moreTd[0]);
18003                        moreNodes.push(moreTd[0]);
18004                    }
18005                    td.addClass('fc-limited').after($(segMoreNodes)); // hide original <td> and inject replacements
18006                    limitedNodes.push(td[0]);
18007                }
18008            }
18009            emptyCellsUntil(this.colCnt); // finish off the level
18010            rowStruct.moreEls = $(moreNodes); // for easy undoing later
18011            rowStruct.limitedEls = $(limitedNodes); // for easy undoing later
18012        }
18013    };
18014    // Reveals all levels and removes all "more"-related elements for a grid's row.
18015    // `row` is a row number.
18016    DayGrid.prototype.unlimitRow = function (row) {
18017        var rowStruct = this.eventRenderer.rowStructs[row];
18018        if (rowStruct.moreEls) {
18019            rowStruct.moreEls.remove();
18020            rowStruct.moreEls = null;
18021        }
18022        if (rowStruct.limitedEls) {
18023            rowStruct.limitedEls.removeClass('fc-limited');
18024            rowStruct.limitedEls = null;
18025        }
18026    };
18027    // Renders an <a> element that represents hidden event element for a cell.
18028    // Responsible for attaching click handler as well.
18029    DayGrid.prototype.renderMoreLink = function (row, col, hiddenSegs) {
18030        var _this = this;
18031        var view = this.view;
18032        return $('<a class="fc-more">')
18033            .text(this.getMoreLinkText(hiddenSegs.length))
18034            .on('click', function (ev) {
18035            var clickOption = _this.opt('eventLimitClick');
18036            var date = _this.getCellDate(row, col);
18037            var moreEl = $(ev.currentTarget);
18038            var dayEl = _this.getCellEl(row, col);
18039            var allSegs = _this.getCellSegs(row, col);
18040            // rescope the segments to be within the cell's date
18041            var reslicedAllSegs = _this.resliceDaySegs(allSegs, date);
18042            var reslicedHiddenSegs = _this.resliceDaySegs(hiddenSegs, date);
18043            if (typeof clickOption === 'function') {
18044                // the returned value can be an atomic option
18045                clickOption = _this.publiclyTrigger('eventLimitClick', {
18046                    context: view,
18047                    args: [
18048                        {
18049                            date: date.clone(),
18050                            dayEl: dayEl,
18051                            moreEl: moreEl,
18052                            segs: reslicedAllSegs,
18053                            hiddenSegs: reslicedHiddenSegs
18054                        },
18055                        ev,
18056                        view
18057                    ]
18058                });
18059            }
18060            if (clickOption === 'popover') {
18061                _this.showSegPopover(row, col, moreEl, reslicedAllSegs);
18062            }
18063            else if (typeof clickOption === 'string') { // a view name
18064                view.calendar.zoomTo(date, clickOption);
18065            }
18066        });
18067    };
18068    // Reveals the popover that displays all events within a cell
18069    DayGrid.prototype.showSegPopover = function (row, col, moreLink, segs) {
18070        var _this = this;
18071        var view = this.view;
18072        var moreWrap = moreLink.parent(); // the <div> wrapper around the <a>
18073        var topEl; // the element we want to match the top coordinate of
18074        var options;
18075        if (this.rowCnt === 1) {
18076            topEl = view.el; // will cause the popover to cover any sort of header
18077        }
18078        else {
18079            topEl = this.rowEls.eq(row); // will align with top of row
18080        }
18081        options = {
18082            className: 'fc-more-popover ' + view.calendar.theme.getClass('popover'),
18083            content: this.renderSegPopoverContent(row, col, segs),
18084            parentEl: view.el,
18085            top: topEl.offset().top,
18086            autoHide: true,
18087            viewportConstrain: this.opt('popoverViewportConstrain'),
18088            hide: function () {
18089                // kill everything when the popover is hidden
18090                // notify events to be removed
18091                if (_this.popoverSegs) {
18092                    _this.triggerBeforeEventSegsDestroyed(_this.popoverSegs);
18093                }
18094                _this.segPopover.removeElement();
18095                _this.segPopover = null;
18096                _this.popoverSegs = null;
18097            }
18098        };
18099        // Determine horizontal coordinate.
18100        // We use the moreWrap instead of the <td> to avoid border confusion.
18101        if (this.isRTL) {
18102            options.right = moreWrap.offset().left + moreWrap.outerWidth() + 1; // +1 to be over cell border
18103        }
18104        else {
18105            options.left = moreWrap.offset().left - 1; // -1 to be over cell border
18106        }
18107        this.segPopover = new Popover_1.default(options);
18108        this.segPopover.show();
18109        // the popover doesn't live within the grid's container element, and thus won't get the event
18110        // delegated-handlers for free. attach event-related handlers to the popover.
18111        this.bindAllSegHandlersToEl(this.segPopover.el);
18112        this.triggerAfterEventSegsRendered(segs);
18113    };
18114    // Builds the inner DOM contents of the segment popover
18115    DayGrid.prototype.renderSegPopoverContent = function (row, col, segs) {
18116        var view = this.view;
18117        var theme = view.calendar.theme;
18118        var title = this.getCellDate(row, col).format(this.opt('dayPopoverFormat'));
18119        var content = $('<div class="fc-header ' + theme.getClass('popoverHeader') + '">' +
18120            '<span class="fc-close ' + theme.getIconClass('close') + '"></span>' +
18121            '<span class="fc-title">' +
18122            util_1.htmlEscape(title) +
18123            '</span>' +
18124            '<div class="fc-clear"></div>' +
18125            '</div>' +
18126            '<div class="fc-body ' + theme.getClass('popoverContent') + '">' +
18127            '<div class="fc-event-container"></div>' +
18128            '</div>');
18129        var segContainer = content.find('.fc-event-container');
18130        var i;
18131        // render each seg's `el` and only return the visible segs
18132        segs = this.eventRenderer.renderFgSegEls(segs, true); // disableResizing=true
18133        this.popoverSegs = segs;
18134        for (i = 0; i < segs.length; i++) {
18135            // because segments in the popover are not part of a grid coordinate system, provide a hint to any
18136            // grids that want to do drag-n-drop about which cell it came from
18137            this.hitsNeeded();
18138            segs[i].hit = this.getCellHit(row, col);
18139            this.hitsNotNeeded();
18140            segContainer.append(segs[i].el);
18141        }
18142        return content;
18143    };
18144    // Given the events within an array of segment objects, reslice them to be in a single day
18145    DayGrid.prototype.resliceDaySegs = function (segs, dayDate) {
18146        var dayStart = dayDate.clone();
18147        var dayEnd = dayStart.clone().add(1, 'days');
18148        var dayRange = new UnzonedRange_1.default(dayStart, dayEnd);
18149        var newSegs = [];
18150        var i;
18151        var seg;
18152        var slicedRange;
18153        for (i = 0; i < segs.length; i++) {
18154            seg = segs[i];
18155            slicedRange = seg.footprint.componentFootprint.unzonedRange.intersect(dayRange);
18156            if (slicedRange) {
18157                newSegs.push($.extend({}, seg, {
18158                    footprint: new EventFootprint_1.default(new ComponentFootprint_1.default(slicedRange, seg.footprint.componentFootprint.isAllDay), seg.footprint.eventDef, seg.footprint.eventInstance),
18159                    isStart: seg.isStart && slicedRange.isStart,
18160                    isEnd: seg.isEnd && slicedRange.isEnd
18161                }));
18162            }
18163        }
18164        // force an order because eventsToSegs doesn't guarantee one
18165        // TODO: research if still needed
18166        this.eventRenderer.sortEventSegs(newSegs);
18167        return newSegs;
18168    };
18169    // Generates the text that should be inside a "more" link, given the number of events it represents
18170    DayGrid.prototype.getMoreLinkText = function (num) {
18171        var opt = this.opt('eventLimitText');
18172        if (typeof opt === 'function') {
18173            return opt(num);
18174        }
18175        else {
18176            return '+' + num + ' ' + opt;
18177        }
18178    };
18179    // Returns segments within a given cell.
18180    // If `startLevel` is specified, returns only events including and below that level. Otherwise returns all segs.
18181    DayGrid.prototype.getCellSegs = function (row, col, startLevel) {
18182        var segMatrix = this.eventRenderer.rowStructs[row].segMatrix;
18183        var level = startLevel || 0;
18184        var segs = [];
18185        var seg;
18186        while (level < segMatrix.length) {
18187            seg = segMatrix[level][col];
18188            if (seg) {
18189                segs.push(seg);
18190            }
18191            level++;
18192        }
18193        return segs;
18194    };
18195    return DayGrid;
18196}(InteractiveDateComponent_1.default));
18197exports.default = DayGrid;
18198DayGrid.prototype.eventRendererClass = DayGridEventRenderer_1.default;
18199DayGrid.prototype.businessHourRendererClass = BusinessHourRenderer_1.default;
18200DayGrid.prototype.helperRendererClass = DayGridHelperRenderer_1.default;
18201DayGrid.prototype.fillRendererClass = DayGridFillRenderer_1.default;
18202StandardInteractionsMixin_1.default.mixInto(DayGrid);
18203DayTableMixin_1.default.mixInto(DayGrid);
18204
18205
18206/***/ }),
18207/* 67 */
18208/***/ (function(module, exports, __webpack_require__) {
18209
18210Object.defineProperty(exports, "__esModule", { value: true });
18211var tslib_1 = __webpack_require__(2);
18212var $ = __webpack_require__(3);
18213var util_1 = __webpack_require__(4);
18214var Scroller_1 = __webpack_require__(41);
18215var View_1 = __webpack_require__(43);
18216var BasicViewDateProfileGenerator_1 = __webpack_require__(68);
18217var DayGrid_1 = __webpack_require__(66);
18218/* An abstract class for the "basic" views, as well as month view. Renders one or more rows of day cells.
18219----------------------------------------------------------------------------------------------------------------------*/
18220// It is a manager for a DayGrid subcomponent, which does most of the heavy lifting.
18221// It is responsible for managing width/height.
18222var BasicView = /** @class */ (function (_super) {
18223    tslib_1.__extends(BasicView, _super);
18224    function BasicView(calendar, viewSpec) {
18225        var _this = _super.call(this, calendar, viewSpec) || this;
18226        _this.dayGrid = _this.instantiateDayGrid();
18227        _this.dayGrid.isRigid = _this.hasRigidRows();
18228        if (_this.opt('weekNumbers')) {
18229            if (_this.opt('weekNumbersWithinDays')) {
18230                _this.dayGrid.cellWeekNumbersVisible = true;
18231                _this.dayGrid.colWeekNumbersVisible = false;
18232            }
18233            else {
18234                _this.dayGrid.cellWeekNumbersVisible = false;
18235                _this.dayGrid.colWeekNumbersVisible = true;
18236            }
18237        }
18238        _this.addChild(_this.dayGrid);
18239        _this.scroller = new Scroller_1.default({
18240            overflowX: 'hidden',
18241            overflowY: 'auto'
18242        });
18243        return _this;
18244    }
18245    // Generates the DayGrid object this view needs. Draws from this.dayGridClass
18246    BasicView.prototype.instantiateDayGrid = function () {
18247        // generate a subclass on the fly with BasicView-specific behavior
18248        // TODO: cache this subclass
18249        var subclass = makeDayGridSubclass(this.dayGridClass);
18250        return new subclass(this);
18251    };
18252    BasicView.prototype.executeDateRender = function (dateProfile) {
18253        this.dayGrid.breakOnWeeks = /year|month|week/.test(dateProfile.currentRangeUnit);
18254        _super.prototype.executeDateRender.call(this, dateProfile);
18255    };
18256    BasicView.prototype.renderSkeleton = function () {
18257        var dayGridContainerEl;
18258        var dayGridEl;
18259        this.el.addClass('fc-basic-view').html(this.renderSkeletonHtml());
18260        this.scroller.render();
18261        dayGridContainerEl = this.scroller.el.addClass('fc-day-grid-container');
18262        dayGridEl = $('<div class="fc-day-grid">').appendTo(dayGridContainerEl);
18263        this.el.find('.fc-body > tr > td').append(dayGridContainerEl);
18264        this.dayGrid.headContainerEl = this.el.find('.fc-head-container');
18265        this.dayGrid.setElement(dayGridEl);
18266    };
18267    BasicView.prototype.unrenderSkeleton = function () {
18268        this.dayGrid.removeElement();
18269        this.scroller.destroy();
18270    };
18271    // Builds the HTML skeleton for the view.
18272    // The day-grid component will render inside of a container defined by this HTML.
18273    BasicView.prototype.renderSkeletonHtml = function () {
18274        var theme = this.calendar.theme;
18275        return '' +
18276            '<table class="' + theme.getClass('tableGrid') + '">' +
18277            (this.opt('columnHeader') ?
18278                '<thead class="fc-head">' +
18279                    '<tr>' +
18280                    '<td class="fc-head-container ' + theme.getClass('widgetHeader') + '">&nbsp;</td>' +
18281                    '</tr>' +
18282                    '</thead>' :
18283                '') +
18284            '<tbody class="fc-body">' +
18285            '<tr>' +
18286            '<td class="' + theme.getClass('widgetContent') + '"></td>' +
18287            '</tr>' +
18288            '</tbody>' +
18289            '</table>';
18290    };
18291    // Generates an HTML attribute string for setting the width of the week number column, if it is known
18292    BasicView.prototype.weekNumberStyleAttr = function () {
18293        if (this.weekNumberWidth != null) {
18294            return 'style="width:' + this.weekNumberWidth + 'px"';
18295        }
18296        return '';
18297    };
18298    // Determines whether each row should have a constant height
18299    BasicView.prototype.hasRigidRows = function () {
18300        var eventLimit = this.opt('eventLimit');
18301        return eventLimit && typeof eventLimit !== 'number';
18302    };
18303    /* Dimensions
18304    ------------------------------------------------------------------------------------------------------------------*/
18305    // Refreshes the horizontal dimensions of the view
18306    BasicView.prototype.updateSize = function (totalHeight, isAuto, isResize) {
18307        var eventLimit = this.opt('eventLimit');
18308        var headRowEl = this.dayGrid.headContainerEl.find('.fc-row');
18309        var scrollerHeight;
18310        var scrollbarWidths;
18311        // hack to give the view some height prior to dayGrid's columns being rendered
18312        // TODO: separate setting height from scroller VS dayGrid.
18313        if (!this.dayGrid.rowEls) {
18314            if (!isAuto) {
18315                scrollerHeight = this.computeScrollerHeight(totalHeight);
18316                this.scroller.setHeight(scrollerHeight);
18317            }
18318            return;
18319        }
18320        _super.prototype.updateSize.call(this, totalHeight, isAuto, isResize);
18321        if (this.dayGrid.colWeekNumbersVisible) {
18322            // Make sure all week number cells running down the side have the same width.
18323            // Record the width for cells created later.
18324            this.weekNumberWidth = util_1.matchCellWidths(this.el.find('.fc-week-number'));
18325        }
18326        // reset all heights to be natural
18327        this.scroller.clear();
18328        util_1.uncompensateScroll(headRowEl);
18329        this.dayGrid.removeSegPopover(); // kill the "more" popover if displayed
18330        // is the event limit a constant level number?
18331        if (eventLimit && typeof eventLimit === 'number') {
18332            this.dayGrid.limitRows(eventLimit); // limit the levels first so the height can redistribute after
18333        }
18334        // distribute the height to the rows
18335        // (totalHeight is a "recommended" value if isAuto)
18336        scrollerHeight = this.computeScrollerHeight(totalHeight);
18337        this.setGridHeight(scrollerHeight, isAuto);
18338        // is the event limit dynamically calculated?
18339        if (eventLimit && typeof eventLimit !== 'number') {
18340            this.dayGrid.limitRows(eventLimit); // limit the levels after the grid's row heights have been set
18341        }
18342        if (!isAuto) { // should we force dimensions of the scroll container?
18343            this.scroller.setHeight(scrollerHeight);
18344            scrollbarWidths = this.scroller.getScrollbarWidths();
18345            if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?
18346                util_1.compensateScroll(headRowEl, scrollbarWidths);
18347                // doing the scrollbar compensation might have created text overflow which created more height. redo
18348                scrollerHeight = this.computeScrollerHeight(totalHeight);
18349                this.scroller.setHeight(scrollerHeight);
18350            }
18351            // guarantees the same scrollbar widths
18352            this.scroller.lockOverflow(scrollbarWidths);
18353        }
18354    };
18355    // given a desired total height of the view, returns what the height of the scroller should be
18356    BasicView.prototype.computeScrollerHeight = function (totalHeight) {
18357        return totalHeight -
18358            util_1.subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
18359    };
18360    // Sets the height of just the DayGrid component in this view
18361    BasicView.prototype.setGridHeight = function (height, isAuto) {
18362        if (isAuto) {
18363            util_1.undistributeHeight(this.dayGrid.rowEls); // let the rows be their natural height with no expanding
18364        }
18365        else {
18366            util_1.distributeHeight(this.dayGrid.rowEls, height, true); // true = compensate for height-hogging rows
18367        }
18368    };
18369    /* Scroll
18370    ------------------------------------------------------------------------------------------------------------------*/
18371    BasicView.prototype.computeInitialDateScroll = function () {
18372        return { top: 0 };
18373    };
18374    BasicView.prototype.queryDateScroll = function () {
18375        return { top: this.scroller.getScrollTop() };
18376    };
18377    BasicView.prototype.applyDateScroll = function (scroll) {
18378        if (scroll.top !== undefined) {
18379            this.scroller.setScrollTop(scroll.top);
18380        }
18381    };
18382    return BasicView;
18383}(View_1.default));
18384exports.default = BasicView;
18385BasicView.prototype.dateProfileGeneratorClass = BasicViewDateProfileGenerator_1.default;
18386BasicView.prototype.dayGridClass = DayGrid_1.default;
18387// customize the rendering behavior of BasicView's dayGrid
18388function makeDayGridSubclass(SuperClass) {
18389    return /** @class */ (function (_super) {
18390        tslib_1.__extends(SubClass, _super);
18391        function SubClass() {
18392            var _this = _super !== null && _super.apply(this, arguments) || this;
18393            _this.colWeekNumbersVisible = false; // display week numbers along the side?
18394            return _this;
18395        }
18396        // Generates the HTML that will go before the day-of week header cells
18397        SubClass.prototype.renderHeadIntroHtml = function () {
18398            var view = this.view;
18399            if (this.colWeekNumbersVisible) {
18400                return '' +
18401                    '<th class="fc-week-number ' + view.calendar.theme.getClass('widgetHeader') + '" ' + view.weekNumberStyleAttr() + '>' +
18402                    '<span>' + // needed for matchCellWidths
18403                    util_1.htmlEscape(this.opt('weekNumberTitle')) +
18404                    '</span>' +
18405                    '</th>';
18406            }
18407            return '';
18408        };
18409        // Generates the HTML that will go before content-skeleton cells that display the day/week numbers
18410        SubClass.prototype.renderNumberIntroHtml = function (row) {
18411            var view = this.view;
18412            var weekStart = this.getCellDate(row, 0);
18413            if (this.colWeekNumbersVisible) {
18414                return '' +
18415                    '<td class="fc-week-number" ' + view.weekNumberStyleAttr() + '>' +
18416                    view.buildGotoAnchorHtml(// aside from link, important for matchCellWidths
18417                    { date: weekStart, type: 'week', forceOff: this.colCnt === 1 }, weekStart.format('w') // inner HTML
18418                    ) +
18419                    '</td>';
18420            }
18421            return '';
18422        };
18423        // Generates the HTML that goes before the day bg cells for each day-row
18424        SubClass.prototype.renderBgIntroHtml = function () {
18425            var view = this.view;
18426            if (this.colWeekNumbersVisible) {
18427                return '<td class="fc-week-number ' + view.calendar.theme.getClass('widgetContent') + '" ' +
18428                    view.weekNumberStyleAttr() + '></td>';
18429            }
18430            return '';
18431        };
18432        // Generates the HTML that goes before every other type of row generated by DayGrid.
18433        // Affects helper-skeleton and highlight-skeleton rows.
18434        SubClass.prototype.renderIntroHtml = function () {
18435            var view = this.view;
18436            if (this.colWeekNumbersVisible) {
18437                return '<td class="fc-week-number" ' + view.weekNumberStyleAttr() + '></td>';
18438            }
18439            return '';
18440        };
18441        SubClass.prototype.getIsNumbersVisible = function () {
18442            return DayGrid_1.default.prototype.getIsNumbersVisible.apply(this, arguments) || this.colWeekNumbersVisible;
18443        };
18444        return SubClass;
18445    }(SuperClass));
18446}
18447
18448
18449/***/ }),
18450/* 68 */
18451/***/ (function(module, exports, __webpack_require__) {
18452
18453Object.defineProperty(exports, "__esModule", { value: true });
18454var tslib_1 = __webpack_require__(2);
18455var UnzonedRange_1 = __webpack_require__(5);
18456var DateProfileGenerator_1 = __webpack_require__(55);
18457var BasicViewDateProfileGenerator = /** @class */ (function (_super) {
18458    tslib_1.__extends(BasicViewDateProfileGenerator, _super);
18459    function BasicViewDateProfileGenerator() {
18460        return _super !== null && _super.apply(this, arguments) || this;
18461    }
18462    // Computes the date range that will be rendered.
18463    BasicViewDateProfileGenerator.prototype.buildRenderRange = function (currentUnzonedRange, currentRangeUnit, isRangeAllDay) {
18464        var renderUnzonedRange = _super.prototype.buildRenderRange.call(this, currentUnzonedRange, currentRangeUnit, isRangeAllDay); // an UnzonedRange
18465        var start = this.msToUtcMoment(renderUnzonedRange.startMs, isRangeAllDay);
18466        var end = this.msToUtcMoment(renderUnzonedRange.endMs, isRangeAllDay);
18467        // year and month views should be aligned with weeks. this is already done for week
18468        if (/^(year|month)$/.test(currentRangeUnit)) {
18469            start.startOf('week');
18470            // make end-of-week if not already
18471            if (end.weekday()) {
18472                end.add(1, 'week').startOf('week'); // exclusively move backwards
18473            }
18474        }
18475        return new UnzonedRange_1.default(start, end);
18476    };
18477    return BasicViewDateProfileGenerator;
18478}(DateProfileGenerator_1.default));
18479exports.default = BasicViewDateProfileGenerator;
18480
18481
18482/***/ }),
18483/* 69 */,
18484/* 70 */,
18485/* 71 */,
18486/* 72 */,
18487/* 73 */,
18488/* 74 */,
18489/* 75 */,
18490/* 76 */,
18491/* 77 */,
18492/* 78 */,
18493/* 79 */,
18494/* 80 */,
18495/* 81 */,
18496/* 82 */,
18497/* 83 */,
18498/* 84 */,
18499/* 85 */,
18500/* 86 */,
18501/* 87 */,
18502/* 88 */,
18503/* 89 */,
18504/* 90 */,
18505/* 91 */,
18506/* 92 */,
18507/* 93 */,
18508/* 94 */,
18509/* 95 */,
18510/* 96 */,
18511/* 97 */,
18512/* 98 */,
18513/* 99 */,
18514/* 100 */,
18515/* 101 */,
18516/* 102 */,
18517/* 103 */,
18518/* 104 */,
18519/* 105 */,
18520/* 106 */,
18521/* 107 */,
18522/* 108 */,
18523/* 109 */,
18524/* 110 */,
18525/* 111 */,
18526/* 112 */,
18527/* 113 */,
18528/* 114 */,
18529/* 115 */,
18530/* 116 */,
18531/* 117 */,
18532/* 118 */,
18533/* 119 */,
18534/* 120 */,
18535/* 121 */,
18536/* 122 */,
18537/* 123 */,
18538/* 124 */,
18539/* 125 */,
18540/* 126 */,
18541/* 127 */,
18542/* 128 */,
18543/* 129 */,
18544/* 130 */,
18545/* 131 */,
18546/* 132 */,
18547/* 133 */,
18548/* 134 */,
18549/* 135 */,
18550/* 136 */,
18551/* 137 */,
18552/* 138 */,
18553/* 139 */,
18554/* 140 */,
18555/* 141 */,
18556/* 142 */,
18557/* 143 */,
18558/* 144 */,
18559/* 145 */,
18560/* 146 */,
18561/* 147 */,
18562/* 148 */,
18563/* 149 */,
18564/* 150 */,
18565/* 151 */,
18566/* 152 */,
18567/* 153 */,
18568/* 154 */,
18569/* 155 */,
18570/* 156 */,
18571/* 157 */,
18572/* 158 */,
18573/* 159 */,
18574/* 160 */,
18575/* 161 */,
18576/* 162 */,
18577/* 163 */,
18578/* 164 */,
18579/* 165 */,
18580/* 166 */,
18581/* 167 */,
18582/* 168 */,
18583/* 169 */,
18584/* 170 */,
18585/* 171 */,
18586/* 172 */,
18587/* 173 */,
18588/* 174 */,
18589/* 175 */,
18590/* 176 */,
18591/* 177 */,
18592/* 178 */,
18593/* 179 */,
18594/* 180 */,
18595/* 181 */,
18596/* 182 */,
18597/* 183 */,
18598/* 184 */,
18599/* 185 */,
18600/* 186 */,
18601/* 187 */,
18602/* 188 */,
18603/* 189 */,
18604/* 190 */,
18605/* 191 */,
18606/* 192 */,
18607/* 193 */,
18608/* 194 */,
18609/* 195 */,
18610/* 196 */,
18611/* 197 */,
18612/* 198 */,
18613/* 199 */,
18614/* 200 */,
18615/* 201 */,
18616/* 202 */,
18617/* 203 */,
18618/* 204 */,
18619/* 205 */,
18620/* 206 */,
18621/* 207 */,
18622/* 208 */,
18623/* 209 */,
18624/* 210 */,
18625/* 211 */,
18626/* 212 */,
18627/* 213 */,
18628/* 214 */,
18629/* 215 */,
18630/* 216 */,
18631/* 217 */
18632/***/ (function(module, exports, __webpack_require__) {
18633
18634Object.defineProperty(exports, "__esModule", { value: true });
18635var UnzonedRange_1 = __webpack_require__(5);
18636var ComponentFootprint_1 = __webpack_require__(12);
18637var EventDefParser_1 = __webpack_require__(36);
18638var EventSource_1 = __webpack_require__(6);
18639var util_1 = __webpack_require__(19);
18640var Constraints = /** @class */ (function () {
18641    function Constraints(eventManager, _calendar) {
18642        this.eventManager = eventManager;
18643        this._calendar = _calendar;
18644    }
18645    Constraints.prototype.opt = function (name) {
18646        return this._calendar.opt(name);
18647    };
18648    /*
18649    determines if eventInstanceGroup is allowed,
18650    in relation to other EVENTS and business hours.
18651    */
18652    Constraints.prototype.isEventInstanceGroupAllowed = function (eventInstanceGroup) {
18653        var eventDef = eventInstanceGroup.getEventDef();
18654        var eventFootprints = this.eventRangesToEventFootprints(eventInstanceGroup.getAllEventRanges());
18655        var i;
18656        var peerEventInstances = this.getPeerEventInstances(eventDef);
18657        var peerEventRanges = peerEventInstances.map(util_1.eventInstanceToEventRange);
18658        var peerEventFootprints = this.eventRangesToEventFootprints(peerEventRanges);
18659        var constraintVal = eventDef.getConstraint();
18660        var overlapVal = eventDef.getOverlap();
18661        var eventAllowFunc = this.opt('eventAllow');
18662        for (i = 0; i < eventFootprints.length; i++) {
18663            if (!this.isFootprintAllowed(eventFootprints[i].componentFootprint, peerEventFootprints, constraintVal, overlapVal, eventFootprints[i].eventInstance)) {
18664                return false;
18665            }
18666        }
18667        if (eventAllowFunc) {
18668            for (i = 0; i < eventFootprints.length; i++) {
18669                if (eventAllowFunc(eventFootprints[i].componentFootprint.toLegacy(this._calendar), eventFootprints[i].getEventLegacy()) === false) {
18670                    return false;
18671                }
18672            }
18673        }
18674        return true;
18675    };
18676    Constraints.prototype.getPeerEventInstances = function (eventDef) {
18677        return this.eventManager.getEventInstancesWithoutId(eventDef.id);
18678    };
18679    Constraints.prototype.isSelectionFootprintAllowed = function (componentFootprint) {
18680        var peerEventInstances = this.eventManager.getEventInstances();
18681        var peerEventRanges = peerEventInstances.map(util_1.eventInstanceToEventRange);
18682        var peerEventFootprints = this.eventRangesToEventFootprints(peerEventRanges);
18683        var selectAllowFunc;
18684        if (this.isFootprintAllowed(componentFootprint, peerEventFootprints, this.opt('selectConstraint'), this.opt('selectOverlap'))) {
18685            selectAllowFunc = this.opt('selectAllow');
18686            if (selectAllowFunc) {
18687                return selectAllowFunc(componentFootprint.toLegacy(this._calendar)) !== false;
18688            }
18689            else {
18690                return true;
18691            }
18692        }
18693        return false;
18694    };
18695    Constraints.prototype.isFootprintAllowed = function (componentFootprint, peerEventFootprints, constraintVal, overlapVal, subjectEventInstance // optional
18696    ) {
18697        var constraintFootprints; // ComponentFootprint[]
18698        var overlapEventFootprints; // EventFootprint[]
18699        if (constraintVal != null) {
18700            constraintFootprints = this.constraintValToFootprints(constraintVal, componentFootprint.isAllDay);
18701            if (!this.isFootprintWithinConstraints(componentFootprint, constraintFootprints)) {
18702                return false;
18703            }
18704        }
18705        overlapEventFootprints = this.collectOverlapEventFootprints(peerEventFootprints, componentFootprint);
18706        if (overlapVal === false) {
18707            if (overlapEventFootprints.length) {
18708                return false;
18709            }
18710        }
18711        else if (typeof overlapVal === 'function') {
18712            if (!isOverlapsAllowedByFunc(overlapEventFootprints, overlapVal, subjectEventInstance)) {
18713                return false;
18714            }
18715        }
18716        if (subjectEventInstance) {
18717            if (!isOverlapEventInstancesAllowed(overlapEventFootprints, subjectEventInstance)) {
18718                return false;
18719            }
18720        }
18721        return true;
18722    };
18723    // Constraint
18724    // ------------------------------------------------------------------------------------------------
18725    Constraints.prototype.isFootprintWithinConstraints = function (componentFootprint, constraintFootprints) {
18726        var i;
18727        for (i = 0; i < constraintFootprints.length; i++) {
18728            if (this.footprintContainsFootprint(constraintFootprints[i], componentFootprint)) {
18729                return true;
18730            }
18731        }
18732        return false;
18733    };
18734    Constraints.prototype.constraintValToFootprints = function (constraintVal, isAllDay) {
18735        var eventInstances;
18736        if (constraintVal === 'businessHours') {
18737            return this.buildCurrentBusinessFootprints(isAllDay);
18738        }
18739        else if (typeof constraintVal === 'object') {
18740            eventInstances = this.parseEventDefToInstances(constraintVal); // handles recurring events
18741            if (!eventInstances) { // invalid input. fallback to parsing footprint directly
18742                return this.parseFootprints(constraintVal);
18743            }
18744            else {
18745                return this.eventInstancesToFootprints(eventInstances);
18746            }
18747        }
18748        else if (constraintVal != null) { // an ID
18749            eventInstances = this.eventManager.getEventInstancesWithId(constraintVal);
18750            return this.eventInstancesToFootprints(eventInstances);
18751        }
18752    };
18753    // returns ComponentFootprint[]
18754    // uses current view's range
18755    Constraints.prototype.buildCurrentBusinessFootprints = function (isAllDay) {
18756        var view = this._calendar.view;
18757        var businessHourGenerator = view.get('businessHourGenerator');
18758        var unzonedRange = view.dateProfile.activeUnzonedRange;
18759        var eventInstanceGroup = businessHourGenerator.buildEventInstanceGroup(isAllDay, unzonedRange);
18760        if (eventInstanceGroup) {
18761            return this.eventInstancesToFootprints(eventInstanceGroup.eventInstances);
18762        }
18763        else {
18764            return [];
18765        }
18766    };
18767    // conversion util
18768    Constraints.prototype.eventInstancesToFootprints = function (eventInstances) {
18769        var eventRanges = eventInstances.map(util_1.eventInstanceToEventRange);
18770        var eventFootprints = this.eventRangesToEventFootprints(eventRanges);
18771        return eventFootprints.map(util_1.eventFootprintToComponentFootprint);
18772    };
18773    // Overlap
18774    // ------------------------------------------------------------------------------------------------
18775    Constraints.prototype.collectOverlapEventFootprints = function (peerEventFootprints, targetFootprint) {
18776        var overlapEventFootprints = [];
18777        var i;
18778        for (i = 0; i < peerEventFootprints.length; i++) {
18779            if (this.footprintsIntersect(targetFootprint, peerEventFootprints[i].componentFootprint)) {
18780                overlapEventFootprints.push(peerEventFootprints[i]);
18781            }
18782        }
18783        return overlapEventFootprints;
18784    };
18785    // Conversion: eventDefs -> eventInstances -> eventRanges -> eventFootprints -> componentFootprints
18786    // ------------------------------------------------------------------------------------------------
18787    // NOTE: this might seem like repetitive code with the Grid class, however, this code is related to
18788    // constraints whereas the Grid code is related to rendering. Each approach might want to convert
18789    // eventRanges -> eventFootprints in a different way. Regardless, there are opportunities to make
18790    // this more DRY.
18791    /*
18792    Returns false on invalid input.
18793    */
18794    Constraints.prototype.parseEventDefToInstances = function (eventInput) {
18795        var eventManager = this.eventManager;
18796        var eventDef = EventDefParser_1.default.parse(eventInput, new EventSource_1.default(this._calendar));
18797        if (!eventDef) { // invalid
18798            return false;
18799        }
18800        return eventDef.buildInstances(eventManager.currentPeriod.unzonedRange);
18801    };
18802    Constraints.prototype.eventRangesToEventFootprints = function (eventRanges) {
18803        var i;
18804        var eventFootprints = [];
18805        for (i = 0; i < eventRanges.length; i++) {
18806            eventFootprints.push.apply(// footprints
18807            eventFootprints, this.eventRangeToEventFootprints(eventRanges[i]));
18808        }
18809        return eventFootprints;
18810    };
18811    Constraints.prototype.eventRangeToEventFootprints = function (eventRange) {
18812        return [util_1.eventRangeToEventFootprint(eventRange)];
18813    };
18814    /*
18815    Parses footprints directly.
18816    Very similar to EventDateProfile::parse :(
18817    */
18818    Constraints.prototype.parseFootprints = function (rawInput) {
18819        var start;
18820        var end;
18821        if (rawInput.start) {
18822            start = this._calendar.moment(rawInput.start);
18823            if (!start.isValid()) {
18824                start = null;
18825            }
18826        }
18827        if (rawInput.end) {
18828            end = this._calendar.moment(rawInput.end);
18829            if (!end.isValid()) {
18830                end = null;
18831            }
18832        }
18833        return [
18834            new ComponentFootprint_1.default(new UnzonedRange_1.default(start, end), (start && !start.hasTime()) || (end && !end.hasTime()) // isAllDay
18835            )
18836        ];
18837    };
18838    // Footprint Utils
18839    // ----------------------------------------------------------------------------------------
18840    Constraints.prototype.footprintContainsFootprint = function (outerFootprint, innerFootprint) {
18841        return outerFootprint.unzonedRange.containsRange(innerFootprint.unzonedRange);
18842    };
18843    Constraints.prototype.footprintsIntersect = function (footprint0, footprint1) {
18844        return footprint0.unzonedRange.intersectsWith(footprint1.unzonedRange);
18845    };
18846    return Constraints;
18847}());
18848exports.default = Constraints;
18849// optional subjectEventInstance
18850function isOverlapsAllowedByFunc(overlapEventFootprints, overlapFunc, subjectEventInstance) {
18851    var i;
18852    for (i = 0; i < overlapEventFootprints.length; i++) {
18853        if (!overlapFunc(overlapEventFootprints[i].eventInstance.toLegacy(), subjectEventInstance ? subjectEventInstance.toLegacy() : null)) {
18854            return false;
18855        }
18856    }
18857    return true;
18858}
18859function isOverlapEventInstancesAllowed(overlapEventFootprints, subjectEventInstance) {
18860    var subjectLegacyInstance = subjectEventInstance.toLegacy();
18861    var i;
18862    var overlapEventInstance;
18863    var overlapEventDef;
18864    var overlapVal;
18865    for (i = 0; i < overlapEventFootprints.length; i++) {
18866        overlapEventInstance = overlapEventFootprints[i].eventInstance;
18867        overlapEventDef = overlapEventInstance.def;
18868        // don't need to pass in calendar, because don't want to consider global eventOverlap property,
18869        // because we already considered that earlier in the process.
18870        overlapVal = overlapEventDef.getOverlap();
18871        if (overlapVal === false) {
18872            return false;
18873        }
18874        else if (typeof overlapVal === 'function') {
18875            if (!overlapVal(overlapEventInstance.toLegacy(), subjectLegacyInstance)) {
18876                return false;
18877            }
18878        }
18879    }
18880    return true;
18881}
18882
18883
18884/***/ }),
18885/* 218 */
18886/***/ (function(module, exports, __webpack_require__) {
18887
18888Object.defineProperty(exports, "__esModule", { value: true });
18889var $ = __webpack_require__(3);
18890var util_1 = __webpack_require__(19);
18891var EventInstanceGroup_1 = __webpack_require__(20);
18892var RecurringEventDef_1 = __webpack_require__(54);
18893var EventSource_1 = __webpack_require__(6);
18894var BUSINESS_HOUR_EVENT_DEFAULTS = {
18895    start: '09:00',
18896    end: '17:00',
18897    dow: [1, 2, 3, 4, 5],
18898    rendering: 'inverse-background'
18899    // classNames are defined in businessHoursSegClasses
18900};
18901var BusinessHourGenerator = /** @class */ (function () {
18902    function BusinessHourGenerator(rawComplexDef, calendar) {
18903        this.rawComplexDef = rawComplexDef;
18904        this.calendar = calendar;
18905    }
18906    BusinessHourGenerator.prototype.buildEventInstanceGroup = function (isAllDay, unzonedRange) {
18907        var eventDefs = this.buildEventDefs(isAllDay);
18908        var eventInstanceGroup;
18909        if (eventDefs.length) {
18910            eventInstanceGroup = new EventInstanceGroup_1.default(util_1.eventDefsToEventInstances(eventDefs, unzonedRange));
18911            // so that inverse-background rendering can happen even when no eventRanges in view
18912            eventInstanceGroup.explicitEventDef = eventDefs[0];
18913            return eventInstanceGroup;
18914        }
18915    };
18916    BusinessHourGenerator.prototype.buildEventDefs = function (isAllDay) {
18917        var rawComplexDef = this.rawComplexDef;
18918        var rawDefs = [];
18919        var requireDow = false;
18920        var i;
18921        var defs = [];
18922        if (rawComplexDef === true) {
18923            rawDefs = [{}]; // will get BUSINESS_HOUR_EVENT_DEFAULTS verbatim
18924        }
18925        else if ($.isPlainObject(rawComplexDef)) {
18926            rawDefs = [rawComplexDef];
18927        }
18928        else if ($.isArray(rawComplexDef)) {
18929            rawDefs = rawComplexDef;
18930            requireDow = true; // every sub-definition NEEDS a day-of-week
18931        }
18932        for (i = 0; i < rawDefs.length; i++) {
18933            if (!requireDow || rawDefs[i].dow) {
18934                defs.push(this.buildEventDef(isAllDay, rawDefs[i]));
18935            }
18936        }
18937        return defs;
18938    };
18939    BusinessHourGenerator.prototype.buildEventDef = function (isAllDay, rawDef) {
18940        var fullRawDef = $.extend({}, BUSINESS_HOUR_EVENT_DEFAULTS, rawDef);
18941        if (isAllDay) {
18942            fullRawDef.start = null;
18943            fullRawDef.end = null;
18944        }
18945        return RecurringEventDef_1.default.parse(fullRawDef, new EventSource_1.default(this.calendar) // dummy source
18946        );
18947    };
18948    return BusinessHourGenerator;
18949}());
18950exports.default = BusinessHourGenerator;
18951
18952
18953/***/ }),
18954/* 219 */
18955/***/ (function(module, exports, __webpack_require__) {
18956
18957Object.defineProperty(exports, "__esModule", { value: true });
18958var $ = __webpack_require__(3);
18959var util_1 = __webpack_require__(4);
18960var Promise_1 = __webpack_require__(21);
18961var EmitterMixin_1 = __webpack_require__(13);
18962var UnzonedRange_1 = __webpack_require__(5);
18963var EventInstanceGroup_1 = __webpack_require__(20);
18964var EventPeriod = /** @class */ (function () {
18965    function EventPeriod(start, end, timezone) {
18966        this.pendingCnt = 0;
18967        this.freezeDepth = 0;
18968        this.stuntedReleaseCnt = 0;
18969        this.releaseCnt = 0;
18970        this.start = start;
18971        this.end = end;
18972        this.timezone = timezone;
18973        this.unzonedRange = new UnzonedRange_1.default(start.clone().stripZone(), end.clone().stripZone());
18974        this.requestsByUid = {};
18975        this.eventDefsByUid = {};
18976        this.eventDefsById = {};
18977        this.eventInstanceGroupsById = {};
18978    }
18979    EventPeriod.prototype.isWithinRange = function (start, end) {
18980        // TODO: use a range util function?
18981        return !start.isBefore(this.start) && !end.isAfter(this.end);
18982    };
18983    // Requesting and Purging
18984    // -----------------------------------------------------------------------------------------------------------------
18985    EventPeriod.prototype.requestSources = function (sources) {
18986        this.freeze();
18987        for (var i = 0; i < sources.length; i++) {
18988            this.requestSource(sources[i]);
18989        }
18990        this.thaw();
18991    };
18992    EventPeriod.prototype.requestSource = function (source) {
18993        var _this = this;
18994        var request = { source: source, status: 'pending', eventDefs: null };
18995        this.requestsByUid[source.uid] = request;
18996        this.pendingCnt += 1;
18997        source.fetch(this.start, this.end, this.timezone).then(function (eventDefs) {
18998            if (request.status !== 'cancelled') {
18999                request.status = 'completed';
19000                request.eventDefs = eventDefs;
19001                _this.addEventDefs(eventDefs);
19002                _this.pendingCnt--;
19003                _this.tryRelease();
19004            }
19005        }, function () {
19006            if (request.status !== 'cancelled') {
19007                request.status = 'failed';
19008                _this.pendingCnt--;
19009                _this.tryRelease();
19010            }
19011        });
19012    };
19013    EventPeriod.prototype.purgeSource = function (source) {
19014        var request = this.requestsByUid[source.uid];
19015        if (request) {
19016            delete this.requestsByUid[source.uid];
19017            if (request.status === 'pending') {
19018                request.status = 'cancelled';
19019                this.pendingCnt--;
19020                this.tryRelease();
19021            }
19022            else if (request.status === 'completed') {
19023                request.eventDefs.forEach(this.removeEventDef.bind(this));
19024            }
19025        }
19026    };
19027    EventPeriod.prototype.purgeAllSources = function () {
19028        var requestsByUid = this.requestsByUid;
19029        var uid;
19030        var request;
19031        var completedCnt = 0;
19032        for (uid in requestsByUid) {
19033            request = requestsByUid[uid];
19034            if (request.status === 'pending') {
19035                request.status = 'cancelled';
19036            }
19037            else if (request.status === 'completed') {
19038                completedCnt++;
19039            }
19040        }
19041        this.requestsByUid = {};
19042        this.pendingCnt = 0;
19043        if (completedCnt) {
19044            this.removeAllEventDefs(); // might release
19045        }
19046    };
19047    // Event Definitions
19048    // -----------------------------------------------------------------------------------------------------------------
19049    EventPeriod.prototype.getEventDefByUid = function (eventDefUid) {
19050        return this.eventDefsByUid[eventDefUid];
19051    };
19052    EventPeriod.prototype.getEventDefsById = function (eventDefId) {
19053        var a = this.eventDefsById[eventDefId];
19054        if (a) {
19055            return a.slice(); // clone
19056        }
19057        return [];
19058    };
19059    EventPeriod.prototype.addEventDefs = function (eventDefs) {
19060        for (var i = 0; i < eventDefs.length; i++) {
19061            this.addEventDef(eventDefs[i]);
19062        }
19063    };
19064    EventPeriod.prototype.addEventDef = function (eventDef) {
19065        var eventDefsById = this.eventDefsById;
19066        var eventDefId = eventDef.id;
19067        var eventDefs = eventDefsById[eventDefId] || (eventDefsById[eventDefId] = []);
19068        var eventInstances = eventDef.buildInstances(this.unzonedRange);
19069        var i;
19070        eventDefs.push(eventDef);
19071        this.eventDefsByUid[eventDef.uid] = eventDef;
19072        for (i = 0; i < eventInstances.length; i++) {
19073            this.addEventInstance(eventInstances[i], eventDefId);
19074        }
19075    };
19076    EventPeriod.prototype.removeEventDefsById = function (eventDefId) {
19077        var _this = this;
19078        this.getEventDefsById(eventDefId).forEach(function (eventDef) {
19079            _this.removeEventDef(eventDef);
19080        });
19081    };
19082    EventPeriod.prototype.removeAllEventDefs = function () {
19083        var isEmpty = $.isEmptyObject(this.eventDefsByUid);
19084        this.eventDefsByUid = {};
19085        this.eventDefsById = {};
19086        this.eventInstanceGroupsById = {};
19087        if (!isEmpty) {
19088            this.tryRelease();
19089        }
19090    };
19091    EventPeriod.prototype.removeEventDef = function (eventDef) {
19092        var eventDefsById = this.eventDefsById;
19093        var eventDefs = eventDefsById[eventDef.id];
19094        delete this.eventDefsByUid[eventDef.uid];
19095        if (eventDefs) {
19096            util_1.removeExact(eventDefs, eventDef);
19097            if (!eventDefs.length) {
19098                delete eventDefsById[eventDef.id];
19099            }
19100            this.removeEventInstancesForDef(eventDef);
19101        }
19102    };
19103    // Event Instances
19104    // -----------------------------------------------------------------------------------------------------------------
19105    EventPeriod.prototype.getEventInstances = function () {
19106        var eventInstanceGroupsById = this.eventInstanceGroupsById;
19107        var eventInstances = [];
19108        var id;
19109        for (id in eventInstanceGroupsById) {
19110            eventInstances.push.apply(eventInstances, // append
19111            eventInstanceGroupsById[id].eventInstances);
19112        }
19113        return eventInstances;
19114    };
19115    EventPeriod.prototype.getEventInstancesWithId = function (eventDefId) {
19116        var eventInstanceGroup = this.eventInstanceGroupsById[eventDefId];
19117        if (eventInstanceGroup) {
19118            return eventInstanceGroup.eventInstances.slice(); // clone
19119        }
19120        return [];
19121    };
19122    EventPeriod.prototype.getEventInstancesWithoutId = function (eventDefId) {
19123        var eventInstanceGroupsById = this.eventInstanceGroupsById;
19124        var matchingInstances = [];
19125        var id;
19126        for (id in eventInstanceGroupsById) {
19127            if (id !== eventDefId) {
19128                matchingInstances.push.apply(matchingInstances, // append
19129                eventInstanceGroupsById[id].eventInstances);
19130            }
19131        }
19132        return matchingInstances;
19133    };
19134    EventPeriod.prototype.addEventInstance = function (eventInstance, eventDefId) {
19135        var eventInstanceGroupsById = this.eventInstanceGroupsById;
19136        var eventInstanceGroup = eventInstanceGroupsById[eventDefId] ||
19137            (eventInstanceGroupsById[eventDefId] = new EventInstanceGroup_1.default());
19138        eventInstanceGroup.eventInstances.push(eventInstance);
19139        this.tryRelease();
19140    };
19141    EventPeriod.prototype.removeEventInstancesForDef = function (eventDef) {
19142        var eventInstanceGroupsById = this.eventInstanceGroupsById;
19143        var eventInstanceGroup = eventInstanceGroupsById[eventDef.id];
19144        var removeCnt;
19145        if (eventInstanceGroup) {
19146            removeCnt = util_1.removeMatching(eventInstanceGroup.eventInstances, function (currentEventInstance) {
19147                return currentEventInstance.def === eventDef;
19148            });
19149            if (!eventInstanceGroup.eventInstances.length) {
19150                delete eventInstanceGroupsById[eventDef.id];
19151            }
19152            if (removeCnt) {
19153                this.tryRelease();
19154            }
19155        }
19156    };
19157    // Releasing and Freezing
19158    // -----------------------------------------------------------------------------------------------------------------
19159    EventPeriod.prototype.tryRelease = function () {
19160        if (!this.pendingCnt) {
19161            if (!this.freezeDepth) {
19162                this.release();
19163            }
19164            else {
19165                this.stuntedReleaseCnt++;
19166            }
19167        }
19168    };
19169    EventPeriod.prototype.release = function () {
19170        this.releaseCnt++;
19171        this.trigger('release', this.eventInstanceGroupsById);
19172    };
19173    EventPeriod.prototype.whenReleased = function () {
19174        var _this = this;
19175        if (this.releaseCnt) {
19176            return Promise_1.default.resolve(this.eventInstanceGroupsById);
19177        }
19178        else {
19179            return Promise_1.default.construct(function (onResolve) {
19180                _this.one('release', onResolve);
19181            });
19182        }
19183    };
19184    EventPeriod.prototype.freeze = function () {
19185        if (!(this.freezeDepth++)) {
19186            this.stuntedReleaseCnt = 0;
19187        }
19188    };
19189    EventPeriod.prototype.thaw = function () {
19190        if (!(--this.freezeDepth) && this.stuntedReleaseCnt && !this.pendingCnt) {
19191            this.release();
19192        }
19193    };
19194    return EventPeriod;
19195}());
19196exports.default = EventPeriod;
19197EmitterMixin_1.default.mixInto(EventPeriod);
19198
19199
19200/***/ }),
19201/* 220 */
19202/***/ (function(module, exports, __webpack_require__) {
19203
19204Object.defineProperty(exports, "__esModule", { value: true });
19205var $ = __webpack_require__(3);
19206var util_1 = __webpack_require__(4);
19207var EventPeriod_1 = __webpack_require__(219);
19208var ArrayEventSource_1 = __webpack_require__(56);
19209var EventSource_1 = __webpack_require__(6);
19210var EventSourceParser_1 = __webpack_require__(38);
19211var SingleEventDef_1 = __webpack_require__(9);
19212var EventInstanceGroup_1 = __webpack_require__(20);
19213var EmitterMixin_1 = __webpack_require__(13);
19214var ListenerMixin_1 = __webpack_require__(7);
19215var EventManager = /** @class */ (function () {
19216    function EventManager(calendar) {
19217        this.calendar = calendar;
19218        this.stickySource = new ArrayEventSource_1.default(calendar);
19219        this.otherSources = [];
19220    }
19221    EventManager.prototype.requestEvents = function (start, end, timezone, force) {
19222        if (force ||
19223            !this.currentPeriod ||
19224            !this.currentPeriod.isWithinRange(start, end) ||
19225            timezone !== this.currentPeriod.timezone) {
19226            this.setPeriod(// will change this.currentPeriod
19227            new EventPeriod_1.default(start, end, timezone));
19228        }
19229        return this.currentPeriod.whenReleased();
19230    };
19231    // Source Adding/Removing
19232    // -----------------------------------------------------------------------------------------------------------------
19233    EventManager.prototype.addSource = function (eventSource) {
19234        this.otherSources.push(eventSource);
19235        if (this.currentPeriod) {
19236            this.currentPeriod.requestSource(eventSource); // might release
19237        }
19238    };
19239    EventManager.prototype.removeSource = function (doomedSource) {
19240        util_1.removeExact(this.otherSources, doomedSource);
19241        if (this.currentPeriod) {
19242            this.currentPeriod.purgeSource(doomedSource); // might release
19243        }
19244    };
19245    EventManager.prototype.removeAllSources = function () {
19246        this.otherSources = [];
19247        if (this.currentPeriod) {
19248            this.currentPeriod.purgeAllSources(); // might release
19249        }
19250    };
19251    // Source Refetching
19252    // -----------------------------------------------------------------------------------------------------------------
19253    EventManager.prototype.refetchSource = function (eventSource) {
19254        var currentPeriod = this.currentPeriod;
19255        if (currentPeriod) {
19256            currentPeriod.freeze();
19257            currentPeriod.purgeSource(eventSource);
19258            currentPeriod.requestSource(eventSource);
19259            currentPeriod.thaw();
19260        }
19261    };
19262    EventManager.prototype.refetchAllSources = function () {
19263        var currentPeriod = this.currentPeriod;
19264        if (currentPeriod) {
19265            currentPeriod.freeze();
19266            currentPeriod.purgeAllSources();
19267            currentPeriod.requestSources(this.getSources());
19268            currentPeriod.thaw();
19269        }
19270    };
19271    // Source Querying
19272    // -----------------------------------------------------------------------------------------------------------------
19273    EventManager.prototype.getSources = function () {
19274        return [this.stickySource].concat(this.otherSources);
19275    };
19276    // like querySources, but accepts multple match criteria (like multiple IDs)
19277    EventManager.prototype.multiQuerySources = function (matchInputs) {
19278        // coerce into an array
19279        if (!matchInputs) {
19280            matchInputs = [];
19281        }
19282        else if (!$.isArray(matchInputs)) {
19283            matchInputs = [matchInputs];
19284        }
19285        var matchingSources = [];
19286        var i;
19287        // resolve raw inputs to real event source objects
19288        for (i = 0; i < matchInputs.length; i++) {
19289            matchingSources.push.apply(// append
19290            matchingSources, this.querySources(matchInputs[i]));
19291        }
19292        return matchingSources;
19293    };
19294    // matchInput can either by a real event source object, an ID, or the function/URL for the source.
19295    // returns an array of matching source objects.
19296    EventManager.prototype.querySources = function (matchInput) {
19297        var sources = this.otherSources;
19298        var i;
19299        var source;
19300        // given a proper event source object
19301        for (i = 0; i < sources.length; i++) {
19302            source = sources[i];
19303            if (source === matchInput) {
19304                return [source];
19305            }
19306        }
19307        // an ID match
19308        source = this.getSourceById(EventSource_1.default.normalizeId(matchInput));
19309        if (source) {
19310            return [source];
19311        }
19312        // parse as an event source
19313        matchInput = EventSourceParser_1.default.parse(matchInput, this.calendar);
19314        if (matchInput) {
19315            return $.grep(sources, function (source) {
19316                return isSourcesEquivalent(matchInput, source);
19317            });
19318        }
19319    };
19320    /*
19321    ID assumed to already be normalized
19322    */
19323    EventManager.prototype.getSourceById = function (id) {
19324        return $.grep(this.otherSources, function (source) {
19325            return source.id && source.id === id;
19326        })[0];
19327    };
19328    // Event-Period
19329    // -----------------------------------------------------------------------------------------------------------------
19330    EventManager.prototype.setPeriod = function (eventPeriod) {
19331        if (this.currentPeriod) {
19332            this.unbindPeriod(this.currentPeriod);
19333            this.currentPeriod = null;
19334        }
19335        this.currentPeriod = eventPeriod;
19336        this.bindPeriod(eventPeriod);
19337        eventPeriod.requestSources(this.getSources());
19338    };
19339    EventManager.prototype.bindPeriod = function (eventPeriod) {
19340        this.listenTo(eventPeriod, 'release', function (eventsPayload) {
19341            this.trigger('release', eventsPayload);
19342        });
19343    };
19344    EventManager.prototype.unbindPeriod = function (eventPeriod) {
19345        this.stopListeningTo(eventPeriod);
19346    };
19347    // Event Getting/Adding/Removing
19348    // -----------------------------------------------------------------------------------------------------------------
19349    EventManager.prototype.getEventDefByUid = function (uid) {
19350        if (this.currentPeriod) {
19351            return this.currentPeriod.getEventDefByUid(uid);
19352        }
19353    };
19354    EventManager.prototype.addEventDef = function (eventDef, isSticky) {
19355        if (isSticky) {
19356            this.stickySource.addEventDef(eventDef);
19357        }
19358        if (this.currentPeriod) {
19359            this.currentPeriod.addEventDef(eventDef); // might release
19360        }
19361    };
19362    EventManager.prototype.removeEventDefsById = function (eventId) {
19363        this.getSources().forEach(function (eventSource) {
19364            eventSource.removeEventDefsById(eventId);
19365        });
19366        if (this.currentPeriod) {
19367            this.currentPeriod.removeEventDefsById(eventId); // might release
19368        }
19369    };
19370    EventManager.prototype.removeAllEventDefs = function () {
19371        this.getSources().forEach(function (eventSource) {
19372            eventSource.removeAllEventDefs();
19373        });
19374        if (this.currentPeriod) {
19375            this.currentPeriod.removeAllEventDefs();
19376        }
19377    };
19378    // Event Mutating
19379    // -----------------------------------------------------------------------------------------------------------------
19380    /*
19381    Returns an undo function.
19382    */
19383    EventManager.prototype.mutateEventsWithId = function (eventDefId, eventDefMutation) {
19384        var currentPeriod = this.currentPeriod;
19385        var eventDefs;
19386        var undoFuncs = [];
19387        if (currentPeriod) {
19388            currentPeriod.freeze();
19389            eventDefs = currentPeriod.getEventDefsById(eventDefId);
19390            eventDefs.forEach(function (eventDef) {
19391                // add/remove esp because id might change
19392                currentPeriod.removeEventDef(eventDef);
19393                undoFuncs.push(eventDefMutation.mutateSingle(eventDef));
19394                currentPeriod.addEventDef(eventDef);
19395            });
19396            currentPeriod.thaw();
19397            return function () {
19398                currentPeriod.freeze();
19399                for (var i = 0; i < eventDefs.length; i++) {
19400                    currentPeriod.removeEventDef(eventDefs[i]);
19401                    undoFuncs[i]();
19402                    currentPeriod.addEventDef(eventDefs[i]);
19403                }
19404                currentPeriod.thaw();
19405            };
19406        }
19407        return function () { };
19408    };
19409    /*
19410    copies and then mutates
19411    */
19412    EventManager.prototype.buildMutatedEventInstanceGroup = function (eventDefId, eventDefMutation) {
19413        var eventDefs = this.getEventDefsById(eventDefId);
19414        var i;
19415        var defCopy;
19416        var allInstances = [];
19417        for (i = 0; i < eventDefs.length; i++) {
19418            defCopy = eventDefs[i].clone();
19419            if (defCopy instanceof SingleEventDef_1.default) {
19420                eventDefMutation.mutateSingle(defCopy);
19421                allInstances.push.apply(allInstances, // append
19422                defCopy.buildInstances());
19423            }
19424        }
19425        return new EventInstanceGroup_1.default(allInstances);
19426    };
19427    // Freezing
19428    // -----------------------------------------------------------------------------------------------------------------
19429    EventManager.prototype.freeze = function () {
19430        if (this.currentPeriod) {
19431            this.currentPeriod.freeze();
19432        }
19433    };
19434    EventManager.prototype.thaw = function () {
19435        if (this.currentPeriod) {
19436            this.currentPeriod.thaw();
19437        }
19438    };
19439    // methods that simply forward to EventPeriod
19440    EventManager.prototype.getEventDefsById = function (eventDefId) {
19441        return this.currentPeriod.getEventDefsById(eventDefId);
19442    };
19443    EventManager.prototype.getEventInstances = function () {
19444        return this.currentPeriod.getEventInstances();
19445    };
19446    EventManager.prototype.getEventInstancesWithId = function (eventDefId) {
19447        return this.currentPeriod.getEventInstancesWithId(eventDefId);
19448    };
19449    EventManager.prototype.getEventInstancesWithoutId = function (eventDefId) {
19450        return this.currentPeriod.getEventInstancesWithoutId(eventDefId);
19451    };
19452    return EventManager;
19453}());
19454exports.default = EventManager;
19455EmitterMixin_1.default.mixInto(EventManager);
19456ListenerMixin_1.default.mixInto(EventManager);
19457function isSourcesEquivalent(source0, source1) {
19458    return source0.getPrimitive() === source1.getPrimitive();
19459}
19460
19461
19462/***/ }),
19463/* 221 */
19464/***/ (function(module, exports, __webpack_require__) {
19465
19466Object.defineProperty(exports, "__esModule", { value: true });
19467var tslib_1 = __webpack_require__(2);
19468var Theme_1 = __webpack_require__(22);
19469var StandardTheme = /** @class */ (function (_super) {
19470    tslib_1.__extends(StandardTheme, _super);
19471    function StandardTheme() {
19472        return _super !== null && _super.apply(this, arguments) || this;
19473    }
19474    return StandardTheme;
19475}(Theme_1.default));
19476exports.default = StandardTheme;
19477StandardTheme.prototype.classes = {
19478    widget: 'fc-unthemed',
19479    widgetHeader: 'fc-widget-header',
19480    widgetContent: 'fc-widget-content',
19481    buttonGroup: 'fc-button-group',
19482    button: 'fc-button',
19483    cornerLeft: 'fc-corner-left',
19484    cornerRight: 'fc-corner-right',
19485    stateDefault: 'fc-state-default',
19486    stateActive: 'fc-state-active',
19487    stateDisabled: 'fc-state-disabled',
19488    stateHover: 'fc-state-hover',
19489    stateDown: 'fc-state-down',
19490    popoverHeader: 'fc-widget-header',
19491    popoverContent: 'fc-widget-content',
19492    // day grid
19493    headerRow: 'fc-widget-header',
19494    dayRow: 'fc-widget-content',
19495    // list view
19496    listView: 'fc-widget-content'
19497};
19498StandardTheme.prototype.baseIconClass = 'fc-icon';
19499StandardTheme.prototype.iconClasses = {
19500    close: 'fc-icon-x',
19501    prev: 'fc-icon-left-single-arrow',
19502    next: 'fc-icon-right-single-arrow',
19503    prevYear: 'fc-icon-left-double-arrow',
19504    nextYear: 'fc-icon-right-double-arrow'
19505};
19506StandardTheme.prototype.iconOverrideOption = 'buttonIcons';
19507StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon';
19508StandardTheme.prototype.iconOverridePrefix = 'fc-icon-';
19509
19510
19511/***/ }),
19512/* 222 */
19513/***/ (function(module, exports, __webpack_require__) {
19514
19515Object.defineProperty(exports, "__esModule", { value: true });
19516var tslib_1 = __webpack_require__(2);
19517var Theme_1 = __webpack_require__(22);
19518var JqueryUiTheme = /** @class */ (function (_super) {
19519    tslib_1.__extends(JqueryUiTheme, _super);
19520    function JqueryUiTheme() {
19521        return _super !== null && _super.apply(this, arguments) || this;
19522    }
19523    return JqueryUiTheme;
19524}(Theme_1.default));
19525exports.default = JqueryUiTheme;
19526JqueryUiTheme.prototype.classes = {
19527    widget: 'ui-widget',
19528    widgetHeader: 'ui-widget-header',
19529    widgetContent: 'ui-widget-content',
19530    buttonGroup: 'fc-button-group',
19531    button: 'ui-button',
19532    cornerLeft: 'ui-corner-left',
19533    cornerRight: 'ui-corner-right',
19534    stateDefault: 'ui-state-default',
19535    stateActive: 'ui-state-active',
19536    stateDisabled: 'ui-state-disabled',
19537    stateHover: 'ui-state-hover',
19538    stateDown: 'ui-state-down',
19539    today: 'ui-state-highlight',
19540    popoverHeader: 'ui-widget-header',
19541    popoverContent: 'ui-widget-content',
19542    // day grid
19543    headerRow: 'ui-widget-header',
19544    dayRow: 'ui-widget-content',
19545    // list view
19546    listView: 'ui-widget-content'
19547};
19548JqueryUiTheme.prototype.baseIconClass = 'ui-icon';
19549JqueryUiTheme.prototype.iconClasses = {
19550    close: 'ui-icon-closethick',
19551    prev: 'ui-icon-circle-triangle-w',
19552    next: 'ui-icon-circle-triangle-e',
19553    prevYear: 'ui-icon-seek-prev',
19554    nextYear: 'ui-icon-seek-next'
19555};
19556JqueryUiTheme.prototype.iconOverrideOption = 'themeButtonIcons';
19557JqueryUiTheme.prototype.iconOverrideCustomButtonOption = 'themeIcon';
19558JqueryUiTheme.prototype.iconOverridePrefix = 'ui-icon-';
19559
19560
19561/***/ }),
19562/* 223 */
19563/***/ (function(module, exports, __webpack_require__) {
19564
19565Object.defineProperty(exports, "__esModule", { value: true });
19566var tslib_1 = __webpack_require__(2);
19567var $ = __webpack_require__(3);
19568var Promise_1 = __webpack_require__(21);
19569var EventSource_1 = __webpack_require__(6);
19570var FuncEventSource = /** @class */ (function (_super) {
19571    tslib_1.__extends(FuncEventSource, _super);
19572    function FuncEventSource() {
19573        return _super !== null && _super.apply(this, arguments) || this;
19574    }
19575    FuncEventSource.parse = function (rawInput, calendar) {
19576        var rawProps;
19577        // normalize raw input
19578        if ($.isFunction(rawInput.events)) { // extended form
19579            rawProps = rawInput;
19580        }
19581        else if ($.isFunction(rawInput)) { // short form
19582            rawProps = { events: rawInput };
19583        }
19584        if (rawProps) {
19585            return EventSource_1.default.parse.call(this, rawProps, calendar);
19586        }
19587        return false;
19588    };
19589    FuncEventSource.prototype.fetch = function (start, end, timezone) {
19590        var _this = this;
19591        this.calendar.pushLoading();
19592        return Promise_1.default.construct(function (onResolve) {
19593            _this.func.call(_this.calendar, start.clone(), end.clone(), timezone, function (rawEventDefs) {
19594                _this.calendar.popLoading();
19595                onResolve(_this.parseEventDefs(rawEventDefs));
19596            });
19597        });
19598    };
19599    FuncEventSource.prototype.getPrimitive = function () {
19600        return this.func;
19601    };
19602    FuncEventSource.prototype.applyManualStandardProps = function (rawProps) {
19603        var superSuccess = _super.prototype.applyManualStandardProps.call(this, rawProps);
19604        this.func = rawProps.events;
19605        return superSuccess;
19606    };
19607    return FuncEventSource;
19608}(EventSource_1.default));
19609exports.default = FuncEventSource;
19610FuncEventSource.defineStandardProps({
19611    events: false // don't automatically transfer
19612});
19613
19614
19615/***/ }),
19616/* 224 */
19617/***/ (function(module, exports, __webpack_require__) {
19618
19619Object.defineProperty(exports, "__esModule", { value: true });
19620var tslib_1 = __webpack_require__(2);
19621var $ = __webpack_require__(3);
19622var util_1 = __webpack_require__(4);
19623var Promise_1 = __webpack_require__(21);
19624var EventSource_1 = __webpack_require__(6);
19625var JsonFeedEventSource = /** @class */ (function (_super) {
19626    tslib_1.__extends(JsonFeedEventSource, _super);
19627    function JsonFeedEventSource() {
19628        return _super !== null && _super.apply(this, arguments) || this;
19629    }
19630    JsonFeedEventSource.parse = function (rawInput, calendar) {
19631        var rawProps;
19632        // normalize raw input
19633        if (typeof rawInput.url === 'string') { // extended form
19634            rawProps = rawInput;
19635        }
19636        else if (typeof rawInput === 'string') { // short form
19637            rawProps = { url: rawInput };
19638        }
19639        if (rawProps) {
19640            return EventSource_1.default.parse.call(this, rawProps, calendar);
19641        }
19642        return false;
19643    };
19644    JsonFeedEventSource.prototype.fetch = function (start, end, timezone) {
19645        var _this = this;
19646        var ajaxSettings = this.ajaxSettings;
19647        var onSuccess = ajaxSettings.success;
19648        var onError = ajaxSettings.error;
19649        var requestParams = this.buildRequestParams(start, end, timezone);
19650        // todo: eventually handle the promise's then,
19651        // don't intercept success/error
19652        // tho will be a breaking API change
19653        this.calendar.pushLoading();
19654        return Promise_1.default.construct(function (onResolve, onReject) {
19655            $.ajax($.extend({}, // destination
19656            JsonFeedEventSource.AJAX_DEFAULTS, ajaxSettings, {
19657                url: _this.url,
19658                data: requestParams,
19659                success: function (rawEventDefs, status, xhr) {
19660                    var callbackRes;
19661                    _this.calendar.popLoading();
19662                    if (rawEventDefs) {
19663                        callbackRes = util_1.applyAll(onSuccess, _this, [rawEventDefs, status, xhr]); // redirect `this`
19664                        if ($.isArray(callbackRes)) {
19665                            rawEventDefs = callbackRes;
19666                        }
19667                        onResolve(_this.parseEventDefs(rawEventDefs));
19668                    }
19669                    else {
19670                        onReject();
19671                    }
19672                },
19673                error: function (xhr, statusText, errorThrown) {
19674                    _this.calendar.popLoading();
19675                    util_1.applyAll(onError, _this, [xhr, statusText, errorThrown]); // redirect `this`
19676                    onReject();
19677                }
19678            }));
19679        });
19680    };
19681    JsonFeedEventSource.prototype.buildRequestParams = function (start, end, timezone) {
19682        var calendar = this.calendar;
19683        var ajaxSettings = this.ajaxSettings;
19684        var startParam;
19685        var endParam;
19686        var timezoneParam;
19687        var customRequestParams;
19688        var params = {};
19689        startParam = this.startParam;
19690        if (startParam == null) {
19691            startParam = calendar.opt('startParam');
19692        }
19693        endParam = this.endParam;
19694        if (endParam == null) {
19695            endParam = calendar.opt('endParam');
19696        }
19697        timezoneParam = this.timezoneParam;
19698        if (timezoneParam == null) {
19699            timezoneParam = calendar.opt('timezoneParam');
19700        }
19701        // retrieve any outbound GET/POST $.ajax data from the options
19702        if ($.isFunction(ajaxSettings.data)) {
19703            // supplied as a function that returns a key/value object
19704            customRequestParams = ajaxSettings.data();
19705        }
19706        else {
19707            // probably supplied as a straight key/value object
19708            customRequestParams = ajaxSettings.data || {};
19709        }
19710        $.extend(params, customRequestParams);
19711        params[startParam] = start.format();
19712        params[endParam] = end.format();
19713        if (timezone && timezone !== 'local') {
19714            params[timezoneParam] = timezone;
19715        }
19716        return params;
19717    };
19718    JsonFeedEventSource.prototype.getPrimitive = function () {
19719        return this.url;
19720    };
19721    JsonFeedEventSource.prototype.applyMiscProps = function (rawProps) {
19722        this.ajaxSettings = rawProps;
19723    };
19724    JsonFeedEventSource.AJAX_DEFAULTS = {
19725        dataType: 'json',
19726        cache: false
19727    };
19728    return JsonFeedEventSource;
19729}(EventSource_1.default));
19730exports.default = JsonFeedEventSource;
19731JsonFeedEventSource.defineStandardProps({
19732    // automatically transfer (true)...
19733    url: true,
19734    startParam: true,
19735    endParam: true,
19736    timezoneParam: true
19737});
19738
19739
19740/***/ }),
19741/* 225 */
19742/***/ (function(module, exports) {
19743
19744Object.defineProperty(exports, "__esModule", { value: true });
19745var Iterator = /** @class */ (function () {
19746    function Iterator(items) {
19747        this.items = items || [];
19748    }
19749    /* Calls a method on every item passing the arguments through */
19750    Iterator.prototype.proxyCall = function (methodName) {
19751        var args = [];
19752        for (var _i = 1; _i < arguments.length; _i++) {
19753            args[_i - 1] = arguments[_i];
19754        }
19755        var results = [];
19756        this.items.forEach(function (item) {
19757            results.push(item[methodName].apply(item, args));
19758        });
19759        return results;
19760    };
19761    return Iterator;
19762}());
19763exports.default = Iterator;
19764
19765
19766/***/ }),
19767/* 226 */
19768/***/ (function(module, exports, __webpack_require__) {
19769
19770Object.defineProperty(exports, "__esModule", { value: true });
19771var $ = __webpack_require__(3);
19772var util_1 = __webpack_require__(4);
19773var ListenerMixin_1 = __webpack_require__(7);
19774/* Creates a clone of an element and lets it track the mouse as it moves
19775----------------------------------------------------------------------------------------------------------------------*/
19776var MouseFollower = /** @class */ (function () {
19777    function MouseFollower(sourceEl, options) {
19778        this.isFollowing = false;
19779        this.isHidden = false;
19780        this.isAnimating = false; // doing the revert animation?
19781        this.options = options = options || {};
19782        this.sourceEl = sourceEl;
19783        this.parentEl = options.parentEl ? $(options.parentEl) : sourceEl.parent(); // default to sourceEl's parent
19784    }
19785    // Causes the element to start following the mouse
19786    MouseFollower.prototype.start = function (ev) {
19787        if (!this.isFollowing) {
19788            this.isFollowing = true;
19789            this.y0 = util_1.getEvY(ev);
19790            this.x0 = util_1.getEvX(ev);
19791            this.topDelta = 0;
19792            this.leftDelta = 0;
19793            if (!this.isHidden) {
19794                this.updatePosition();
19795            }
19796            if (util_1.getEvIsTouch(ev)) {
19797                this.listenTo($(document), 'touchmove', this.handleMove);
19798            }
19799            else {
19800                this.listenTo($(document), 'mousemove', this.handleMove);
19801            }
19802        }
19803    };
19804    // Causes the element to stop following the mouse. If shouldRevert is true, will animate back to original position.
19805    // `callback` gets invoked when the animation is complete. If no animation, it is invoked immediately.
19806    MouseFollower.prototype.stop = function (shouldRevert, callback) {
19807        var _this = this;
19808        var revertDuration = this.options.revertDuration;
19809        var complete = function () {
19810            _this.isAnimating = false;
19811            _this.removeElement();
19812            _this.top0 = _this.left0 = null; // reset state for future updatePosition calls
19813            if (callback) {
19814                callback();
19815            }
19816        };
19817        if (this.isFollowing && !this.isAnimating) { // disallow more than one stop animation at a time
19818            this.isFollowing = false;
19819            this.stopListeningTo($(document));
19820            if (shouldRevert && revertDuration && !this.isHidden) { // do a revert animation?
19821                this.isAnimating = true;
19822                this.el.animate({
19823                    top: this.top0,
19824                    left: this.left0
19825                }, {
19826                    duration: revertDuration,
19827                    complete: complete
19828                });
19829            }
19830            else {
19831                complete();
19832            }
19833        }
19834    };
19835    // Gets the tracking element. Create it if necessary
19836    MouseFollower.prototype.getEl = function () {
19837        var el = this.el;
19838        if (!el) {
19839            el = this.el = this.sourceEl.clone()
19840                .addClass(this.options.additionalClass || '')
19841                .css({
19842                position: 'absolute',
19843                visibility: '',
19844                display: this.isHidden ? 'none' : '',
19845                margin: 0,
19846                right: 'auto',
19847                bottom: 'auto',
19848                width: this.sourceEl.width(),
19849                height: this.sourceEl.height(),
19850                opacity: this.options.opacity || '',
19851                zIndex: this.options.zIndex
19852            });
19853            // we don't want long taps or any mouse interaction causing selection/menus.
19854            // would use preventSelection(), but that prevents selectstart, causing problems.
19855            el.addClass('fc-unselectable');
19856            el.appendTo(this.parentEl);
19857        }
19858        return el;
19859    };
19860    // Removes the tracking element if it has already been created
19861    MouseFollower.prototype.removeElement = function () {
19862        if (this.el) {
19863            this.el.remove();
19864            this.el = null;
19865        }
19866    };
19867    // Update the CSS position of the tracking element
19868    MouseFollower.prototype.updatePosition = function () {
19869        var sourceOffset;
19870        var origin;
19871        this.getEl(); // ensure this.el
19872        // make sure origin info was computed
19873        if (this.top0 == null) {
19874            sourceOffset = this.sourceEl.offset();
19875            origin = this.el.offsetParent().offset();
19876            this.top0 = sourceOffset.top - origin.top;
19877            this.left0 = sourceOffset.left - origin.left;
19878        }
19879        this.el.css({
19880            top: this.top0 + this.topDelta,
19881            left: this.left0 + this.leftDelta
19882        });
19883    };
19884    // Gets called when the user moves the mouse
19885    MouseFollower.prototype.handleMove = function (ev) {
19886        this.topDelta = util_1.getEvY(ev) - this.y0;
19887        this.leftDelta = util_1.getEvX(ev) - this.x0;
19888        if (!this.isHidden) {
19889            this.updatePosition();
19890        }
19891    };
19892    // Temporarily makes the tracking element invisible. Can be called before following starts
19893    MouseFollower.prototype.hide = function () {
19894        if (!this.isHidden) {
19895            this.isHidden = true;
19896            if (this.el) {
19897                this.el.hide();
19898            }
19899        }
19900    };
19901    // Show the tracking element after it has been temporarily hidden
19902    MouseFollower.prototype.show = function () {
19903        if (this.isHidden) {
19904            this.isHidden = false;
19905            this.updatePosition();
19906            this.getEl().show();
19907        }
19908    };
19909    return MouseFollower;
19910}());
19911exports.default = MouseFollower;
19912ListenerMixin_1.default.mixInto(MouseFollower);
19913
19914
19915/***/ }),
19916/* 227 */
19917/***/ (function(module, exports, __webpack_require__) {
19918
19919/* A rectangular panel that is absolutely positioned over other content
19920------------------------------------------------------------------------------------------------------------------------
19921Options:
19922  - className (string)
19923  - content (HTML string or jQuery element set)
19924  - parentEl
19925  - top
19926  - left
19927  - right (the x coord of where the right edge should be. not a "CSS" right)
19928  - autoHide (boolean)
19929  - show (callback)
19930  - hide (callback)
19931*/
19932Object.defineProperty(exports, "__esModule", { value: true });
19933var $ = __webpack_require__(3);
19934var util_1 = __webpack_require__(4);
19935var ListenerMixin_1 = __webpack_require__(7);
19936var Popover = /** @class */ (function () {
19937    function Popover(options) {
19938        this.isHidden = true;
19939        this.margin = 10; // the space required between the popover and the edges of the scroll container
19940        this.options = options || {};
19941    }
19942    // Shows the popover on the specified position. Renders it if not already
19943    Popover.prototype.show = function () {
19944        if (this.isHidden) {
19945            if (!this.el) {
19946                this.render();
19947            }
19948            this.el.show();
19949            this.position();
19950            this.isHidden = false;
19951            this.trigger('show');
19952        }
19953    };
19954    // Hides the popover, through CSS, but does not remove it from the DOM
19955    Popover.prototype.hide = function () {
19956        if (!this.isHidden) {
19957            this.el.hide();
19958            this.isHidden = true;
19959            this.trigger('hide');
19960        }
19961    };
19962    // Creates `this.el` and renders content inside of it
19963    Popover.prototype.render = function () {
19964        var _this = this;
19965        var options = this.options;
19966        this.el = $('<div class="fc-popover">')
19967            .addClass(options.className || '')
19968            .css({
19969            // position initially to the top left to avoid creating scrollbars
19970            top: 0,
19971            left: 0
19972        })
19973            .append(options.content)
19974            .appendTo(options.parentEl);
19975        // when a click happens on anything inside with a 'fc-close' className, hide the popover
19976        this.el.on('click', '.fc-close', function () {
19977            _this.hide();
19978        });
19979        if (options.autoHide) {
19980            this.listenTo($(document), 'mousedown', this.documentMousedown);
19981        }
19982    };
19983    // Triggered when the user clicks *anywhere* in the document, for the autoHide feature
19984    Popover.prototype.documentMousedown = function (ev) {
19985        // only hide the popover if the click happened outside the popover
19986        if (this.el && !$(ev.target).closest(this.el).length) {
19987            this.hide();
19988        }
19989    };
19990    // Hides and unregisters any handlers
19991    Popover.prototype.removeElement = function () {
19992        this.hide();
19993        if (this.el) {
19994            this.el.remove();
19995            this.el = null;
19996        }
19997        this.stopListeningTo($(document), 'mousedown');
19998    };
19999    // Positions the popover optimally, using the top/left/right options
20000    Popover.prototype.position = function () {
20001        var options = this.options;
20002        var origin = this.el.offsetParent().offset();
20003        var width = this.el.outerWidth();
20004        var height = this.el.outerHeight();
20005        var windowEl = $(window);
20006        var viewportEl = util_1.getScrollParent(this.el);
20007        var viewportTop;
20008        var viewportLeft;
20009        var viewportOffset;
20010        var top; // the "position" (not "offset") values for the popover
20011        var left; //
20012        // compute top and left
20013        top = options.top || 0;
20014        if (options.left !== undefined) {
20015            left = options.left;
20016        }
20017        else if (options.right !== undefined) {
20018            left = options.right - width; // derive the left value from the right value
20019        }
20020        else {
20021            left = 0;
20022        }
20023        if (viewportEl.is(window) || viewportEl.is(document)) { // normalize getScrollParent's result
20024            viewportEl = windowEl;
20025            viewportTop = 0; // the window is always at the top left
20026            viewportLeft = 0; // (and .offset() won't work if called here)
20027        }
20028        else {
20029            viewportOffset = viewportEl.offset();
20030            viewportTop = viewportOffset.top;
20031            viewportLeft = viewportOffset.left;
20032        }
20033        // if the window is scrolled, it causes the visible area to be further down
20034        viewportTop += windowEl.scrollTop();
20035        viewportLeft += windowEl.scrollLeft();
20036        // constrain to the view port. if constrained by two edges, give precedence to top/left
20037        if (options.viewportConstrain !== false) {
20038            top = Math.min(top, viewportTop + viewportEl.outerHeight() - height - this.margin);
20039            top = Math.max(top, viewportTop + this.margin);
20040            left = Math.min(left, viewportLeft + viewportEl.outerWidth() - width - this.margin);
20041            left = Math.max(left, viewportLeft + this.margin);
20042        }
20043        this.el.css({
20044            top: top - origin.top,
20045            left: left - origin.left
20046        });
20047    };
20048    // Triggers a callback. Calls a function in the option hash of the same name.
20049    // Arguments beyond the first `name` are forwarded on.
20050    // TODO: better code reuse for this. Repeat code
20051    Popover.prototype.trigger = function (name) {
20052        if (this.options[name]) {
20053            this.options[name].apply(this, Array.prototype.slice.call(arguments, 1));
20054        }
20055    };
20056    return Popover;
20057}());
20058exports.default = Popover;
20059ListenerMixin_1.default.mixInto(Popover);
20060
20061
20062/***/ }),
20063/* 228 */
20064/***/ (function(module, exports, __webpack_require__) {
20065
20066Object.defineProperty(exports, "__esModule", { value: true });
20067var EmitterMixin_1 = __webpack_require__(13);
20068var TaskQueue = /** @class */ (function () {
20069    function TaskQueue() {
20070        this.q = [];
20071        this.isPaused = false;
20072        this.isRunning = false;
20073    }
20074    TaskQueue.prototype.queue = function () {
20075        var args = [];
20076        for (var _i = 0; _i < arguments.length; _i++) {
20077            args[_i] = arguments[_i];
20078        }
20079        this.q.push.apply(this.q, args); // append
20080        this.tryStart();
20081    };
20082    TaskQueue.prototype.pause = function () {
20083        this.isPaused = true;
20084    };
20085    TaskQueue.prototype.resume = function () {
20086        this.isPaused = false;
20087        this.tryStart();
20088    };
20089    TaskQueue.prototype.getIsIdle = function () {
20090        return !this.isRunning && !this.isPaused;
20091    };
20092    TaskQueue.prototype.tryStart = function () {
20093        if (!this.isRunning && this.canRunNext()) {
20094            this.isRunning = true;
20095            this.trigger('start');
20096            this.runRemaining();
20097        }
20098    };
20099    TaskQueue.prototype.canRunNext = function () {
20100        return !this.isPaused && this.q.length;
20101    };
20102    TaskQueue.prototype.runRemaining = function () {
20103        var _this = this;
20104        var task;
20105        var res;
20106        do {
20107            task = this.q.shift(); // always freshly reference q. might have been reassigned.
20108            res = this.runTask(task);
20109            if (res && res.then) {
20110                res.then(function () {
20111                    if (_this.canRunNext()) {
20112                        _this.runRemaining();
20113                    }
20114                });
20115                return; // prevent marking as stopped
20116            }
20117        } while (this.canRunNext());
20118        this.trigger('stop'); // not really a 'stop' ... more of a 'drained'
20119        this.isRunning = false;
20120        // if 'stop' handler added more tasks.... TODO: write test for this
20121        this.tryStart();
20122    };
20123    TaskQueue.prototype.runTask = function (task) {
20124        return task(); // task *is* the function, but subclasses can change the format of a task
20125    };
20126    return TaskQueue;
20127}());
20128exports.default = TaskQueue;
20129EmitterMixin_1.default.mixInto(TaskQueue);
20130
20131
20132/***/ }),
20133/* 229 */
20134/***/ (function(module, exports, __webpack_require__) {
20135
20136Object.defineProperty(exports, "__esModule", { value: true });
20137var tslib_1 = __webpack_require__(2);
20138var TaskQueue_1 = __webpack_require__(228);
20139var RenderQueue = /** @class */ (function (_super) {
20140    tslib_1.__extends(RenderQueue, _super);
20141    function RenderQueue(waitsByNamespace) {
20142        var _this = _super.call(this) || this;
20143        _this.waitsByNamespace = waitsByNamespace || {};
20144        return _this;
20145    }
20146    RenderQueue.prototype.queue = function (taskFunc, namespace, type) {
20147        var task = {
20148            func: taskFunc,
20149            namespace: namespace,
20150            type: type
20151        };
20152        var waitMs;
20153        if (namespace) {
20154            waitMs = this.waitsByNamespace[namespace];
20155        }
20156        if (this.waitNamespace) {
20157            if (namespace === this.waitNamespace && waitMs != null) {
20158                this.delayWait(waitMs);
20159            }
20160            else {
20161                this.clearWait();
20162                this.tryStart();
20163            }
20164        }
20165        if (this.compoundTask(task)) { // appended to queue?
20166            if (!this.waitNamespace && waitMs != null) {
20167                this.startWait(namespace, waitMs);
20168            }
20169            else {
20170                this.tryStart();
20171            }
20172        }
20173    };
20174    RenderQueue.prototype.startWait = function (namespace, waitMs) {
20175        this.waitNamespace = namespace;
20176        this.spawnWait(waitMs);
20177    };
20178    RenderQueue.prototype.delayWait = function (waitMs) {
20179        clearTimeout(this.waitId);
20180        this.spawnWait(waitMs);
20181    };
20182    RenderQueue.prototype.spawnWait = function (waitMs) {
20183        var _this = this;
20184        this.waitId = setTimeout(function () {
20185            _this.waitNamespace = null;
20186            _this.tryStart();
20187        }, waitMs);
20188    };
20189    RenderQueue.prototype.clearWait = function () {
20190        if (this.waitNamespace) {
20191            clearTimeout(this.waitId);
20192            this.waitId = null;
20193            this.waitNamespace = null;
20194        }
20195    };
20196    RenderQueue.prototype.canRunNext = function () {
20197        if (!_super.prototype.canRunNext.call(this)) {
20198            return false;
20199        }
20200        // waiting for a certain namespace to stop receiving tasks?
20201        if (this.waitNamespace) {
20202            var q = this.q;
20203            // if there was a different namespace task in the meantime,
20204            // that forces all previously-waiting tasks to suddenly execute.
20205            // TODO: find a way to do this in constant time.
20206            for (var i = 0; i < q.length; i++) {
20207                if (q[i].namespace !== this.waitNamespace) {
20208                    return true; // allow execution
20209                }
20210            }
20211            return false;
20212        }
20213        return true;
20214    };
20215    RenderQueue.prototype.runTask = function (task) {
20216        task.func();
20217    };
20218    RenderQueue.prototype.compoundTask = function (newTask) {
20219        var q = this.q;
20220        var shouldAppend = true;
20221        var i;
20222        var task;
20223        if (newTask.namespace && newTask.type === 'destroy') {
20224            // remove all init/add/remove ops with same namespace, regardless of order
20225            for (i = q.length - 1; i >= 0; i--) {
20226                task = q[i];
20227                if (task.namespace === newTask.namespace) {
20228                    switch (task.type) {
20229                        case 'init':
20230                            shouldAppend = false;
20231                        // the latest destroy is cancelled out by not doing the init
20232                        /* falls through */
20233                        case 'add':
20234                        /* falls through */
20235                        case 'remove':
20236                            q.splice(i, 1); // remove task
20237                    }
20238                }
20239            }
20240        }
20241        if (shouldAppend) {
20242            q.push(newTask);
20243        }
20244        return shouldAppend;
20245    };
20246    return RenderQueue;
20247}(TaskQueue_1.default));
20248exports.default = RenderQueue;
20249
20250
20251/***/ }),
20252/* 230 */
20253/***/ (function(module, exports, __webpack_require__) {
20254
20255Object.defineProperty(exports, "__esModule", { value: true });
20256var tslib_1 = __webpack_require__(2);
20257var Model_1 = __webpack_require__(51);
20258var Component = /** @class */ (function (_super) {
20259    tslib_1.__extends(Component, _super);
20260    function Component() {
20261        return _super !== null && _super.apply(this, arguments) || this;
20262    }
20263    Component.prototype.setElement = function (el) {
20264        this.el = el;
20265        this.bindGlobalHandlers();
20266        this.renderSkeleton();
20267        this.set('isInDom', true);
20268    };
20269    Component.prototype.removeElement = function () {
20270        this.unset('isInDom');
20271        this.unrenderSkeleton();
20272        this.unbindGlobalHandlers();
20273        this.el.remove();
20274        // NOTE: don't null-out this.el in case the View was destroyed within an API callback.
20275        // We don't null-out the View's other jQuery element references upon destroy,
20276        //  so we shouldn't kill this.el either.
20277    };
20278    Component.prototype.bindGlobalHandlers = function () {
20279        // subclasses can override
20280    };
20281    Component.prototype.unbindGlobalHandlers = function () {
20282        // subclasses can override
20283    };
20284    /*
20285    NOTE: Can't have a `render` method. Read the deprecation notice in View::executeDateRender
20286    */
20287    // Renders the basic structure of the view before any content is rendered
20288    Component.prototype.renderSkeleton = function () {
20289        // subclasses should implement
20290    };
20291    // Unrenders the basic structure of the view
20292    Component.prototype.unrenderSkeleton = function () {
20293        // subclasses should implement
20294    };
20295    return Component;
20296}(Model_1.default));
20297exports.default = Component;
20298
20299
20300/***/ }),
20301/* 231 */
20302/***/ (function(module, exports, __webpack_require__) {
20303
20304Object.defineProperty(exports, "__esModule", { value: true });
20305var tslib_1 = __webpack_require__(2);
20306var $ = __webpack_require__(3);
20307var moment = __webpack_require__(0);
20308var util_1 = __webpack_require__(4);
20309var moment_ext_1 = __webpack_require__(11);
20310var date_formatting_1 = __webpack_require__(49);
20311var Component_1 = __webpack_require__(230);
20312var util_2 = __webpack_require__(19);
20313var DateComponent = /** @class */ (function (_super) {
20314    tslib_1.__extends(DateComponent, _super);
20315    function DateComponent(_view, _options) {
20316        var _this = _super.call(this) || this;
20317        _this.isRTL = false; // frequently accessed options
20318        _this.hitsNeededDepth = 0; // necessary because multiple callers might need the same hits
20319        _this.hasAllDayBusinessHours = false; // TODO: unify with largeUnit and isTimeScale?
20320        _this.isDatesRendered = false;
20321        // hack to set options prior to the this.opt calls
20322        if (_view) {
20323            _this['view'] = _view;
20324        }
20325        if (_options) {
20326            _this['options'] = _options;
20327        }
20328        _this.uid = String(DateComponent.guid++);
20329        _this.childrenByUid = {};
20330        _this.nextDayThreshold = moment.duration(_this.opt('nextDayThreshold'));
20331        _this.isRTL = _this.opt('isRTL');
20332        if (_this.fillRendererClass) {
20333            _this.fillRenderer = new _this.fillRendererClass(_this);
20334        }
20335        if (_this.eventRendererClass) { // fillRenderer is optional -----v
20336            _this.eventRenderer = new _this.eventRendererClass(_this, _this.fillRenderer);
20337        }
20338        if (_this.helperRendererClass && _this.eventRenderer) {
20339            _this.helperRenderer = new _this.helperRendererClass(_this, _this.eventRenderer);
20340        }
20341        if (_this.businessHourRendererClass && _this.fillRenderer) {
20342            _this.businessHourRenderer = new _this.businessHourRendererClass(_this, _this.fillRenderer);
20343        }
20344        return _this;
20345    }
20346    DateComponent.prototype.addChild = function (child) {
20347        if (!this.childrenByUid[child.uid]) {
20348            this.childrenByUid[child.uid] = child;
20349            return true;
20350        }
20351        return false;
20352    };
20353    DateComponent.prototype.removeChild = function (child) {
20354        if (this.childrenByUid[child.uid]) {
20355            delete this.childrenByUid[child.uid];
20356            return true;
20357        }
20358        return false;
20359    };
20360    // TODO: only do if isInDom?
20361    // TODO: make part of Component, along with children/batch-render system?
20362    DateComponent.prototype.updateSize = function (totalHeight, isAuto, isResize) {
20363        this.callChildren('updateSize', arguments);
20364    };
20365    // Options
20366    // -----------------------------------------------------------------------------------------------------------------
20367    DateComponent.prototype.opt = function (name) {
20368        return this._getView().opt(name); // default implementation
20369    };
20370    DateComponent.prototype.publiclyTrigger = function () {
20371        var args = [];
20372        for (var _i = 0; _i < arguments.length; _i++) {
20373            args[_i] = arguments[_i];
20374        }
20375        var calendar = this._getCalendar();
20376        return calendar.publiclyTrigger.apply(calendar, args);
20377    };
20378    DateComponent.prototype.hasPublicHandlers = function () {
20379        var args = [];
20380        for (var _i = 0; _i < arguments.length; _i++) {
20381            args[_i] = arguments[_i];
20382        }
20383        var calendar = this._getCalendar();
20384        return calendar.hasPublicHandlers.apply(calendar, args);
20385    };
20386    // Date
20387    // -----------------------------------------------------------------------------------------------------------------
20388    DateComponent.prototype.executeDateRender = function (dateProfile) {
20389        this.dateProfile = dateProfile; // for rendering
20390        this.renderDates(dateProfile);
20391        this.isDatesRendered = true;
20392        this.callChildren('executeDateRender', arguments);
20393    };
20394    DateComponent.prototype.executeDateUnrender = function () {
20395        this.callChildren('executeDateUnrender', arguments);
20396        this.dateProfile = null;
20397        this.unrenderDates();
20398        this.isDatesRendered = false;
20399    };
20400    // date-cell content only
20401    DateComponent.prototype.renderDates = function (dateProfile) {
20402        // subclasses should implement
20403    };
20404    // date-cell content only
20405    DateComponent.prototype.unrenderDates = function () {
20406        // subclasses should override
20407    };
20408    // Now-Indicator
20409    // -----------------------------------------------------------------------------------------------------------------
20410    // Returns a string unit, like 'second' or 'minute' that defined how often the current time indicator
20411    // should be refreshed. If something falsy is returned, no time indicator is rendered at all.
20412    DateComponent.prototype.getNowIndicatorUnit = function () {
20413        // subclasses should implement
20414    };
20415    // Renders a current time indicator at the given datetime
20416    DateComponent.prototype.renderNowIndicator = function (date) {
20417        this.callChildren('renderNowIndicator', arguments);
20418    };
20419    // Undoes the rendering actions from renderNowIndicator
20420    DateComponent.prototype.unrenderNowIndicator = function () {
20421        this.callChildren('unrenderNowIndicator', arguments);
20422    };
20423    // Business Hours
20424    // ---------------------------------------------------------------------------------------------------------------
20425    DateComponent.prototype.renderBusinessHours = function (businessHourGenerator) {
20426        if (this.businessHourRenderer) {
20427            this.businessHourRenderer.render(businessHourGenerator);
20428        }
20429        this.callChildren('renderBusinessHours', arguments);
20430    };
20431    // Unrenders previously-rendered business-hours
20432    DateComponent.prototype.unrenderBusinessHours = function () {
20433        this.callChildren('unrenderBusinessHours', arguments);
20434        if (this.businessHourRenderer) {
20435            this.businessHourRenderer.unrender();
20436        }
20437    };
20438    // Event Displaying
20439    // -----------------------------------------------------------------------------------------------------------------
20440    DateComponent.prototype.executeEventRender = function (eventsPayload) {
20441        if (this.eventRenderer) {
20442            this.eventRenderer.rangeUpdated(); // poorly named now
20443            this.eventRenderer.render(eventsPayload);
20444        }
20445        else if (this['renderEvents']) { // legacy
20446            this['renderEvents'](convertEventsPayloadToLegacyArray(eventsPayload));
20447        }
20448        this.callChildren('executeEventRender', arguments);
20449    };
20450    DateComponent.prototype.executeEventUnrender = function () {
20451        this.callChildren('executeEventUnrender', arguments);
20452        if (this.eventRenderer) {
20453            this.eventRenderer.unrender();
20454        }
20455        else if (this['destroyEvents']) { // legacy
20456            this['destroyEvents']();
20457        }
20458    };
20459    DateComponent.prototype.getBusinessHourSegs = function () {
20460        var segs = this.getOwnBusinessHourSegs();
20461        this.iterChildren(function (child) {
20462            segs.push.apply(segs, child.getBusinessHourSegs());
20463        });
20464        return segs;
20465    };
20466    DateComponent.prototype.getOwnBusinessHourSegs = function () {
20467        if (this.businessHourRenderer) {
20468            return this.businessHourRenderer.getSegs();
20469        }
20470        return [];
20471    };
20472    DateComponent.prototype.getEventSegs = function () {
20473        var segs = this.getOwnEventSegs();
20474        this.iterChildren(function (child) {
20475            segs.push.apply(segs, child.getEventSegs());
20476        });
20477        return segs;
20478    };
20479    DateComponent.prototype.getOwnEventSegs = function () {
20480        if (this.eventRenderer) {
20481            return this.eventRenderer.getSegs();
20482        }
20483        return [];
20484    };
20485    // Event Rendering Triggering
20486    // -----------------------------------------------------------------------------------------------------------------
20487    DateComponent.prototype.triggerAfterEventsRendered = function () {
20488        this.triggerAfterEventSegsRendered(this.getEventSegs());
20489        this.publiclyTrigger('eventAfterAllRender', {
20490            context: this,
20491            args: [this]
20492        });
20493    };
20494    DateComponent.prototype.triggerAfterEventSegsRendered = function (segs) {
20495        var _this = this;
20496        // an optimization, because getEventLegacy is expensive
20497        if (this.hasPublicHandlers('eventAfterRender')) {
20498            segs.forEach(function (seg) {
20499                var legacy;
20500                if (seg.el) { // necessary?
20501                    legacy = seg.footprint.getEventLegacy();
20502                    _this.publiclyTrigger('eventAfterRender', {
20503                        context: legacy,
20504                        args: [legacy, seg.el, _this]
20505                    });
20506                }
20507            });
20508        }
20509    };
20510    DateComponent.prototype.triggerBeforeEventsDestroyed = function () {
20511        this.triggerBeforeEventSegsDestroyed(this.getEventSegs());
20512    };
20513    DateComponent.prototype.triggerBeforeEventSegsDestroyed = function (segs) {
20514        var _this = this;
20515        if (this.hasPublicHandlers('eventDestroy')) {
20516            segs.forEach(function (seg) {
20517                var legacy;
20518                if (seg.el) { // necessary?
20519                    legacy = seg.footprint.getEventLegacy();
20520                    _this.publiclyTrigger('eventDestroy', {
20521                        context: legacy,
20522                        args: [legacy, seg.el, _this]
20523                    });
20524                }
20525            });
20526        }
20527    };
20528    // Event Rendering Utils
20529    // -----------------------------------------------------------------------------------------------------------------
20530    // Hides all rendered event segments linked to the given event
20531    // RECURSIVE with subcomponents
20532    DateComponent.prototype.showEventsWithId = function (eventDefId) {
20533        this.getEventSegs().forEach(function (seg) {
20534            if (seg.footprint.eventDef.id === eventDefId &&
20535                seg.el // necessary?
20536            ) {
20537                seg.el.css('visibility', '');
20538            }
20539        });
20540        this.callChildren('showEventsWithId', arguments);
20541    };
20542    // Shows all rendered event segments linked to the given event
20543    // RECURSIVE with subcomponents
20544    DateComponent.prototype.hideEventsWithId = function (eventDefId) {
20545        this.getEventSegs().forEach(function (seg) {
20546            if (seg.footprint.eventDef.id === eventDefId &&
20547                seg.el // necessary?
20548            ) {
20549                seg.el.css('visibility', 'hidden');
20550            }
20551        });
20552        this.callChildren('hideEventsWithId', arguments);
20553    };
20554    // Drag-n-Drop Rendering (for both events and external elements)
20555    // ---------------------------------------------------------------------------------------------------------------
20556    // Renders a visual indication of a event or external-element drag over the given drop zone.
20557    // If an external-element, seg will be `null`.
20558    // Must return elements used for any mock events.
20559    DateComponent.prototype.renderDrag = function (eventFootprints, seg, isTouch) {
20560        var renderedHelper = false;
20561        this.iterChildren(function (child) {
20562            if (child.renderDrag(eventFootprints, seg, isTouch)) {
20563                renderedHelper = true;
20564            }
20565        });
20566        return renderedHelper;
20567    };
20568    // Unrenders a visual indication of an event or external-element being dragged.
20569    DateComponent.prototype.unrenderDrag = function () {
20570        this.callChildren('unrenderDrag', arguments);
20571    };
20572    // Event Resizing
20573    // ---------------------------------------------------------------------------------------------------------------
20574    // Renders a visual indication of an event being resized.
20575    DateComponent.prototype.renderEventResize = function (eventFootprints, seg, isTouch) {
20576        this.callChildren('renderEventResize', arguments);
20577    };
20578    // Unrenders a visual indication of an event being resized.
20579    DateComponent.prototype.unrenderEventResize = function () {
20580        this.callChildren('unrenderEventResize', arguments);
20581    };
20582    // Selection
20583    // ---------------------------------------------------------------------------------------------------------------
20584    // Renders a visual indication of the selection
20585    // TODO: rename to `renderSelection` after legacy is gone
20586    DateComponent.prototype.renderSelectionFootprint = function (componentFootprint) {
20587        this.renderHighlight(componentFootprint);
20588        this.callChildren('renderSelectionFootprint', arguments);
20589    };
20590    // Unrenders a visual indication of selection
20591    DateComponent.prototype.unrenderSelection = function () {
20592        this.unrenderHighlight();
20593        this.callChildren('unrenderSelection', arguments);
20594    };
20595    // Highlight
20596    // ---------------------------------------------------------------------------------------------------------------
20597    // Renders an emphasis on the given date range. Given a span (unzoned start/end and other misc data)
20598    DateComponent.prototype.renderHighlight = function (componentFootprint) {
20599        if (this.fillRenderer) {
20600            this.fillRenderer.renderFootprint('highlight', componentFootprint, {
20601                getClasses: function () {
20602                    return ['fc-highlight'];
20603                }
20604            });
20605        }
20606        this.callChildren('renderHighlight', arguments);
20607    };
20608    // Unrenders the emphasis on a date range
20609    DateComponent.prototype.unrenderHighlight = function () {
20610        if (this.fillRenderer) {
20611            this.fillRenderer.unrender('highlight');
20612        }
20613        this.callChildren('unrenderHighlight', arguments);
20614    };
20615    // Hit Areas
20616    // ---------------------------------------------------------------------------------------------------------------
20617    // just because all DateComponents support this interface
20618    // doesn't mean they need to have their own internal coord system. they can defer to sub-components.
20619    DateComponent.prototype.hitsNeeded = function () {
20620        if (!(this.hitsNeededDepth++)) {
20621            this.prepareHits();
20622        }
20623        this.callChildren('hitsNeeded', arguments);
20624    };
20625    DateComponent.prototype.hitsNotNeeded = function () {
20626        if (this.hitsNeededDepth && !(--this.hitsNeededDepth)) {
20627            this.releaseHits();
20628        }
20629        this.callChildren('hitsNotNeeded', arguments);
20630    };
20631    DateComponent.prototype.prepareHits = function () {
20632        // subclasses can implement
20633    };
20634    DateComponent.prototype.releaseHits = function () {
20635        // subclasses can implement
20636    };
20637    // Given coordinates from the topleft of the document, return data about the date-related area underneath.
20638    // Can return an object with arbitrary properties (although top/right/left/bottom are encouraged).
20639    // Must have a `grid` property, a reference to this current grid. TODO: avoid this
20640    // The returned object will be processed by getHitFootprint and getHitEl.
20641    DateComponent.prototype.queryHit = function (leftOffset, topOffset) {
20642        var childrenByUid = this.childrenByUid;
20643        var uid;
20644        var hit;
20645        for (uid in childrenByUid) {
20646            hit = childrenByUid[uid].queryHit(leftOffset, topOffset);
20647            if (hit) {
20648                break;
20649            }
20650        }
20651        return hit;
20652    };
20653    DateComponent.prototype.getSafeHitFootprint = function (hit) {
20654        var footprint = this.getHitFootprint(hit);
20655        if (!this.dateProfile.activeUnzonedRange.containsRange(footprint.unzonedRange)) {
20656            return null;
20657        }
20658        return footprint;
20659    };
20660    DateComponent.prototype.getHitFootprint = function (hit) {
20661        // what about being abstract!?
20662    };
20663    // Given position-level information about a date-related area within the grid,
20664    // should return a jQuery element that best represents it. passed to dayClick callback.
20665    DateComponent.prototype.getHitEl = function (hit) {
20666        // what about being abstract!?
20667    };
20668    /* Converting eventRange -> eventFootprint
20669    ------------------------------------------------------------------------------------------------------------------*/
20670    DateComponent.prototype.eventRangesToEventFootprints = function (eventRanges) {
20671        var eventFootprints = [];
20672        var i;
20673        for (i = 0; i < eventRanges.length; i++) {
20674            eventFootprints.push.apply(// append
20675            eventFootprints, this.eventRangeToEventFootprints(eventRanges[i]));
20676        }
20677        return eventFootprints;
20678    };
20679    DateComponent.prototype.eventRangeToEventFootprints = function (eventRange) {
20680        return [util_2.eventRangeToEventFootprint(eventRange)];
20681    };
20682    /* Converting componentFootprint/eventFootprint -> segs
20683    ------------------------------------------------------------------------------------------------------------------*/
20684    DateComponent.prototype.eventFootprintsToSegs = function (eventFootprints) {
20685        var segs = [];
20686        var i;
20687        for (i = 0; i < eventFootprints.length; i++) {
20688            segs.push.apply(segs, this.eventFootprintToSegs(eventFootprints[i]));
20689        }
20690        return segs;
20691    };
20692    // Given an event's span (unzoned start/end and other misc data), and the event itself,
20693    // slices into segments and attaches event-derived properties to them.
20694    // eventSpan - { start, end, isStart, isEnd, otherthings... }
20695    DateComponent.prototype.eventFootprintToSegs = function (eventFootprint) {
20696        var unzonedRange = eventFootprint.componentFootprint.unzonedRange;
20697        var segs;
20698        var i;
20699        var seg;
20700        segs = this.componentFootprintToSegs(eventFootprint.componentFootprint);
20701        for (i = 0; i < segs.length; i++) {
20702            seg = segs[i];
20703            if (!unzonedRange.isStart) {
20704                seg.isStart = false;
20705            }
20706            if (!unzonedRange.isEnd) {
20707                seg.isEnd = false;
20708            }
20709            seg.footprint = eventFootprint;
20710            // TODO: rename to seg.eventFootprint
20711        }
20712        return segs;
20713    };
20714    DateComponent.prototype.componentFootprintToSegs = function (componentFootprint) {
20715        return [];
20716    };
20717    // Utils
20718    // ---------------------------------------------------------------------------------------------------------------
20719    DateComponent.prototype.callChildren = function (methodName, args) {
20720        this.iterChildren(function (child) {
20721            child[methodName].apply(child, args);
20722        });
20723    };
20724    DateComponent.prototype.iterChildren = function (func) {
20725        var childrenByUid = this.childrenByUid;
20726        var uid;
20727        for (uid in childrenByUid) {
20728            func(childrenByUid[uid]);
20729        }
20730    };
20731    DateComponent.prototype._getCalendar = function () {
20732        var t = this;
20733        return t.calendar || t.view.calendar;
20734    };
20735    DateComponent.prototype._getView = function () {
20736        return this.view;
20737    };
20738    DateComponent.prototype._getDateProfile = function () {
20739        return this._getView().get('dateProfile');
20740    };
20741    // Generates HTML for an anchor to another view into the calendar.
20742    // Will either generate an <a> tag or a non-clickable <span> tag, depending on enabled settings.
20743    // `gotoOptions` can either be a moment input, or an object with the form:
20744    // { date, type, forceOff }
20745    // `type` is a view-type like "day" or "week". default value is "day".
20746    // `attrs` and `innerHtml` are use to generate the rest of the HTML tag.
20747    DateComponent.prototype.buildGotoAnchorHtml = function (gotoOptions, attrs, innerHtml) {
20748        var date;
20749        var type;
20750        var forceOff;
20751        var finalOptions;
20752        if ($.isPlainObject(gotoOptions)) {
20753            date = gotoOptions.date;
20754            type = gotoOptions.type;
20755            forceOff = gotoOptions.forceOff;
20756        }
20757        else {
20758            date = gotoOptions; // a single moment input
20759        }
20760        date = moment_ext_1.default(date); // if a string, parse it
20761        finalOptions = {
20762            date: date.format('YYYY-MM-DD'),
20763            type: type || 'day'
20764        };
20765        if (typeof attrs === 'string') {
20766            innerHtml = attrs;
20767            attrs = null;
20768        }
20769        attrs = attrs ? ' ' + util_1.attrsToStr(attrs) : ''; // will have a leading space
20770        innerHtml = innerHtml || '';
20771        if (!forceOff && this.opt('navLinks')) {
20772            return '<a' + attrs +
20773                ' data-goto="' + util_1.htmlEscape(JSON.stringify(finalOptions)) + '">' +
20774                innerHtml +
20775                '</a>';
20776        }
20777        else {
20778            return '<span' + attrs + '>' +
20779                innerHtml +
20780                '</span>';
20781        }
20782    };
20783    DateComponent.prototype.getAllDayHtml = function () {
20784        return this.opt('allDayHtml') || util_1.htmlEscape(this.opt('allDayText'));
20785    };
20786    // Computes HTML classNames for a single-day element
20787    DateComponent.prototype.getDayClasses = function (date, noThemeHighlight) {
20788        var view = this._getView();
20789        var classes = [];
20790        var today;
20791        if (!this.dateProfile.activeUnzonedRange.containsDate(date)) {
20792            classes.push('fc-disabled-day'); // TODO: jQuery UI theme?
20793        }
20794        else {
20795            classes.push('fc-' + util_1.dayIDs[date.day()]);
20796            if (view.isDateInOtherMonth(date, this.dateProfile)) { // TODO: use DateComponent subclass somehow
20797                classes.push('fc-other-month');
20798            }
20799            today = view.calendar.getNow();
20800            if (date.isSame(today, 'day')) {
20801                classes.push('fc-today');
20802                if (noThemeHighlight !== true) {
20803                    classes.push(view.calendar.theme.getClass('today'));
20804                }
20805            }
20806            else if (date < today) {
20807                classes.push('fc-past');
20808            }
20809            else {
20810                classes.push('fc-future');
20811            }
20812        }
20813        return classes;
20814    };
20815    // Utility for formatting a range. Accepts a range object, formatting string, and optional separator.
20816    // Displays all-day ranges naturally, with an inclusive end. Takes the current isRTL into account.
20817    // The timezones of the dates within `range` will be respected.
20818    DateComponent.prototype.formatRange = function (range, isAllDay, formatStr, separator) {
20819        var end = range.end;
20820        if (isAllDay) {
20821            end = end.clone().subtract(1); // convert to inclusive. last ms of previous day
20822        }
20823        return date_formatting_1.formatRange(range.start, end, formatStr, separator, this.isRTL);
20824    };
20825    // Compute the number of the give units in the "current" range.
20826    // Will return a floating-point number. Won't round.
20827    DateComponent.prototype.currentRangeAs = function (unit) {
20828        return this._getDateProfile().currentUnzonedRange.as(unit);
20829    };
20830    // Returns the date range of the full days the given range visually appears to occupy.
20831    // Returns a plain object with start/end, NOT an UnzonedRange!
20832    DateComponent.prototype.computeDayRange = function (unzonedRange) {
20833        var calendar = this._getCalendar();
20834        var startDay = calendar.msToUtcMoment(unzonedRange.startMs, true); // the beginning of the day the range starts
20835        var end = calendar.msToUtcMoment(unzonedRange.endMs);
20836        var endTimeMS = +end.time(); // # of milliseconds into `endDay`
20837        var endDay = end.clone().stripTime(); // the beginning of the day the range exclusively ends
20838        // If the end time is actually inclusively part of the next day and is equal to or
20839        // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`.
20840        // Otherwise, leaving it as inclusive will cause it to exclude `endDay`.
20841        if (endTimeMS && endTimeMS >= this.nextDayThreshold) {
20842            endDay.add(1, 'days');
20843        }
20844        // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day.
20845        if (endDay <= startDay) {
20846            endDay = startDay.clone().add(1, 'days');
20847        }
20848        return { start: startDay, end: endDay };
20849    };
20850    // Does the given range visually appear to occupy more than one day?
20851    DateComponent.prototype.isMultiDayRange = function (unzonedRange) {
20852        var dayRange = this.computeDayRange(unzonedRange);
20853        return dayRange.end.diff(dayRange.start, 'days') > 1;
20854    };
20855    DateComponent.guid = 0; // TODO: better system for this?
20856    return DateComponent;
20857}(Component_1.default));
20858exports.default = DateComponent;
20859// legacy
20860function convertEventsPayloadToLegacyArray(eventsPayload) {
20861    var eventDefId;
20862    var eventInstances;
20863    var legacyEvents = [];
20864    var i;
20865    for (eventDefId in eventsPayload) {
20866        eventInstances = eventsPayload[eventDefId].eventInstances;
20867        for (i = 0; i < eventInstances.length; i++) {
20868            legacyEvents.push(eventInstances[i].toLegacy());
20869        }
20870    }
20871    return legacyEvents;
20872}
20873
20874
20875/***/ }),
20876/* 232 */
20877/***/ (function(module, exports, __webpack_require__) {
20878
20879Object.defineProperty(exports, "__esModule", { value: true });
20880var $ = __webpack_require__(3);
20881var moment = __webpack_require__(0);
20882var util_1 = __webpack_require__(4);
20883var options_1 = __webpack_require__(33);
20884var Iterator_1 = __webpack_require__(225);
20885var GlobalEmitter_1 = __webpack_require__(23);
20886var EmitterMixin_1 = __webpack_require__(13);
20887var ListenerMixin_1 = __webpack_require__(7);
20888var Toolbar_1 = __webpack_require__(257);
20889var OptionsManager_1 = __webpack_require__(258);
20890var ViewSpecManager_1 = __webpack_require__(259);
20891var Constraints_1 = __webpack_require__(217);
20892var locale_1 = __webpack_require__(32);
20893var moment_ext_1 = __webpack_require__(11);
20894var UnzonedRange_1 = __webpack_require__(5);
20895var ComponentFootprint_1 = __webpack_require__(12);
20896var EventDateProfile_1 = __webpack_require__(16);
20897var EventManager_1 = __webpack_require__(220);
20898var BusinessHourGenerator_1 = __webpack_require__(218);
20899var EventSourceParser_1 = __webpack_require__(38);
20900var EventDefParser_1 = __webpack_require__(36);
20901var SingleEventDef_1 = __webpack_require__(9);
20902var EventDefMutation_1 = __webpack_require__(39);
20903var EventSource_1 = __webpack_require__(6);
20904var ThemeRegistry_1 = __webpack_require__(57);
20905var Calendar = /** @class */ (function () {
20906    function Calendar(el, overrides) {
20907        this.loadingLevel = 0; // number of simultaneous loading tasks
20908        this.ignoreUpdateViewSize = 0;
20909        this.freezeContentHeightDepth = 0;
20910        // declare the current calendar instance relies on GlobalEmitter. needed for garbage collection.
20911        // unneeded() is called in destroy.
20912        GlobalEmitter_1.default.needed();
20913        this.el = el;
20914        this.viewsByType = {};
20915        this.optionsManager = new OptionsManager_1.default(this, overrides);
20916        this.viewSpecManager = new ViewSpecManager_1.default(this.optionsManager, this);
20917        this.initMomentInternals(); // needs to happen after options hash initialized
20918        this.initCurrentDate();
20919        this.initEventManager();
20920        this.constraints = new Constraints_1.default(this.eventManager, this);
20921        this.constructed();
20922    }
20923    Calendar.prototype.constructed = function () {
20924        // useful for monkeypatching. used?
20925    };
20926    Calendar.prototype.getView = function () {
20927        return this.view;
20928    };
20929    Calendar.prototype.publiclyTrigger = function (name, triggerInfo) {
20930        var optHandler = this.opt(name);
20931        var context;
20932        var args;
20933        if ($.isPlainObject(triggerInfo)) {
20934            context = triggerInfo.context;
20935            args = triggerInfo.args;
20936        }
20937        else if ($.isArray(triggerInfo)) {
20938            args = triggerInfo;
20939        }
20940        if (context == null) {
20941            context = this.el[0]; // fallback context
20942        }
20943        if (!args) {
20944            args = [];
20945        }
20946        this.triggerWith(name, context, args); // Emitter's method
20947        if (optHandler) {
20948            return optHandler.apply(context, args);
20949        }
20950    };
20951    Calendar.prototype.hasPublicHandlers = function (name) {
20952        return this.hasHandlers(name) ||
20953            this.opt(name); // handler specified in options
20954    };
20955    // Options Public API
20956    // -----------------------------------------------------------------------------------------------------------------
20957    // public getter/setter
20958    Calendar.prototype.option = function (name, value) {
20959        var newOptionHash;
20960        if (typeof name === 'string') {
20961            if (value === undefined) { // getter
20962                return this.optionsManager.get(name);
20963            }
20964            else { // setter for individual option
20965                newOptionHash = {};
20966                newOptionHash[name] = value;
20967                this.optionsManager.add(newOptionHash);
20968            }
20969        }
20970        else if (typeof name === 'object') { // compound setter with object input
20971            this.optionsManager.add(name);
20972        }
20973    };
20974    // private getter
20975    Calendar.prototype.opt = function (name) {
20976        return this.optionsManager.get(name);
20977    };
20978    // View
20979    // -----------------------------------------------------------------------------------------------------------------
20980    // Given a view name for a custom view or a standard view, creates a ready-to-go View object
20981    Calendar.prototype.instantiateView = function (viewType) {
20982        var spec = this.viewSpecManager.getViewSpec(viewType);
20983        if (!spec) {
20984            throw new Error("View type \"" + viewType + "\" is not valid");
20985        }
20986        return new spec['class'](this, spec);
20987    };
20988    // Returns a boolean about whether the view is okay to instantiate at some point
20989    Calendar.prototype.isValidViewType = function (viewType) {
20990        return Boolean(this.viewSpecManager.getViewSpec(viewType));
20991    };
20992    Calendar.prototype.changeView = function (viewName, dateOrRange) {
20993        if (dateOrRange) {
20994            if (dateOrRange.start && dateOrRange.end) { // a range
20995                this.optionsManager.recordOverrides({
20996                    visibleRange: dateOrRange
20997                });
20998            }
20999            else { // a date
21000                this.currentDate = this.moment(dateOrRange).stripZone(); // just like gotoDate
21001            }
21002        }
21003        this.renderView(viewName);
21004    };
21005    // Forces navigation to a view for the given date.
21006    // `viewType` can be a specific view name or a generic one like "week" or "day".
21007    Calendar.prototype.zoomTo = function (newDate, viewType) {
21008        var spec;
21009        viewType = viewType || 'day'; // day is default zoom
21010        spec = this.viewSpecManager.getViewSpec(viewType) ||
21011            this.viewSpecManager.getUnitViewSpec(viewType);
21012        this.currentDate = newDate.clone();
21013        this.renderView(spec ? spec.type : null);
21014    };
21015    // Current Date
21016    // -----------------------------------------------------------------------------------------------------------------
21017    Calendar.prototype.initCurrentDate = function () {
21018        var defaultDateInput = this.opt('defaultDate');
21019        // compute the initial ambig-timezone date
21020        if (defaultDateInput != null) {
21021            this.currentDate = this.moment(defaultDateInput).stripZone();
21022        }
21023        else {
21024            this.currentDate = this.getNow(); // getNow already returns unzoned
21025        }
21026    };
21027    Calendar.prototype.prev = function () {
21028        var view = this.view;
21029        var prevInfo = view.dateProfileGenerator.buildPrev(view.get('dateProfile'));
21030        if (prevInfo.isValid) {
21031            this.currentDate = prevInfo.date;
21032            this.renderView();
21033        }
21034    };
21035    Calendar.prototype.next = function () {
21036        var view = this.view;
21037        var nextInfo = view.dateProfileGenerator.buildNext(view.get('dateProfile'));
21038        if (nextInfo.isValid) {
21039            this.currentDate = nextInfo.date;
21040            this.renderView();
21041        }
21042    };
21043    Calendar.prototype.prevYear = function () {
21044        this.currentDate.add(-1, 'years');
21045        this.renderView();
21046    };
21047    Calendar.prototype.nextYear = function () {
21048        this.currentDate.add(1, 'years');
21049        this.renderView();
21050    };
21051    Calendar.prototype.today = function () {
21052        this.currentDate = this.getNow(); // should deny like prev/next?
21053        this.renderView();
21054    };
21055    Calendar.prototype.gotoDate = function (zonedDateInput) {
21056        this.currentDate = this.moment(zonedDateInput).stripZone();
21057        this.renderView();
21058    };
21059    Calendar.prototype.incrementDate = function (delta) {
21060        this.currentDate.add(moment.duration(delta));
21061        this.renderView();
21062    };
21063    // for external API
21064    Calendar.prototype.getDate = function () {
21065        return this.applyTimezone(this.currentDate); // infuse the calendar's timezone
21066    };
21067    // Loading Triggering
21068    // -----------------------------------------------------------------------------------------------------------------
21069    // Should be called when any type of async data fetching begins
21070    Calendar.prototype.pushLoading = function () {
21071        if (!(this.loadingLevel++)) {
21072            this.publiclyTrigger('loading', [true, this.view]);
21073        }
21074    };
21075    // Should be called when any type of async data fetching completes
21076    Calendar.prototype.popLoading = function () {
21077        if (!(--this.loadingLevel)) {
21078            this.publiclyTrigger('loading', [false, this.view]);
21079        }
21080    };
21081    // High-level Rendering
21082    // -----------------------------------------------------------------------------------
21083    Calendar.prototype.render = function () {
21084        if (!this.contentEl) {
21085            this.initialRender();
21086        }
21087        else if (this.elementVisible()) {
21088            // mainly for the public API
21089            this.calcSize();
21090            this.updateViewSize();
21091        }
21092    };
21093    Calendar.prototype.initialRender = function () {
21094        var _this = this;
21095        var el = this.el;
21096        el.addClass('fc');
21097        // event delegation for nav links
21098        el.on('click.fc', 'a[data-goto]', function (ev) {
21099            var anchorEl = $(ev.currentTarget);
21100            var gotoOptions = anchorEl.data('goto'); // will automatically parse JSON
21101            var date = _this.moment(gotoOptions.date);
21102            var viewType = gotoOptions.type;
21103            // property like "navLinkDayClick". might be a string or a function
21104            var customAction = _this.view.opt('navLink' + util_1.capitaliseFirstLetter(viewType) + 'Click');
21105            if (typeof customAction === 'function') {
21106                customAction(date, ev);
21107            }
21108            else {
21109                if (typeof customAction === 'string') {
21110                    viewType = customAction;
21111                }
21112                _this.zoomTo(date, viewType);
21113            }
21114        });
21115        // called immediately, and upon option change
21116        this.optionsManager.watch('settingTheme', ['?theme', '?themeSystem'], function (opts) {
21117            var themeClass = ThemeRegistry_1.getThemeSystemClass(opts.themeSystem || opts.theme);
21118            var theme = new themeClass(_this.optionsManager);
21119            var widgetClass = theme.getClass('widget');
21120            _this.theme = theme;
21121            if (widgetClass) {
21122                el.addClass(widgetClass);
21123            }
21124        }, function () {
21125            var widgetClass = _this.theme.getClass('widget');
21126            _this.theme = null;
21127            if (widgetClass) {
21128                el.removeClass(widgetClass);
21129            }
21130        });
21131        this.optionsManager.watch('settingBusinessHourGenerator', ['?businessHours'], function (deps) {
21132            _this.businessHourGenerator = new BusinessHourGenerator_1.default(deps.businessHours, _this);
21133            if (_this.view) {
21134                _this.view.set('businessHourGenerator', _this.businessHourGenerator);
21135            }
21136        }, function () {
21137            _this.businessHourGenerator = null;
21138        });
21139        // called immediately, and upon option change.
21140        // HACK: locale often affects isRTL, so we explicitly listen to that too.
21141        this.optionsManager.watch('applyingDirClasses', ['?isRTL', '?locale'], function (opts) {
21142            el.toggleClass('fc-ltr', !opts.isRTL);
21143            el.toggleClass('fc-rtl', opts.isRTL);
21144        });
21145        this.contentEl = $("<div class='fc-view-container'>").prependTo(el);
21146        this.initToolbars();
21147        this.renderHeader();
21148        this.renderFooter();
21149        this.renderView(this.opt('defaultView'));
21150        if (this.opt('handleWindowResize')) {
21151            $(window).resize(this.windowResizeProxy = util_1.debounce(// prevents rapid calls
21152            this.windowResize.bind(this), this.opt('windowResizeDelay')));
21153        }
21154    };
21155    Calendar.prototype.destroy = function () {
21156        if (this.view) {
21157            this.clearView();
21158        }
21159        this.toolbarsManager.proxyCall('removeElement');
21160        this.contentEl.remove();
21161        this.el.removeClass('fc fc-ltr fc-rtl');
21162        // removes theme-related root className
21163        this.optionsManager.unwatch('settingTheme');
21164        this.optionsManager.unwatch('settingBusinessHourGenerator');
21165        this.el.off('.fc'); // unbind nav link handlers
21166        if (this.windowResizeProxy) {
21167            $(window).unbind('resize', this.windowResizeProxy);
21168            this.windowResizeProxy = null;
21169        }
21170        GlobalEmitter_1.default.unneeded();
21171    };
21172    Calendar.prototype.elementVisible = function () {
21173        return this.el.is(':visible');
21174    };
21175    // Render Queue
21176    // -----------------------------------------------------------------------------------------------------------------
21177    Calendar.prototype.bindViewHandlers = function (view) {
21178        var _this = this;
21179        view.watch('titleForCalendar', ['title'], function (deps) {
21180            if (view === _this.view) { // hack
21181                _this.setToolbarsTitle(deps.title);
21182            }
21183        });
21184        view.watch('dateProfileForCalendar', ['dateProfile'], function (deps) {
21185            if (view === _this.view) { // hack
21186                _this.currentDate = deps.dateProfile.date; // might have been constrained by view dates
21187                _this.updateToolbarButtons(deps.dateProfile);
21188            }
21189        });
21190    };
21191    Calendar.prototype.unbindViewHandlers = function (view) {
21192        view.unwatch('titleForCalendar');
21193        view.unwatch('dateProfileForCalendar');
21194    };
21195    // View Rendering
21196    // -----------------------------------------------------------------------------------
21197    // Renders a view because of a date change, view-type change, or for the first time.
21198    // If not given a viewType, keep the current view but render different dates.
21199    // Accepts an optional scroll state to restore to.
21200    Calendar.prototype.renderView = function (viewType) {
21201        var oldView = this.view;
21202        var newView;
21203        this.freezeContentHeight();
21204        if (oldView && viewType && oldView.type !== viewType) {
21205            this.clearView();
21206        }
21207        // if viewType changed, or the view was never created, create a fresh view
21208        if (!this.view && viewType) {
21209            newView = this.view =
21210                this.viewsByType[viewType] ||
21211                    (this.viewsByType[viewType] = this.instantiateView(viewType));
21212            this.bindViewHandlers(newView);
21213            newView.startBatchRender(); // so that setElement+setDate rendering are joined
21214            newView.setElement($("<div class='fc-view fc-" + viewType + "-view'>").appendTo(this.contentEl));
21215            this.toolbarsManager.proxyCall('activateButton', viewType);
21216        }
21217        if (this.view) {
21218            // prevent unnecessary change firing
21219            if (this.view.get('businessHourGenerator') !== this.businessHourGenerator) {
21220                this.view.set('businessHourGenerator', this.businessHourGenerator);
21221            }
21222            this.view.setDate(this.currentDate);
21223            if (newView) {
21224                newView.stopBatchRender();
21225            }
21226        }
21227        this.thawContentHeight();
21228    };
21229    // Unrenders the current view and reflects this change in the Header.
21230    // Unregsiters the `view`, but does not remove from viewByType hash.
21231    Calendar.prototype.clearView = function () {
21232        var currentView = this.view;
21233        this.toolbarsManager.proxyCall('deactivateButton', currentView.type);
21234        this.unbindViewHandlers(currentView);
21235        currentView.removeElement();
21236        currentView.unsetDate(); // so bindViewHandlers doesn't fire with old values next time
21237        this.view = null;
21238    };
21239    // Destroys the view, including the view object. Then, re-instantiates it and renders it.
21240    // Maintains the same scroll state.
21241    // TODO: maintain any other user-manipulated state.
21242    Calendar.prototype.reinitView = function () {
21243        var oldView = this.view;
21244        var scroll = oldView.queryScroll(); // wouldn't be so complicated if Calendar owned the scroll
21245        this.freezeContentHeight();
21246        this.clearView();
21247        this.calcSize();
21248        this.renderView(oldView.type); // needs the type to freshly render
21249        this.view.applyScroll(scroll);
21250        this.thawContentHeight();
21251    };
21252    // Resizing
21253    // -----------------------------------------------------------------------------------
21254    Calendar.prototype.getSuggestedViewHeight = function () {
21255        if (this.suggestedViewHeight == null) {
21256            this.calcSize();
21257        }
21258        return this.suggestedViewHeight;
21259    };
21260    Calendar.prototype.isHeightAuto = function () {
21261        return this.opt('contentHeight') === 'auto' || this.opt('height') === 'auto';
21262    };
21263    Calendar.prototype.updateViewSize = function (isResize) {
21264        if (isResize === void 0) { isResize = false; }
21265        var view = this.view;
21266        var scroll;
21267        if (!this.ignoreUpdateViewSize && view) {
21268            if (isResize) {
21269                this.calcSize();
21270                scroll = view.queryScroll();
21271            }
21272            this.ignoreUpdateViewSize++;
21273            view.updateSize(this.getSuggestedViewHeight(), this.isHeightAuto(), isResize);
21274            this.ignoreUpdateViewSize--;
21275            if (isResize) {
21276                view.applyScroll(scroll);
21277            }
21278            return true; // signal success
21279        }
21280    };
21281    Calendar.prototype.calcSize = function () {
21282        if (this.elementVisible()) {
21283            this._calcSize();
21284        }
21285    };
21286    Calendar.prototype._calcSize = function () {
21287        var contentHeightInput = this.opt('contentHeight');
21288        var heightInput = this.opt('height');
21289        if (typeof contentHeightInput === 'number') { // exists and not 'auto'
21290            this.suggestedViewHeight = contentHeightInput;
21291        }
21292        else if (typeof contentHeightInput === 'function') { // exists and is a function
21293            this.suggestedViewHeight = contentHeightInput();
21294        }
21295        else if (typeof heightInput === 'number') { // exists and not 'auto'
21296            this.suggestedViewHeight = heightInput - this.queryToolbarsHeight();
21297        }
21298        else if (typeof heightInput === 'function') { // exists and is a function
21299            this.suggestedViewHeight = heightInput() - this.queryToolbarsHeight();
21300        }
21301        else if (heightInput === 'parent') { // set to height of parent element
21302            this.suggestedViewHeight = this.el.parent().height() - this.queryToolbarsHeight();
21303        }
21304        else {
21305            this.suggestedViewHeight = Math.round(this.contentEl.width() /
21306                Math.max(this.opt('aspectRatio'), .5));
21307        }
21308    };
21309    Calendar.prototype.windowResize = function (ev) {
21310        if (
21311        // the purpose: so we don't process jqui "resize" events that have bubbled up
21312        // cast to any because .target, which is Element, can't be compared to window for some reason.
21313        ev.target === window &&
21314            this.view &&
21315            this.view.isDatesRendered) {
21316            if (this.updateViewSize(true)) { // isResize=true, returns true on success
21317                this.publiclyTrigger('windowResize', [this.view]);
21318            }
21319        }
21320    };
21321    /* Height "Freezing"
21322    -----------------------------------------------------------------------------*/
21323    Calendar.prototype.freezeContentHeight = function () {
21324        if (!(this.freezeContentHeightDepth++)) {
21325            this.forceFreezeContentHeight();
21326        }
21327    };
21328    Calendar.prototype.forceFreezeContentHeight = function () {
21329        this.contentEl.css({
21330            width: '100%',
21331            height: this.contentEl.height(),
21332            overflow: 'hidden'
21333        });
21334    };
21335    Calendar.prototype.thawContentHeight = function () {
21336        this.freezeContentHeightDepth--;
21337        // always bring back to natural height
21338        this.contentEl.css({
21339            width: '',
21340            height: '',
21341            overflow: ''
21342        });
21343        // but if there are future thaws, re-freeze
21344        if (this.freezeContentHeightDepth) {
21345            this.forceFreezeContentHeight();
21346        }
21347    };
21348    // Toolbar
21349    // -----------------------------------------------------------------------------------------------------------------
21350    Calendar.prototype.initToolbars = function () {
21351        this.header = new Toolbar_1.default(this, this.computeHeaderOptions());
21352        this.footer = new Toolbar_1.default(this, this.computeFooterOptions());
21353        this.toolbarsManager = new Iterator_1.default([this.header, this.footer]);
21354    };
21355    Calendar.prototype.computeHeaderOptions = function () {
21356        return {
21357            extraClasses: 'fc-header-toolbar',
21358            layout: this.opt('header')
21359        };
21360    };
21361    Calendar.prototype.computeFooterOptions = function () {
21362        return {
21363            extraClasses: 'fc-footer-toolbar',
21364            layout: this.opt('footer')
21365        };
21366    };
21367    // can be called repeatedly and Header will rerender
21368    Calendar.prototype.renderHeader = function () {
21369        var header = this.header;
21370        header.setToolbarOptions(this.computeHeaderOptions());
21371        header.render();
21372        if (header.el) {
21373            this.el.prepend(header.el);
21374        }
21375    };
21376    // can be called repeatedly and Footer will rerender
21377    Calendar.prototype.renderFooter = function () {
21378        var footer = this.footer;
21379        footer.setToolbarOptions(this.computeFooterOptions());
21380        footer.render();
21381        if (footer.el) {
21382            this.el.append(footer.el);
21383        }
21384    };
21385    Calendar.prototype.setToolbarsTitle = function (title) {
21386        this.toolbarsManager.proxyCall('updateTitle', title);
21387    };
21388    Calendar.prototype.updateToolbarButtons = function (dateProfile) {
21389        var now = this.getNow();
21390        var view = this.view;
21391        var todayInfo = view.dateProfileGenerator.build(now);
21392        var prevInfo = view.dateProfileGenerator.buildPrev(view.get('dateProfile'));
21393        var nextInfo = view.dateProfileGenerator.buildNext(view.get('dateProfile'));
21394        this.toolbarsManager.proxyCall((todayInfo.isValid && !dateProfile.currentUnzonedRange.containsDate(now)) ?
21395            'enableButton' :
21396            'disableButton', 'today');
21397        this.toolbarsManager.proxyCall(prevInfo.isValid ?
21398            'enableButton' :
21399            'disableButton', 'prev');
21400        this.toolbarsManager.proxyCall(nextInfo.isValid ?
21401            'enableButton' :
21402            'disableButton', 'next');
21403    };
21404    Calendar.prototype.queryToolbarsHeight = function () {
21405        return this.toolbarsManager.items.reduce(function (accumulator, toolbar) {
21406            var toolbarHeight = toolbar.el ? toolbar.el.outerHeight(true) : 0; // includes margin
21407            return accumulator + toolbarHeight;
21408        }, 0);
21409    };
21410    // Selection
21411    // -----------------------------------------------------------------------------------------------------------------
21412    // this public method receives start/end dates in any format, with any timezone
21413    Calendar.prototype.select = function (zonedStartInput, zonedEndInput) {
21414        this.view.select(this.buildSelectFootprint.apply(this, arguments));
21415    };
21416    Calendar.prototype.unselect = function () {
21417        if (this.view) {
21418            this.view.unselect();
21419        }
21420    };
21421    // Given arguments to the select method in the API, returns a span (unzoned start/end and other info)
21422    Calendar.prototype.buildSelectFootprint = function (zonedStartInput, zonedEndInput) {
21423        var start = this.moment(zonedStartInput).stripZone();
21424        var end;
21425        if (zonedEndInput) {
21426            end = this.moment(zonedEndInput).stripZone();
21427        }
21428        else if (start.hasTime()) {
21429            end = start.clone().add(this.defaultTimedEventDuration);
21430        }
21431        else {
21432            end = start.clone().add(this.defaultAllDayEventDuration);
21433        }
21434        return new ComponentFootprint_1.default(new UnzonedRange_1.default(start, end), !start.hasTime());
21435    };
21436    // Date Utils
21437    // -----------------------------------------------------------------------------------------------------------------
21438    Calendar.prototype.initMomentInternals = function () {
21439        var _this = this;
21440        this.defaultAllDayEventDuration = moment.duration(this.opt('defaultAllDayEventDuration'));
21441        this.defaultTimedEventDuration = moment.duration(this.opt('defaultTimedEventDuration'));
21442        // Called immediately, and when any of the options change.
21443        // Happens before any internal objects rebuild or rerender, because this is very core.
21444        this.optionsManager.watch('buildingMomentLocale', [
21445            '?locale', '?monthNames', '?monthNamesShort', '?dayNames', '?dayNamesShort',
21446            '?firstDay', '?weekNumberCalculation'
21447        ], function (opts) {
21448            var weekNumberCalculation = opts.weekNumberCalculation;
21449            var firstDay = opts.firstDay;
21450            var _week;
21451            // normalize
21452            if (weekNumberCalculation === 'iso') {
21453                weekNumberCalculation = 'ISO'; // normalize
21454            }
21455            var localeData = Object.create(// make a cheap copy
21456            locale_1.getMomentLocaleData(opts.locale) // will fall back to en
21457            );
21458            if (opts.monthNames) {
21459                localeData._months = opts.monthNames;
21460            }
21461            if (opts.monthNamesShort) {
21462                localeData._monthsShort = opts.monthNamesShort;
21463            }
21464            if (opts.dayNames) {
21465                localeData._weekdays = opts.dayNames;
21466            }
21467            if (opts.dayNamesShort) {
21468                localeData._weekdaysShort = opts.dayNamesShort;
21469            }
21470            if (firstDay == null && weekNumberCalculation === 'ISO') {
21471                firstDay = 1;
21472            }
21473            if (firstDay != null) {
21474                _week = Object.create(localeData._week); // _week: { dow: # }
21475                _week.dow = firstDay;
21476                localeData._week = _week;
21477            }
21478            if ( // whitelist certain kinds of input
21479            weekNumberCalculation === 'ISO' ||
21480                weekNumberCalculation === 'local' ||
21481                typeof weekNumberCalculation === 'function') {
21482                localeData._fullCalendar_weekCalc = weekNumberCalculation; // moment-ext will know what to do with it
21483            }
21484            _this.localeData = localeData;
21485            // If the internal current date object already exists, move to new locale.
21486            // We do NOT need to do this technique for event dates, because this happens when converting to "segments".
21487            if (_this.currentDate) {
21488                _this.localizeMoment(_this.currentDate); // sets to localeData
21489            }
21490        });
21491    };
21492    // Builds a moment using the settings of the current calendar: timezone and locale.
21493    // Accepts anything the vanilla moment() constructor accepts.
21494    Calendar.prototype.moment = function () {
21495        var args = [];
21496        for (var _i = 0; _i < arguments.length; _i++) {
21497            args[_i] = arguments[_i];
21498        }
21499        var mom;
21500        if (this.opt('timezone') === 'local') {
21501            mom = moment_ext_1.default.apply(null, args);
21502            // Force the moment to be local, because momentExt doesn't guarantee it.
21503            if (mom.hasTime()) { // don't give ambiguously-timed moments a local zone
21504                mom.local();
21505            }
21506        }
21507        else if (this.opt('timezone') === 'UTC') {
21508            mom = moment_ext_1.default.utc.apply(null, args); // process as UTC
21509        }
21510        else {
21511            mom = moment_ext_1.default.parseZone.apply(null, args); // let the input decide the zone
21512        }
21513        this.localizeMoment(mom); // TODO
21514        return mom;
21515    };
21516    Calendar.prototype.msToMoment = function (ms, forceAllDay) {
21517        var mom = moment_ext_1.default.utc(ms); // TODO: optimize by using Date.UTC
21518        if (forceAllDay) {
21519            mom.stripTime();
21520        }
21521        else {
21522            mom = this.applyTimezone(mom); // may or may not apply locale
21523        }
21524        this.localizeMoment(mom);
21525        return mom;
21526    };
21527    Calendar.prototype.msToUtcMoment = function (ms, forceAllDay) {
21528        var mom = moment_ext_1.default.utc(ms); // TODO: optimize by using Date.UTC
21529        if (forceAllDay) {
21530            mom.stripTime();
21531        }
21532        this.localizeMoment(mom);
21533        return mom;
21534    };
21535    // Updates the given moment's locale settings to the current calendar locale settings.
21536    Calendar.prototype.localizeMoment = function (mom) {
21537        mom._locale = this.localeData;
21538    };
21539    // Returns a boolean about whether or not the calendar knows how to calculate
21540    // the timezone offset of arbitrary dates in the current timezone.
21541    Calendar.prototype.getIsAmbigTimezone = function () {
21542        return this.opt('timezone') !== 'local' && this.opt('timezone') !== 'UTC';
21543    };
21544    // Returns a copy of the given date in the current timezone. Has no effect on dates without times.
21545    Calendar.prototype.applyTimezone = function (date) {
21546        if (!date.hasTime()) {
21547            return date.clone();
21548        }
21549        var zonedDate = this.moment(date.toArray());
21550        var timeAdjust = date.time().asMilliseconds() - zonedDate.time().asMilliseconds();
21551        var adjustedZonedDate;
21552        // Safari sometimes has problems with this coersion when near DST. Adjust if necessary. (bug #2396)
21553        if (timeAdjust) { // is the time result different than expected?
21554            adjustedZonedDate = zonedDate.clone().add(timeAdjust); // add milliseconds
21555            if (date.time().asMilliseconds() - adjustedZonedDate.time().asMilliseconds() === 0) { // does it match perfectly now?
21556                zonedDate = adjustedZonedDate;
21557            }
21558        }
21559        return zonedDate;
21560    };
21561    /*
21562    Assumes the footprint is non-open-ended.
21563    */
21564    Calendar.prototype.footprintToDateProfile = function (componentFootprint, ignoreEnd) {
21565        if (ignoreEnd === void 0) { ignoreEnd = false; }
21566        var start = moment_ext_1.default.utc(componentFootprint.unzonedRange.startMs);
21567        var end;
21568        if (!ignoreEnd) {
21569            end = moment_ext_1.default.utc(componentFootprint.unzonedRange.endMs);
21570        }
21571        if (componentFootprint.isAllDay) {
21572            start.stripTime();
21573            if (end) {
21574                end.stripTime();
21575            }
21576        }
21577        else {
21578            start = this.applyTimezone(start);
21579            if (end) {
21580                end = this.applyTimezone(end);
21581            }
21582        }
21583        this.localizeMoment(start);
21584        if (end) {
21585            this.localizeMoment(end);
21586        }
21587        return new EventDateProfile_1.default(start, end, this);
21588    };
21589    // Returns a moment for the current date, as defined by the client's computer or from the `now` option.
21590    // Will return an moment with an ambiguous timezone.
21591    Calendar.prototype.getNow = function () {
21592        var now = this.opt('now');
21593        if (typeof now === 'function') {
21594            now = now();
21595        }
21596        return this.moment(now).stripZone();
21597    };
21598    // Produces a human-readable string for the given duration.
21599    // Side-effect: changes the locale of the given duration.
21600    Calendar.prototype.humanizeDuration = function (duration) {
21601        return duration.locale(this.opt('locale')).humanize();
21602    };
21603    // will return `null` if invalid range
21604    Calendar.prototype.parseUnzonedRange = function (rangeInput) {
21605        var start = null;
21606        var end = null;
21607        if (rangeInput.start) {
21608            start = this.moment(rangeInput.start).stripZone();
21609        }
21610        if (rangeInput.end) {
21611            end = this.moment(rangeInput.end).stripZone();
21612        }
21613        if (!start && !end) {
21614            return null;
21615        }
21616        if (start && end && end.isBefore(start)) {
21617            return null;
21618        }
21619        return new UnzonedRange_1.default(start, end);
21620    };
21621    // Event-Date Utilities
21622    // -----------------------------------------------------------------------------------------------------------------
21623    Calendar.prototype.initEventManager = function () {
21624        var _this = this;
21625        var eventManager = new EventManager_1.default(this);
21626        var rawSources = this.opt('eventSources') || [];
21627        var singleRawSource = this.opt('events');
21628        this.eventManager = eventManager;
21629        if (singleRawSource) {
21630            rawSources.unshift(singleRawSource);
21631        }
21632        eventManager.on('release', function (eventsPayload) {
21633            _this.trigger('eventsReset', eventsPayload);
21634        });
21635        eventManager.freeze();
21636        rawSources.forEach(function (rawSource) {
21637            var source = EventSourceParser_1.default.parse(rawSource, _this);
21638            if (source) {
21639                eventManager.addSource(source);
21640            }
21641        });
21642        eventManager.thaw();
21643    };
21644    Calendar.prototype.requestEvents = function (start, end) {
21645        return this.eventManager.requestEvents(start, end, this.opt('timezone'), !this.opt('lazyFetching'));
21646    };
21647    // Get an event's normalized end date. If not present, calculate it from the defaults.
21648    Calendar.prototype.getEventEnd = function (event) {
21649        if (event.end) {
21650            return event.end.clone();
21651        }
21652        else {
21653            return this.getDefaultEventEnd(event.allDay, event.start);
21654        }
21655    };
21656    // Given an event's allDay status and start date, return what its fallback end date should be.
21657    // TODO: rename to computeDefaultEventEnd
21658    Calendar.prototype.getDefaultEventEnd = function (allDay, zonedStart) {
21659        var end = zonedStart.clone();
21660        if (allDay) {
21661            end.stripTime().add(this.defaultAllDayEventDuration);
21662        }
21663        else {
21664            end.add(this.defaultTimedEventDuration);
21665        }
21666        if (this.getIsAmbigTimezone()) {
21667            end.stripZone(); // we don't know what the tzo should be
21668        }
21669        return end;
21670    };
21671    // Public Events API
21672    // -----------------------------------------------------------------------------------------------------------------
21673    Calendar.prototype.rerenderEvents = function () {
21674        this.view.flash('displayingEvents');
21675    };
21676    Calendar.prototype.refetchEvents = function () {
21677        this.eventManager.refetchAllSources();
21678    };
21679    Calendar.prototype.renderEvents = function (eventInputs, isSticky) {
21680        this.eventManager.freeze();
21681        for (var i = 0; i < eventInputs.length; i++) {
21682            this.renderEvent(eventInputs[i], isSticky);
21683        }
21684        this.eventManager.thaw();
21685    };
21686    Calendar.prototype.renderEvent = function (eventInput, isSticky) {
21687        if (isSticky === void 0) { isSticky = false; }
21688        var eventManager = this.eventManager;
21689        var eventDef = EventDefParser_1.default.parse(eventInput, eventInput.source || eventManager.stickySource);
21690        if (eventDef) {
21691            eventManager.addEventDef(eventDef, isSticky);
21692        }
21693    };
21694    // legacyQuery operates on legacy event instance objects
21695    Calendar.prototype.removeEvents = function (legacyQuery) {
21696        var eventManager = this.eventManager;
21697        var legacyInstances = [];
21698        var idMap = {};
21699        var eventDef;
21700        var i;
21701        if (legacyQuery == null) { // shortcut for removing all
21702            eventManager.removeAllEventDefs(); // persist=true
21703        }
21704        else {
21705            eventManager.getEventInstances().forEach(function (eventInstance) {
21706                legacyInstances.push(eventInstance.toLegacy());
21707            });
21708            legacyInstances = filterLegacyEventInstances(legacyInstances, legacyQuery);
21709            // compute unique IDs
21710            for (i = 0; i < legacyInstances.length; i++) {
21711                eventDef = this.eventManager.getEventDefByUid(legacyInstances[i]._id);
21712                idMap[eventDef.id] = true;
21713            }
21714            eventManager.freeze();
21715            for (i in idMap) { // reuse `i` as an "id"
21716                eventManager.removeEventDefsById(i); // persist=true
21717            }
21718            eventManager.thaw();
21719        }
21720    };
21721    // legacyQuery operates on legacy event instance objects
21722    Calendar.prototype.clientEvents = function (legacyQuery) {
21723        var legacyEventInstances = [];
21724        this.eventManager.getEventInstances().forEach(function (eventInstance) {
21725            legacyEventInstances.push(eventInstance.toLegacy());
21726        });
21727        return filterLegacyEventInstances(legacyEventInstances, legacyQuery);
21728    };
21729    Calendar.prototype.updateEvents = function (eventPropsArray) {
21730        this.eventManager.freeze();
21731        for (var i = 0; i < eventPropsArray.length; i++) {
21732            this.updateEvent(eventPropsArray[i]);
21733        }
21734        this.eventManager.thaw();
21735    };
21736    Calendar.prototype.updateEvent = function (eventProps) {
21737        var eventDef = this.eventManager.getEventDefByUid(eventProps._id);
21738        var eventInstance;
21739        var eventDefMutation;
21740        if (eventDef instanceof SingleEventDef_1.default) {
21741            eventInstance = eventDef.buildInstance();
21742            eventDefMutation = EventDefMutation_1.default.createFromRawProps(eventInstance, eventProps, // raw props
21743            null // largeUnit -- who uses it?
21744            );
21745            this.eventManager.mutateEventsWithId(eventDef.id, eventDefMutation); // will release
21746        }
21747    };
21748    // Public Event Sources API
21749    // ------------------------------------------------------------------------------------
21750    Calendar.prototype.getEventSources = function () {
21751        return this.eventManager.otherSources.slice(); // clone
21752    };
21753    Calendar.prototype.getEventSourceById = function (id) {
21754        return this.eventManager.getSourceById(EventSource_1.default.normalizeId(id));
21755    };
21756    Calendar.prototype.addEventSource = function (sourceInput) {
21757        var source = EventSourceParser_1.default.parse(sourceInput, this);
21758        if (source) {
21759            this.eventManager.addSource(source);
21760        }
21761    };
21762    Calendar.prototype.removeEventSources = function (sourceMultiQuery) {
21763        var eventManager = this.eventManager;
21764        var sources;
21765        var i;
21766        if (sourceMultiQuery == null) {
21767            this.eventManager.removeAllSources();
21768        }
21769        else {
21770            sources = eventManager.multiQuerySources(sourceMultiQuery);
21771            eventManager.freeze();
21772            for (i = 0; i < sources.length; i++) {
21773                eventManager.removeSource(sources[i]);
21774            }
21775            eventManager.thaw();
21776        }
21777    };
21778    Calendar.prototype.removeEventSource = function (sourceQuery) {
21779        var eventManager = this.eventManager;
21780        var sources = eventManager.querySources(sourceQuery);
21781        var i;
21782        eventManager.freeze();
21783        for (i = 0; i < sources.length; i++) {
21784            eventManager.removeSource(sources[i]);
21785        }
21786        eventManager.thaw();
21787    };
21788    Calendar.prototype.refetchEventSources = function (sourceMultiQuery) {
21789        var eventManager = this.eventManager;
21790        var sources = eventManager.multiQuerySources(sourceMultiQuery);
21791        var i;
21792        eventManager.freeze();
21793        for (i = 0; i < sources.length; i++) {
21794            eventManager.refetchSource(sources[i]);
21795        }
21796        eventManager.thaw();
21797    };
21798    // not for internal use. use options module directly instead.
21799    Calendar.defaults = options_1.globalDefaults;
21800    Calendar.englishDefaults = options_1.englishDefaults;
21801    Calendar.rtlDefaults = options_1.rtlDefaults;
21802    return Calendar;
21803}());
21804exports.default = Calendar;
21805EmitterMixin_1.default.mixInto(Calendar);
21806ListenerMixin_1.default.mixInto(Calendar);
21807function filterLegacyEventInstances(legacyEventInstances, legacyQuery) {
21808    if (legacyQuery == null) {
21809        return legacyEventInstances;
21810    }
21811    else if ($.isFunction(legacyQuery)) {
21812        return legacyEventInstances.filter(legacyQuery);
21813    }
21814    else { // an event ID
21815        legacyQuery += ''; // normalize to string
21816        return legacyEventInstances.filter(function (legacyEventInstance) {
21817            // soft comparison because id not be normalized to string
21818            // tslint:disable-next-line
21819            return legacyEventInstance.id == legacyQuery ||
21820                legacyEventInstance._id === legacyQuery; // can specify internal id, but must exactly match
21821        });
21822    }
21823}
21824
21825
21826/***/ }),
21827/* 233 */
21828/***/ (function(module, exports, __webpack_require__) {
21829
21830Object.defineProperty(exports, "__esModule", { value: true });
21831var tslib_1 = __webpack_require__(2);
21832var $ = __webpack_require__(3);
21833var moment = __webpack_require__(0);
21834var exportHooks = __webpack_require__(18);
21835var util_1 = __webpack_require__(4);
21836var moment_ext_1 = __webpack_require__(11);
21837var ListenerMixin_1 = __webpack_require__(7);
21838var HitDragListener_1 = __webpack_require__(17);
21839var SingleEventDef_1 = __webpack_require__(9);
21840var EventInstanceGroup_1 = __webpack_require__(20);
21841var EventSource_1 = __webpack_require__(6);
21842var Interaction_1 = __webpack_require__(14);
21843var ExternalDropping = /** @class */ (function (_super) {
21844    tslib_1.__extends(ExternalDropping, _super);
21845    function ExternalDropping() {
21846        var _this = _super !== null && _super.apply(this, arguments) || this;
21847        _this.isDragging = false; // jqui-dragging an external element? boolean
21848        return _this;
21849    }
21850    /*
21851    component impements:
21852      - eventRangesToEventFootprints
21853      - isEventInstanceGroupAllowed
21854      - isExternalInstanceGroupAllowed
21855      - renderDrag
21856      - unrenderDrag
21857    */
21858    ExternalDropping.prototype.end = function () {
21859        if (this.dragListener) {
21860            this.dragListener.endInteraction();
21861        }
21862    };
21863    ExternalDropping.prototype.bindToDocument = function () {
21864        this.listenTo($(document), {
21865            dragstart: this.handleDragStart,
21866            sortstart: this.handleDragStart // jqui
21867        });
21868    };
21869    ExternalDropping.prototype.unbindFromDocument = function () {
21870        this.stopListeningTo($(document));
21871    };
21872    // Called when a jQuery UI drag is initiated anywhere in the DOM
21873    ExternalDropping.prototype.handleDragStart = function (ev, ui) {
21874        var el;
21875        var accept;
21876        if (this.opt('droppable')) { // only listen if this setting is on
21877            el = $((ui ? ui.item : null) || ev.target);
21878            // Test that the dragged element passes the dropAccept selector or filter function.
21879            // FYI, the default is "*" (matches all)
21880            accept = this.opt('dropAccept');
21881            if ($.isFunction(accept) ? accept.call(el[0], el) : el.is(accept)) {
21882                if (!this.isDragging) { // prevent double-listening if fired twice
21883                    this.listenToExternalDrag(el, ev, ui);
21884                }
21885            }
21886        }
21887    };
21888    // Called when a jQuery UI drag starts and it needs to be monitored for dropping
21889    ExternalDropping.prototype.listenToExternalDrag = function (el, ev, ui) {
21890        var _this = this;
21891        var component = this.component;
21892        var view = this.view;
21893        var meta = getDraggedElMeta(el); // extra data about event drop, including possible event to create
21894        var singleEventDef; // a null value signals an unsuccessful drag
21895        // listener that tracks mouse movement over date-associated pixel regions
21896        var dragListener = this.dragListener = new HitDragListener_1.default(component, {
21897            interactionStart: function () {
21898                _this.isDragging = true;
21899            },
21900            hitOver: function (hit) {
21901                var isAllowed = true;
21902                var hitFootprint = hit.component.getSafeHitFootprint(hit); // hit might not belong to this grid
21903                var mutatedEventInstanceGroup;
21904                if (hitFootprint) {
21905                    singleEventDef = _this.computeExternalDrop(hitFootprint, meta);
21906                    if (singleEventDef) {
21907                        mutatedEventInstanceGroup = new EventInstanceGroup_1.default(singleEventDef.buildInstances());
21908                        isAllowed = meta.eventProps ? // isEvent?
21909                            component.isEventInstanceGroupAllowed(mutatedEventInstanceGroup) :
21910                            component.isExternalInstanceGroupAllowed(mutatedEventInstanceGroup);
21911                    }
21912                    else {
21913                        isAllowed = false;
21914                    }
21915                }
21916                else {
21917                    isAllowed = false;
21918                }
21919                if (!isAllowed) {
21920                    singleEventDef = null;
21921                    util_1.disableCursor();
21922                }
21923                if (singleEventDef) {
21924                    component.renderDrag(// called without a seg parameter
21925                    component.eventRangesToEventFootprints(mutatedEventInstanceGroup.sliceRenderRanges(component.dateProfile.renderUnzonedRange, view.calendar)));
21926                }
21927            },
21928            hitOut: function () {
21929                singleEventDef = null; // signal unsuccessful
21930            },
21931            hitDone: function () {
21932                util_1.enableCursor();
21933                component.unrenderDrag();
21934            },
21935            interactionEnd: function (ev) {
21936                if (singleEventDef) { // element was dropped on a valid hit
21937                    view.reportExternalDrop(singleEventDef, Boolean(meta.eventProps), // isEvent
21938                    Boolean(meta.stick), // isSticky
21939                    el, ev, ui);
21940                }
21941                _this.isDragging = false;
21942                _this.dragListener = null;
21943            }
21944        });
21945        dragListener.startDrag(ev); // start listening immediately
21946    };
21947    // Given a hit to be dropped upon, and misc data associated with the jqui drag (guaranteed to be a plain object),
21948    // returns the zoned start/end dates for the event that would result from the hypothetical drop. end might be null.
21949    // Returning a null value signals an invalid drop hit.
21950    // DOES NOT consider overlap/constraint.
21951    // Assumes both footprints are non-open-ended.
21952    ExternalDropping.prototype.computeExternalDrop = function (componentFootprint, meta) {
21953        var calendar = this.view.calendar;
21954        var start = moment_ext_1.default.utc(componentFootprint.unzonedRange.startMs).stripZone();
21955        var end;
21956        var eventDef;
21957        if (componentFootprint.isAllDay) {
21958            // if dropped on an all-day span, and element's metadata specified a time, set it
21959            if (meta.startTime) {
21960                start.time(meta.startTime);
21961            }
21962            else {
21963                start.stripTime();
21964            }
21965        }
21966        if (meta.duration) {
21967            end = start.clone().add(meta.duration);
21968        }
21969        start = calendar.applyTimezone(start);
21970        if (end) {
21971            end = calendar.applyTimezone(end);
21972        }
21973        eventDef = SingleEventDef_1.default.parse($.extend({}, meta.eventProps, {
21974            start: start,
21975            end: end
21976        }), new EventSource_1.default(calendar));
21977        return eventDef;
21978    };
21979    return ExternalDropping;
21980}(Interaction_1.default));
21981exports.default = ExternalDropping;
21982ListenerMixin_1.default.mixInto(ExternalDropping);
21983/* External-Dragging-Element Data
21984----------------------------------------------------------------------------------------------------------------------*/
21985// Require all HTML5 data-* attributes used by FullCalendar to have this prefix.
21986// A value of '' will query attributes like data-event. A value of 'fc' will query attributes like data-fc-event.
21987exportHooks.dataAttrPrefix = '';
21988// Given a jQuery element that might represent a dragged FullCalendar event, returns an intermediate data structure
21989// to be used for Event Object creation.
21990// A defined `.eventProps`, even when empty, indicates that an event should be created.
21991function getDraggedElMeta(el) {
21992    var prefix = exportHooks.dataAttrPrefix;
21993    var eventProps; // properties for creating the event, not related to date/time
21994    var startTime; // a Duration
21995    var duration;
21996    var stick;
21997    if (prefix) {
21998        prefix += '-';
21999    }
22000    eventProps = el.data(prefix + 'event') || null;
22001    if (eventProps) {
22002        if (typeof eventProps === 'object') {
22003            eventProps = $.extend({}, eventProps); // make a copy
22004        }
22005        else { // something like 1 or true. still signal event creation
22006            eventProps = {};
22007        }
22008        // pluck special-cased date/time properties
22009        startTime = eventProps.start;
22010        if (startTime == null) {
22011            startTime = eventProps.time;
22012        } // accept 'time' as well
22013        duration = eventProps.duration;
22014        stick = eventProps.stick;
22015        delete eventProps.start;
22016        delete eventProps.time;
22017        delete eventProps.duration;
22018        delete eventProps.stick;
22019    }
22020    // fallback to standalone attribute values for each of the date/time properties
22021    if (startTime == null) {
22022        startTime = el.data(prefix + 'start');
22023    }
22024    if (startTime == null) {
22025        startTime = el.data(prefix + 'time');
22026    } // accept 'time' as well
22027    if (duration == null) {
22028        duration = el.data(prefix + 'duration');
22029    }
22030    if (stick == null) {
22031        stick = el.data(prefix + 'stick');
22032    }
22033    // massage into correct data types
22034    startTime = startTime != null ? moment.duration(startTime) : null;
22035    duration = duration != null ? moment.duration(duration) : null;
22036    stick = Boolean(stick);
22037    return { eventProps: eventProps, startTime: startTime, duration: duration, stick: stick };
22038}
22039
22040
22041/***/ }),
22042/* 234 */
22043/***/ (function(module, exports, __webpack_require__) {
22044
22045Object.defineProperty(exports, "__esModule", { value: true });
22046var tslib_1 = __webpack_require__(2);
22047var $ = __webpack_require__(3);
22048var util_1 = __webpack_require__(4);
22049var EventDefMutation_1 = __webpack_require__(39);
22050var EventDefDateMutation_1 = __webpack_require__(40);
22051var HitDragListener_1 = __webpack_require__(17);
22052var Interaction_1 = __webpack_require__(14);
22053var EventResizing = /** @class */ (function (_super) {
22054    tslib_1.__extends(EventResizing, _super);
22055    /*
22056    component impements:
22057      - bindSegHandlerToEl
22058      - publiclyTrigger
22059      - diffDates
22060      - eventRangesToEventFootprints
22061      - isEventInstanceGroupAllowed
22062      - getSafeHitFootprint
22063    */
22064    function EventResizing(component, eventPointing) {
22065        var _this = _super.call(this, component) || this;
22066        _this.isResizing = false;
22067        _this.eventPointing = eventPointing;
22068        return _this;
22069    }
22070    EventResizing.prototype.end = function () {
22071        if (this.dragListener) {
22072            this.dragListener.endInteraction();
22073        }
22074    };
22075    EventResizing.prototype.bindToEl = function (el) {
22076        var component = this.component;
22077        component.bindSegHandlerToEl(el, 'mousedown', this.handleMouseDown.bind(this));
22078        component.bindSegHandlerToEl(el, 'touchstart', this.handleTouchStart.bind(this));
22079    };
22080    EventResizing.prototype.handleMouseDown = function (seg, ev) {
22081        if (this.component.canStartResize(seg, ev)) {
22082            this.buildDragListener(seg, $(ev.target).is('.fc-start-resizer'))
22083                .startInteraction(ev, { distance: 5 });
22084        }
22085    };
22086    EventResizing.prototype.handleTouchStart = function (seg, ev) {
22087        if (this.component.canStartResize(seg, ev)) {
22088            this.buildDragListener(seg, $(ev.target).is('.fc-start-resizer'))
22089                .startInteraction(ev);
22090        }
22091    };
22092    // Creates a listener that tracks the user as they resize an event segment.
22093    // Generic enough to work with any type of Grid.
22094    EventResizing.prototype.buildDragListener = function (seg, isStart) {
22095        var _this = this;
22096        var component = this.component;
22097        var view = this.view;
22098        var calendar = view.calendar;
22099        var eventManager = calendar.eventManager;
22100        var el = seg.el;
22101        var eventDef = seg.footprint.eventDef;
22102        var eventInstance = seg.footprint.eventInstance;
22103        var isDragging;
22104        var resizeMutation; // zoned event date properties. falsy if invalid resize
22105        // Tracks mouse movement over the *grid's* coordinate map
22106        var dragListener = this.dragListener = new HitDragListener_1.default(component, {
22107            scroll: this.opt('dragScroll'),
22108            subjectEl: el,
22109            interactionStart: function () {
22110                isDragging = false;
22111            },
22112            dragStart: function (ev) {
22113                isDragging = true;
22114                // ensure a mouseout on the manipulated event has been reported
22115                _this.eventPointing.handleMouseout(seg, ev);
22116                _this.segResizeStart(seg, ev);
22117            },
22118            hitOver: function (hit, isOrig, origHit) {
22119                var isAllowed = true;
22120                var origHitFootprint = component.getSafeHitFootprint(origHit);
22121                var hitFootprint = component.getSafeHitFootprint(hit);
22122                var mutatedEventInstanceGroup;
22123                if (origHitFootprint && hitFootprint) {
22124                    resizeMutation = isStart ?
22125                        _this.computeEventStartResizeMutation(origHitFootprint, hitFootprint, seg.footprint) :
22126                        _this.computeEventEndResizeMutation(origHitFootprint, hitFootprint, seg.footprint);
22127                    if (resizeMutation) {
22128                        mutatedEventInstanceGroup = eventManager.buildMutatedEventInstanceGroup(eventDef.id, resizeMutation);
22129                        isAllowed = component.isEventInstanceGroupAllowed(mutatedEventInstanceGroup);
22130                    }
22131                    else {
22132                        isAllowed = false;
22133                    }
22134                }
22135                else {
22136                    isAllowed = false;
22137                }
22138                if (!isAllowed) {
22139                    resizeMutation = null;
22140                    util_1.disableCursor();
22141                }
22142                else if (resizeMutation.isEmpty()) {
22143                    // no change. (FYI, event dates might have zones)
22144                    resizeMutation = null;
22145                }
22146                if (resizeMutation) {
22147                    view.hideEventsWithId(seg.footprint.eventDef.id);
22148                    view.renderEventResize(component.eventRangesToEventFootprints(mutatedEventInstanceGroup.sliceRenderRanges(component.dateProfile.renderUnzonedRange, calendar)), seg);
22149                }
22150            },
22151            hitOut: function () {
22152                resizeMutation = null;
22153            },
22154            hitDone: function () {
22155                view.unrenderEventResize(seg);
22156                view.showEventsWithId(seg.footprint.eventDef.id);
22157                util_1.enableCursor();
22158            },
22159            interactionEnd: function (ev) {
22160                if (isDragging) {
22161                    _this.segResizeStop(seg, ev);
22162                }
22163                if (resizeMutation) { // valid date to resize to?
22164                    // no need to re-show original, will rerender all anyways. esp important if eventRenderWait
22165                    view.reportEventResize(eventInstance, resizeMutation, el, ev);
22166                }
22167                _this.dragListener = null;
22168            }
22169        });
22170        return dragListener;
22171    };
22172    // Called before event segment resizing starts
22173    EventResizing.prototype.segResizeStart = function (seg, ev) {
22174        this.isResizing = true;
22175        this.component.publiclyTrigger('eventResizeStart', {
22176            context: seg.el[0],
22177            args: [
22178                seg.footprint.getEventLegacy(),
22179                ev,
22180                {},
22181                this.view
22182            ]
22183        });
22184    };
22185    // Called after event segment resizing stops
22186    EventResizing.prototype.segResizeStop = function (seg, ev) {
22187        this.isResizing = false;
22188        this.component.publiclyTrigger('eventResizeStop', {
22189            context: seg.el[0],
22190            args: [
22191                seg.footprint.getEventLegacy(),
22192                ev,
22193                {},
22194                this.view
22195            ]
22196        });
22197    };
22198    // Returns new date-information for an event segment being resized from its start
22199    EventResizing.prototype.computeEventStartResizeMutation = function (startFootprint, endFootprint, origEventFootprint) {
22200        var origRange = origEventFootprint.componentFootprint.unzonedRange;
22201        var startDelta = this.component.diffDates(endFootprint.unzonedRange.getStart(), startFootprint.unzonedRange.getStart());
22202        var dateMutation;
22203        var eventDefMutation;
22204        if (origRange.getStart().add(startDelta) < origRange.getEnd()) {
22205            dateMutation = new EventDefDateMutation_1.default();
22206            dateMutation.setStartDelta(startDelta);
22207            eventDefMutation = new EventDefMutation_1.default();
22208            eventDefMutation.setDateMutation(dateMutation);
22209            return eventDefMutation;
22210        }
22211        return false;
22212    };
22213    // Returns new date-information for an event segment being resized from its end
22214    EventResizing.prototype.computeEventEndResizeMutation = function (startFootprint, endFootprint, origEventFootprint) {
22215        var origRange = origEventFootprint.componentFootprint.unzonedRange;
22216        var endDelta = this.component.diffDates(endFootprint.unzonedRange.getEnd(), startFootprint.unzonedRange.getEnd());
22217        var dateMutation;
22218        var eventDefMutation;
22219        if (origRange.getEnd().add(endDelta) > origRange.getStart()) {
22220            dateMutation = new EventDefDateMutation_1.default();
22221            dateMutation.setEndDelta(endDelta);
22222            eventDefMutation = new EventDefMutation_1.default();
22223            eventDefMutation.setDateMutation(dateMutation);
22224            return eventDefMutation;
22225        }
22226        return false;
22227    };
22228    return EventResizing;
22229}(Interaction_1.default));
22230exports.default = EventResizing;
22231
22232
22233/***/ }),
22234/* 235 */
22235/***/ (function(module, exports, __webpack_require__) {
22236
22237Object.defineProperty(exports, "__esModule", { value: true });
22238var tslib_1 = __webpack_require__(2);
22239var util_1 = __webpack_require__(4);
22240var EventDefMutation_1 = __webpack_require__(39);
22241var EventDefDateMutation_1 = __webpack_require__(40);
22242var DragListener_1 = __webpack_require__(59);
22243var HitDragListener_1 = __webpack_require__(17);
22244var MouseFollower_1 = __webpack_require__(226);
22245var Interaction_1 = __webpack_require__(14);
22246var EventDragging = /** @class */ (function (_super) {
22247    tslib_1.__extends(EventDragging, _super);
22248    /*
22249    component implements:
22250      - bindSegHandlerToEl
22251      - publiclyTrigger
22252      - diffDates
22253      - eventRangesToEventFootprints
22254      - isEventInstanceGroupAllowed
22255    */
22256    function EventDragging(component, eventPointing) {
22257        var _this = _super.call(this, component) || this;
22258        _this.isDragging = false;
22259        _this.eventPointing = eventPointing;
22260        return _this;
22261    }
22262    EventDragging.prototype.end = function () {
22263        if (this.dragListener) {
22264            this.dragListener.endInteraction();
22265        }
22266    };
22267    EventDragging.prototype.getSelectionDelay = function () {
22268        var delay = this.opt('eventLongPressDelay');
22269        if (delay == null) {
22270            delay = this.opt('longPressDelay'); // fallback
22271        }
22272        return delay;
22273    };
22274    EventDragging.prototype.bindToEl = function (el) {
22275        var component = this.component;
22276        component.bindSegHandlerToEl(el, 'mousedown', this.handleMousedown.bind(this));
22277        component.bindSegHandlerToEl(el, 'touchstart', this.handleTouchStart.bind(this));
22278    };
22279    EventDragging.prototype.handleMousedown = function (seg, ev) {
22280        if (!this.component.shouldIgnoreMouse() &&
22281            this.component.canStartDrag(seg, ev)) {
22282            this.buildDragListener(seg).startInteraction(ev, { distance: 5 });
22283        }
22284    };
22285    EventDragging.prototype.handleTouchStart = function (seg, ev) {
22286        var component = this.component;
22287        var settings = {
22288            delay: this.view.isEventDefSelected(seg.footprint.eventDef) ? // already selected?
22289                0 : this.getSelectionDelay()
22290        };
22291        if (component.canStartDrag(seg, ev)) {
22292            this.buildDragListener(seg).startInteraction(ev, settings);
22293        }
22294        else if (component.canStartSelection(seg, ev)) {
22295            this.buildSelectListener(seg).startInteraction(ev, settings);
22296        }
22297    };
22298    // seg isn't draggable, but let's use a generic DragListener
22299    // simply for the delay, so it can be selected.
22300    // Has side effect of setting/unsetting `dragListener`
22301    EventDragging.prototype.buildSelectListener = function (seg) {
22302        var _this = this;
22303        var view = this.view;
22304        var eventDef = seg.footprint.eventDef;
22305        var eventInstance = seg.footprint.eventInstance; // null for inverse-background events
22306        if (this.dragListener) {
22307            return this.dragListener;
22308        }
22309        var dragListener = this.dragListener = new DragListener_1.default({
22310            dragStart: function (ev) {
22311                if (dragListener.isTouch &&
22312                    !view.isEventDefSelected(eventDef) &&
22313                    eventInstance) {
22314                    // if not previously selected, will fire after a delay. then, select the event
22315                    view.selectEventInstance(eventInstance);
22316                }
22317            },
22318            interactionEnd: function (ev) {
22319                _this.dragListener = null;
22320            }
22321        });
22322        return dragListener;
22323    };
22324    // Builds a listener that will track user-dragging on an event segment.
22325    // Generic enough to work with any type of Grid.
22326    // Has side effect of setting/unsetting `dragListener`
22327    EventDragging.prototype.buildDragListener = function (seg) {
22328        var _this = this;
22329        var component = this.component;
22330        var view = this.view;
22331        var calendar = view.calendar;
22332        var eventManager = calendar.eventManager;
22333        var el = seg.el;
22334        var eventDef = seg.footprint.eventDef;
22335        var eventInstance = seg.footprint.eventInstance; // null for inverse-background events
22336        var isDragging;
22337        var mouseFollower; // A clone of the original element that will move with the mouse
22338        var eventDefMutation;
22339        if (this.dragListener) {
22340            return this.dragListener;
22341        }
22342        // Tracks mouse movement over the *view's* coordinate map. Allows dragging and dropping between subcomponents
22343        // of the view.
22344        var dragListener = this.dragListener = new HitDragListener_1.default(view, {
22345            scroll: this.opt('dragScroll'),
22346            subjectEl: el,
22347            subjectCenter: true,
22348            interactionStart: function (ev) {
22349                seg.component = component; // for renderDrag
22350                isDragging = false;
22351                mouseFollower = new MouseFollower_1.default(seg.el, {
22352                    additionalClass: 'fc-dragging',
22353                    parentEl: view.el,
22354                    opacity: dragListener.isTouch ? null : _this.opt('dragOpacity'),
22355                    revertDuration: _this.opt('dragRevertDuration'),
22356                    zIndex: 2 // one above the .fc-view
22357                });
22358                mouseFollower.hide(); // don't show until we know this is a real drag
22359                mouseFollower.start(ev);
22360            },
22361            dragStart: function (ev) {
22362                if (dragListener.isTouch &&
22363                    !view.isEventDefSelected(eventDef) &&
22364                    eventInstance) {
22365                    // if not previously selected, will fire after a delay. then, select the event
22366                    view.selectEventInstance(eventInstance);
22367                }
22368                isDragging = true;
22369                // ensure a mouseout on the manipulated event has been reported
22370                _this.eventPointing.handleMouseout(seg, ev);
22371                _this.segDragStart(seg, ev);
22372                view.hideEventsWithId(seg.footprint.eventDef.id);
22373            },
22374            hitOver: function (hit, isOrig, origHit) {
22375                var isAllowed = true;
22376                var origFootprint;
22377                var footprint;
22378                var mutatedEventInstanceGroup;
22379                // starting hit could be forced (DayGrid.limit)
22380                if (seg.hit) {
22381                    origHit = seg.hit;
22382                }
22383                // hit might not belong to this grid, so query origin grid
22384                origFootprint = origHit.component.getSafeHitFootprint(
22384origHit);
22385                footprint = hit.component.getSafeHitFootprint(hit);
22386                if (origFootprint && footprint) {
22387                    eventDefMutation = _this.computeEventDropMutation(origFootprint, footprint, eventDef);
22388                    if (eventDefMutation) {
22389                        mutatedEventInstanceGroup = eventManager.buildMutatedEventInstanceGroup(eventDef.id, eventDefMutation);
22390                        isAllowed = component.isEventInstanceGroupAllowed(mutatedEventInstanceGroup);
22391                    }
22392                    else {
22393                        isAllowed = false;
22394                    }
22395                }
22396                else {
22397                    isAllowed = false;
22398                }
22399                if (!isAllowed) {
22400                    eventDefMutation = null;
22401                    util_1.disableCursor();
22402                }
22403                // if a valid drop location, have the subclass render a visual indication
22404                if (eventDefMutation &&
22405                    view.renderDrag(// truthy if rendered something
22406                    component.eventRangesToEventFootprints(mutatedEventInstanceGroup.sliceRenderRanges(component.dateProfile.renderUnzonedRange, calendar)), seg, dragListener.isTouch)) {
22407                    mouseFollower.hide(); // if the subclass is already using a mock event "helper", hide our own
22408                }
22409                else {
22410                    mouseFollower.show(); // otherwise, have the helper follow the mouse (no snapping)
22411                }
22412                if (isOrig) {
22413                    // needs to have moved hits to be a valid drop
22414                    eventDefMutation = null;
22415                }
22416            },
22417            hitOut: function () {
22418                view.unrenderDrag(seg); // unrender whatever was done in renderDrag
22419                mouseFollower.show(); // show in case we are moving out of all hits
22420                eventDefMutation = null;
22421            },
22422            hitDone: function () {
22423                util_1.enableCursor();
22424            },
22425            interactionEnd: function (ev) {
22426                delete seg.component; // prevent side effects
22427                // do revert animation if hasn't changed. calls a callback when finished (whether animation or not)
22428                mouseFollower.stop(!eventDefMutation, function () {
22429                    if (isDragging) {
22430                        view.unrenderDrag(seg);
22431                        _this.segDragStop(seg, ev);
22432                    }
22433                    view.showEventsWithId(seg.footprint.eventDef.id);
22434                    if (eventDefMutation) {
22435                        // no need to re-show original, will rerender all anyways. esp important if eventRenderWait
22436                        view.reportEventDrop(eventInstance, eventDefMutation, el, ev);
22437                    }
22438                });
22439                _this.dragListener = null;
22440            }
22441        });
22442        return dragListener;
22443    };
22444    // Called before event segment dragging starts
22445    EventDragging.prototype.segDragStart = function (seg, ev) {
22446        this.isDragging = true;
22447        this.component.publiclyTrigger('eventDragStart', {
22448            context: seg.el[0],
22449            args: [
22450                seg.footprint.getEventLegacy(),
22451                ev,
22452                {},
22453                this.view
22454            ]
22455        });
22456    };
22457    // Called after event segment dragging stops
22458    EventDragging.prototype.segDragStop = function (seg, ev) {
22459        this.isDragging = false;
22460        this.component.publiclyTrigger('eventDragStop', {
22461            context: seg.el[0],
22462            args: [
22463                seg.footprint.getEventLegacy(),
22464                ev,
22465                {},
22466                this.view
22467            ]
22468        });
22469    };
22470    // DOES NOT consider overlap/constraint
22471    EventDragging.prototype.computeEventDropMutation = function (startFootprint, endFootprint, eventDef) {
22472        var eventDefMutation = new EventDefMutation_1.default();
22473        eventDefMutation.setDateMutation(this.computeEventDateMutation(startFootprint, endFootprint));
22474        return eventDefMutation;
22475    };
22476    EventDragging.prototype.computeEventDateMutation = function (startFootprint, endFootprint) {
22477        var date0 = startFootprint.unzonedRange.getStart();
22478        var date1 = endFootprint.unzonedRange.getStart();
22479        var clearEnd = false;
22480        var forceTimed = false;
22481        var forceAllDay = false;
22482        var dateDelta;
22483        var dateMutation;
22484        if (startFootprint.isAllDay !== endFootprint.isAllDay) {
22485            clearEnd = true;
22486            if (endFootprint.isAllDay) {
22487                forceAllDay = true;
22488                date0.stripTime();
22489            }
22490            else {
22491                forceTimed = true;
22492            }
22493        }
22494        dateDelta = this.component.diffDates(date1, date0);
22495        dateMutation = new EventDefDateMutation_1.default();
22496        dateMutation.clearEnd = clearEnd;
22497        dateMutation.forceTimed = forceTimed;
22498        dateMutation.forceAllDay = forceAllDay;
22499        dateMutation.setDateDelta(dateDelta);
22500        return dateMutation;
22501    };
22502    return EventDragging;
22503}(Interaction_1.default));
22504exports.default = EventDragging;
22505
22506
22507/***/ }),
22508/* 236 */
22509/***/ (function(module, exports, __webpack_require__) {
22510
22511Object.defineProperty(exports, "__esModule", { value: true });
22512var tslib_1 = __webpack_require__(2);
22513var util_1 = __webpack_require__(4);
22514var HitDragListener_1 = __webpack_require__(17);
22515var ComponentFootprint_1 = __webpack_require__(12);
22516var UnzonedRange_1 = __webpack_require__(5);
22517var Interaction_1 = __webpack_require__(14);
22518var DateSelecting = /** @class */ (function (_super) {
22519    tslib_1.__extends(DateSelecting, _super);
22520    /*
22521    component must implement:
22522      - bindDateHandlerToEl
22523      - getSafeHitFootprint
22524      - renderHighlight
22525      - unrenderHighlight
22526    */
22527    function DateSelecting(component) {
22528        var _this = _super.call(this, component) || this;
22529        _this.dragListener = _this.buildDragListener();
22530        return _this;
22531    }
22532    DateSelecting.prototype.end = function () {
22533        this.dragListener.endInteraction();
22534    };
22535    DateSelecting.prototype.getDelay = function () {
22536        var delay = this.opt('selectLongPressDelay');
22537        if (delay == null) {
22538            delay = this.opt('longPressDelay'); // fallback
22539        }
22540        return delay;
22541    };
22542    DateSelecting.prototype.bindToEl = function (el) {
22543        var _this = this;
22544        var component = this.component;
22545        var dragListener = this.dragListener;
22546        component.bindDateHandlerToEl(el, 'mousedown', function (ev) {
22547            if (_this.opt('selectable') && !component.shouldIgnoreMouse()) {
22548                dragListener.startInteraction(ev, {
22549                    distance: _this.opt('selectMinDistance')
22550                });
22551            }
22552        });
22553        component.bindDateHandlerToEl(el, 'touchstart', function (ev) {
22554            if (_this.opt('selectable') && !component.shouldIgnoreTouch()) {
22555                dragListener.startInteraction(ev, {
22556                    delay: _this.getDelay()
22557                });
22558            }
22559        });
22560        util_1.preventSelection(el);
22561    };
22562    // Creates a listener that tracks the user's drag across day elements, for day selecting.
22563    DateSelecting.prototype.buildDragListener = function () {
22564        var _this = this;
22565        var component = this.component;
22566        var selectionFootprint; // null if invalid selection
22567        var dragListener = new HitDragListener_1.default(component, {
22568            scroll: this.opt('dragScroll'),
22569            interactionStart: function () {
22570                selectionFootprint = null;
22571            },
22572            dragStart: function (ev) {
22573                _this.view.unselect(ev); // since we could be rendering a new selection, we want to clear any old one
22574            },
22575            hitOver: function (hit, isOrig, origHit) {
22576                var origHitFootprint;
22577                var hitFootprint;
22578                if (origHit) { // click needs to have started on a hit
22579                    origHitFootprint = component.getSafeHitFootprint(origHit);
22580                    hitFootprint = component.getSafeHitFootprint(hit);
22581                    if (origHitFootprint && hitFootprint) {
22582                        selectionFootprint = _this.computeSelection(origHitFootprint, hitFootprint);
22583                    }
22584                    else {
22585                        selectionFootprint = null;
22586                    }
22587                    if (selectionFootprint) {
22588                        component.renderSelectionFootprint(selectionFootprint);
22589                    }
22590                    else if (selectionFootprint === false) {
22591                        util_1.disableCursor();
22592                    }
22593                }
22594            },
22595            hitOut: function () {
22596                selectionFootprint = null;
22597                component.unrenderSelection();
22598            },
22599            hitDone: function () {
22600                util_1.enableCursor();
22601            },
22602            interactionEnd: function (ev, isCancelled) {
22603                if (!isCancelled && selectionFootprint) {
22604                    // the selection will already have been rendered. just report it
22605                    _this.view.reportSelection(selectionFootprint, ev);
22606                }
22607            }
22608        });
22609        return dragListener;
22610    };
22611    // Given the first and last date-spans of a selection, returns another date-span object.
22612    // Subclasses can override and provide additional data in the span object. Will be passed to renderSelectionFootprint().
22613    // Will return false if the selection is invalid and this should be indicated to the user.
22614    // Will return null/undefined if a selection invalid but no error should be reported.
22615    DateSelecting.prototype.computeSelection = function (footprint0, footprint1) {
22616        var wholeFootprint = this.computeSelectionFootprint(footprint0, footprint1);
22617        if (wholeFootprint && !this.isSelectionFootprintAllowed(wholeFootprint)) {
22618            return false;
22619        }
22620        return wholeFootprint;
22621    };
22622    // Given two spans, must return the combination of the two.
22623    // TODO: do this separation of concerns (combining VS validation) for event dnd/resize too.
22624    // Assumes both footprints are non-open-ended.
22625    DateSelecting.prototype.computeSelectionFootprint = function (footprint0, footprint1) {
22626        var ms = [
22627            footprint0.unzonedRange.startMs,
22628            footprint0.unzonedRange.endMs,
22629            footprint1.unzonedRange.startMs,
22630            footprint1.unzonedRange.endMs
22631        ];
22632        ms.sort(util_1.compareNumbers);
22633        return new ComponentFootprint_1.default(new UnzonedRange_1.default(ms[0], ms[3]), footprint0.isAllDay);
22634    };
22635    DateSelecting.prototype.isSelectionFootprintAllowed = function (componentFootprint) {
22636        return this.component.dateProfile.validUnzonedRange.containsRange(componentFootprint.unzonedRange) &&
22637            this.view.calendar.constraints.isSelectionFootprintAllowed(componentFootprint);
22638    };
22639    return DateSelecting;
22640}(Interaction_1.default));
22641exports.default = DateSelecting;
22642
22643
22644/***/ }),
22645/* 237 */
22646/***/ (function(module, exports, __webpack_require__) {
22647
22648Object.defineProperty(exports, "__esModule", { value: true });
22649var tslib_1 = __webpack_require__(2);
22650var HitDragListener_1 = __webpack_require__(17);
22651var Interaction_1 = __webpack_require__(14);
22652var DateClicking = /** @class */ (function (_super) {
22653    tslib_1.__extends(DateClicking, _super);
22654    /*
22655    component must implement:
22656      - bindDateHandlerToEl
22657      - getSafeHitFootprint
22658      - getHitEl
22659    */
22660    function DateClicking(component) {
22661        var _this = _super.call(this, component) || this;
22662        _this.dragListener = _this.buildDragListener();
22663        return _this;
22664    }
22665    DateClicking.prototype.end = function () {
22666        this.dragListener.endInteraction();
22667    };
22668    DateClicking.prototype.bindToEl = function (el) {
22669        var component = this.component;
22670        var dragListener = this.dragListener;
22671        component.bindDateHandlerToEl(el, 'mousedown', function (ev) {
22672            if (!component.shouldIgnoreMouse()) {
22673                dragListener.startInteraction(ev);
22674            }
22675        });
22676        component.bindDateHandlerToEl(el, 'touchstart', function (ev) {
22677            if (!component.shouldIgnoreTouch()) {
22678                dragListener.startInteraction(ev);
22679            }
22680        });
22681    };
22682    // Creates a listener that tracks the user's drag across day elements, for day clicking.
22683    DateClicking.prototype.buildDragListener = function () {
22684        var _this = this;
22685        var component = this.component;
22686        var dayClickHit; // null if invalid dayClick
22687        var dragListener = new HitDragListener_1.default(component, {
22688            scroll: this.opt('dragScroll'),
22689            interactionStart: function () {
22690                dayClickHit = dragListener.origHit;
22691            },
22692            hitOver: function (hit, isOrig, origHit) {
22693                // if user dragged to another cell at any point, it can no longer be a dayClick
22694                if (!isOrig) {
22695                    dayClickHit = null;
22696                }
22697            },
22698            hitOut: function () {
22699                dayClickHit = null;
22700            },
22701            interactionEnd: function (ev, isCancelled) {
22702                var componentFootprint;
22703                if (!isCancelled && dayClickHit) {
22704                    componentFootprint = component.getSafeHitFootprint(dayClickHit);
22705                    if (componentFootprint) {
22706                        _this.view.triggerDayClick(componentFootprint, component.getHitEl(dayClickHit), ev);
22707                    }
22708                }
22709            }
22710        });
22711        // because dragListener won't be called with any time delay, "dragging" will begin immediately,
22712        // which will kill any touchmoving/scrolling. Prevent this.
22713        dragListener.shouldCancelTouchScroll = false;
22714        dragListener.scrollAlwaysKills = true;
22715        return dragListener;
22716    };
22717    return DateClicking;
22718}(Interaction_1.default));
22719exports.default = DateClicking;
22720
22721
22722/***/ }),
22723/* 238 */
22724/***/ (function(module, exports, __webpack_require__) {
22725
22726Object.defineProperty(exports, "__esModule", { value: true });
22727var tslib_1 = __webpack_require__(2);
22728var moment = __webpack_require__(0);
22729var $ = __webpack_require__(3);
22730var util_1 = __webpack_require__(4);
22731var Scroller_1 = __webpack_require__(41);
22732var View_1 = __webpack_require__(43);
22733var TimeGrid_1 = __webpack_require__(239);
22734var DayGrid_1 = __webpack_require__(66);
22735var AGENDA_ALL_DAY_EVENT_LIMIT = 5;
22736var agendaTimeGridMethods;
22737var agendaDayGridMethods;
22738/* An abstract class for all agenda-related views. Displays one more columns with time slots running vertically.
22739----------------------------------------------------------------------------------------------------------------------*/
22740// Is a manager for the TimeGrid subcomponent and possibly the DayGrid subcomponent (if allDaySlot is on).
22741// Responsible for managing width/height.
22742var AgendaView = /** @class */ (function (_super) {
22743    tslib_1.__extends(AgendaView, _super);
22744    function AgendaView(calendar, viewSpec) {
22745        var _this = _super.call(this, calendar, viewSpec) || this;
22746        _this.usesMinMaxTime = true; // indicates that minTime/maxTime affects rendering
22747        _this.timeGrid = _this.instantiateTimeGrid();
22748        _this.addChild(_this.timeGrid);
22749        if (_this.opt('allDaySlot')) { // should we display the "all-day" area?
22750            _this.dayGrid = _this.instantiateDayGrid(); // the all-day subcomponent of this view
22751            _this.addChild(_this.dayGrid);
22752        }
22753        _this.scroller = new Scroller_1.default({
22754            overflowX: 'hidden',
22755            overflowY: 'auto'
22756        });
22757        return _this;
22758    }
22759    // Instantiates the TimeGrid object this view needs. Draws from this.timeGridClass
22760    AgendaView.prototype.instantiateTimeGrid = function () {
22761        var timeGrid = new this.timeGridClass(this);
22762        util_1.copyOwnProps(agendaTimeGridMethods, timeGrid);
22763        return timeGrid;
22764    };
22765    // Instantiates the DayGrid object this view might need. Draws from this.dayGridClass
22766    AgendaView.prototype.instantiateDayGrid = function () {
22767        var dayGrid = new this.dayGridClass(this);
22768        util_1.copyOwnProps(agendaDayGridMethods, dayGrid);
22769        return dayGrid;
22770    };
22771    /* Rendering
22772    ------------------------------------------------------------------------------------------------------------------*/
22773    AgendaView.prototype.renderSkeleton = function () {
22774        var timeGridWrapEl;
22775        var timeGridEl;
22776        this.el.addClass('fc-agenda-view').html(this.renderSkeletonHtml());
22777        this.scroller.render();
22778        timeGridWrapEl = this.scroller.el.addClass('fc-time-grid-container');
22779        timeGridEl = $('<div class="fc-time-grid">').appendTo(timeGridWrapEl);
22780        this.el.find('.fc-body > tr > td').append(timeGridWrapEl);
22781        this.timeGrid.headContainerEl = this.el.find('.fc-head-container');
22782        this.timeGrid.setElement(timeGridEl);
22783        if (this.dayGrid) {
22784            this.dayGrid.setElement(this.el.find('.fc-day-grid'));
22785            // have the day-grid extend it's coordinate area over the <hr> dividing the two grids
22786            this.dayGrid.bottomCoordPadding = this.dayGrid.el.next('hr').outerHeight();
22787        }
22788    };
22789    AgendaView.prototype.unrenderSkeleton = function () {
22790        this.timeGrid.removeElement();
22791        if (this.dayGrid) {
22792            this.dayGrid.removeElement();
22793        }
22794        this.scroller.destroy();
22795    };
22796    // Builds the HTML skeleton for the view.
22797    // The day-grid and time-grid components will render inside containers defined by this HTML.
22798    AgendaView.prototype.renderSkeletonHtml = function () {
22799        var theme = this.calendar.theme;
22800        return '' +
22801            '<table class="' + theme.getClass('tableGrid') + '">' +
22802            (this.opt('columnHeader') ?
22803                '<thead class="fc-head">' +
22804                    '<tr>' +
22805                    '<td class="fc-head-container ' + theme.getClass('widgetHeader') + '">&nbsp;</td>' +
22806                    '</tr>' +
22807                    '</thead>' :
22808                '') +
22809            '<tbody class="fc-body">' +
22810            '<tr>' +
22811            '<td class="' + theme.getClass('widgetContent') + '">' +
22812            (this.dayGrid ?
22813                '<div class="fc-day-grid"></div>' +
22814                    '<hr class="fc-divider ' + theme.getClass('widgetHeader') + '"></hr>' :
22815                '') +
22816            '</td>' +
22817            '</tr>' +
22818            '</tbody>' +
22819            '</table>';
22820    };
22821    // Generates an HTML attribute string for setting the width of the axis, if it is known
22822    AgendaView.prototype.axisStyleAttr = function () {
22823        if (this.axisWidth != null) {
22824            return 'style="width:' + this.axisWidth + 'px"';
22825        }
22826        return '';
22827    };
22828    /* Now Indicator
22829    ------------------------------------------------------------------------------------------------------------------*/
22830    AgendaView.prototype.getNowIndicatorUnit = function () {
22831        return this.timeGrid.getNowIndicatorUnit();
22832    };
22833    /* Dimensions
22834    ------------------------------------------------------------------------------------------------------------------*/
22835    // Adjusts the vertical dimensions of the view to the specified values
22836    AgendaView.prototype.updateSize = function (totalHeight, isAuto, isResize) {
22837        var eventLimit;
22838        var scrollerHeight;
22839        var scrollbarWidths;
22840        _super.prototype.updateSize.call(this, totalHeight, isAuto, isResize);
22841        // make all axis cells line up, and record the width so newly created axis cells will have it
22842        this.axisWidth = util_1.matchCellWidths(this.el.find('.fc-axis'));
22843        // hack to give the view some height prior to timeGrid's columns being rendered
22844        // TODO: separate setting height from scroller VS timeGrid.
22845        if (!this.timeGrid.colEls) {
22846            if (!isAuto) {
22847                scrollerHeight = this.computeScrollerHeight(totalHeight);
22848                this.scroller.setHeight(scrollerHeight);
22849            }
22850            return;
22851        }
22852        // set of fake row elements that must compensate when scroller has scrollbars
22853        var noScrollRowEls = this.el.find('.fc-row:not(.fc-scroller *)');
22854        // reset all dimensions back to the original state
22855        this.timeGrid.bottomRuleEl.hide(); // .show() will be called later if this <hr> is necessary
22856        this.scroller.clear(); // sets height to 'auto' and clears overflow
22857        util_1.uncompensateScroll(noScrollRowEls);
22858        // limit number of events in the all-day area
22859        if (this.dayGrid) {
22860            this.dayGrid.removeSegPopover(); // kill the "more" popover if displayed
22861            eventLimit = this.opt('eventLimit');
22862            if (eventLimit && typeof eventLimit !== 'number') {
22863                eventLimit = AGENDA_ALL_DAY_EVENT_LIMIT; // make sure "auto" goes to a real number
22864            }
22865            if (eventLimit) {
22866                this.dayGrid.limitRows(eventLimit);
22867            }
22868        }
22869        if (!isAuto) { // should we force dimensions of the scroll container?
22870            scrollerHeight = this.computeScrollerHeight(totalHeight);
22871            this.scroller.setHeight(scrollerHeight);
22872            scrollbarWidths = this.scroller.getScrollbarWidths();
22873            if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?
22874                // make the all-day and header rows lines up
22875                util_1.compensateScroll(noScrollRowEls, scrollbarWidths);
22876                // the scrollbar compensation might have changed text flow, which might affect height, so recalculate
22877                // and reapply the desired height to the scroller.
22878                scrollerHeight = this.computeScrollerHeight(totalHeight);
22879                this.scroller.setHeight(scrollerHeight);
22880            }
22881            // guarantees the same scrollbar widths
22882            this.scroller.lockOverflow(scrollbarWidths);
22883            // if there's any space below the slats, show the horizontal rule.
22884            // this won't cause any new overflow, because lockOverflow already called.
22885            if (this.timeGrid.getTotalSlatHeight() < scrollerHeight) {
22886                this.timeGrid.bottomRuleEl.show();
22887            }
22888        }
22889    };
22890    // given a desired total height of the view, returns what the height of the scroller should be
22891    AgendaView.prototype.computeScrollerHeight = function (totalHeight) {
22892        return totalHeight -
22893            util_1.subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
22894    };
22895    /* Scroll
22896    ------------------------------------------------------------------------------------------------------------------*/
22897    // Computes the initial pre-configured scroll state prior to allowing the user to change it
22898    AgendaView.prototype.computeInitialDateScroll = function () {
22899        var scrollTime = moment.duration(this.opt('scrollTime'));
22900        var top = this.timeGrid.computeTimeTop(scrollTime);
22901        // zoom can give weird floating-point values. rather scroll a little bit further
22902        top = Math.ceil(top);
22903        if (top) {
22904            top++; // to overcome top border that slots beyond the first have. looks better
22905        }
22906        return { top: top };
22907    };
22908    AgendaView.prototype.queryDateScroll = function () {
22909        return { top: this.scroller.getScrollTop() };
22910    };
22911    AgendaView.prototype.applyDateScroll = function (scroll) {
22912        if (scroll.top !== undefined) {
22913            this.scroller.setScrollTop(scroll.top);
22914        }
22915    };
22916    /* Hit Areas
22917    ------------------------------------------------------------------------------------------------------------------*/
22918    // forward all hit-related method calls to the grids (dayGrid might not be defined)
22919    AgendaView.prototype.getHitFootprint = function (hit) {
22920        // TODO: hit.component is set as a hack to identify where the hit came from
22921        return hit.component.getHitFootprint(hit);
22922    };
22923    AgendaView.prototype.getHitEl = function (hit) {
22924        // TODO: hit.component is set as a hack to identify where the hit came from
22925        return hit.component.getHitEl(hit);
22926    };
22927    /* Event Rendering
22928    ------------------------------------------------------------------------------------------------------------------*/
22929    AgendaView.prototype.executeEventRender = function (eventsPayload) {
22930        var dayEventsPayload = {};
22931        var timedEventsPayload = {};
22932        var id;
22933        var eventInstanceGroup;
22934        // separate the events into all-day and timed
22935        for (id in eventsPayload) {
22936            eventInstanceGroup = eventsPayload[id];
22937            if (eventInstanceGroup.getEventDef().isAllDay()) {
22938                dayEventsPayload[id] = eventInstanceGroup;
22939            }
22940            else {
22941                timedEventsPayload[id] = eventInstanceGroup;
22942            }
22943        }
22944        this.timeGrid.executeEventRender(timedEventsPayload);
22945        if (this.dayGrid) {
22946            this.dayGrid.executeEventRender(dayEventsPayload);
22947        }
22948    };
22949    /* Dragging/Resizing Routing
22950    ------------------------------------------------------------------------------------------------------------------*/
22951    // A returned value of `true` signals that a mock "helper" event has been rendered.
22952    AgendaView.prototype.renderDrag = function (eventFootprints, seg, isTouch) {
22953        var groups = groupEventFootprintsByAllDay(eventFootprints);
22954        var renderedHelper = false;
22955        renderedHelper = this.timeGrid.renderDrag(groups.timed, seg, isTouch);
22956        if (this.dayGrid) {
22957            renderedHelper = this.dayGrid.renderDrag(groups.allDay, seg, isTouch) || renderedHelper;
22958        }
22959        return renderedHelper;
22960    };
22961    AgendaView.prototype.renderEventResize = function (eventFootprints, seg, isTouch) {
22962        var groups = groupEventFootprintsByAllDay(eventFootprints);
22963        this.timeGrid.renderEventResize(groups.timed, seg, isTouch);
22964        if (this.dayGrid) {
22965            this.dayGrid.renderEventResize(groups.allDay, seg, isTouch);
22966        }
22967    };
22968    /* Selection
22969    ------------------------------------------------------------------------------------------------------------------*/
22970    // Renders a visual indication of a selection
22971    AgendaView.prototype.renderSelectionFootprint = function (componentFootprint) {
22972        if (!componentFootprint.isAllDay) {
22973            this.timeGrid.renderSelectionFootprint(componentFootprint);
22974        }
22975        else if (this.dayGrid) {
22976            this.dayGrid.renderSelectionFootprint(componentFootprint);
22977        }
22978    };
22979    return AgendaView;
22980}(View_1.default));
22981exports.default = AgendaView;
22982AgendaView.prototype.timeGridClass = TimeGrid_1.default;
22983AgendaView.prototype.dayGridClass = DayGrid_1.default;
22984// Will customize the rendering behavior of the AgendaView's timeGrid
22985agendaTimeGridMethods = {
22986    // Generates the HTML that will go before the day-of week header cells
22987    renderHeadIntroHtml: function () {
22988        var view = this.view;
22989        var calendar = view.calendar;
22990        var weekStart = calendar.msToUtcMoment(this.dateProfile.renderUnzonedRange.startMs, true);
22991        var weekText;
22992        if (this.opt('weekNumbers')) {
22993            weekText = weekStart.format(this.opt('smallWeekFormat'));
22994            return '' +
22995                '<th class="fc-axis fc-week-number ' + calendar.theme.getClass('widgetHeader') + '" ' + view.axisStyleAttr() + '>' +
22996                view.buildGotoAnchorHtml(// aside from link, important for matchCellWidths
22997                { date: weekStart, type: 'week', forceOff: this.colCnt > 1 }, util_1.htmlEscape(weekText) // inner HTML
22998                ) +
22999                '</th>';
23000        }
23001        else {
23002            return '<th class="fc-axis ' + calendar.theme.getClass('widgetHeader') + '" ' + view.axisStyleAttr() + '></th>';
23003        }
23004    },
23005    // Generates the HTML that goes before the bg of the TimeGrid slot area. Long vertical column.
23006    renderBgIntroHtml: function () {
23007        var view = this.view;
23008        return '<td class="fc-axis ' + view.calendar.theme.getClass('widgetContent') + '" ' + view.axisStyleAttr() + '></td>';
23009    },
23010    // Generates the HTML that goes before all other types of cells.
23011    // Affects content-skeleton, helper-skeleton, highlight-skeleton for both the time-grid and day-grid.
23012    renderIntroHtml: function () {
23013        var view = this.view;
23014        return '<td class="fc-axis" ' + view.axisStyleAttr() + '></td>';
23015    }
23016};
23017// Will customize the rendering behavior of the AgendaView's dayGrid
23018agendaDayGridMethods = {
23019    // Generates the HTML that goes before the all-day cells
23020    renderBgIntroHtml: function () {
23021        var view = this.view;
23022        return '' +
23023            '<td class="fc-axis ' + view.calendar.theme.getClass('widgetContent') + '" ' + view.axisStyleAttr() + '>' +
23024            '<span>' + // needed for matchCellWidths
23025            view.getAllDayHtml() +
23026            '</span>' +
23027            '</td>';
23028    },
23029    // Generates the HTML that goes before all other types of cells.
23030    // Affects content-skeleton, helper-skeleton, highlight-skeleton for both the time-grid and day-grid.
23031    renderIntroHtml: function () {
23032        var view = this.view;
23033        return '<td class="fc-axis" ' + view.axisStyleAttr() + '></td>';
23034    }
23035};
23036function groupEventFootprintsByAllDay(eventFootprints) {
23037    var allDay = [];
23038    var timed = [];
23039    var i;
23040    for (i = 0; i < eventFootprints.length; i++) {
23041        if (eventFootprints[i].componentFootprint.isAllDay) {
23042            allDay.push(eventFootprints[i]);
23043        }
23044        else {
23045            timed.push(eventFootprints[i]);
23046        }
23047    }
23048    return { allDay: allDay, timed: timed };
23049}
23050
23051
23052/***/ }),
23053/* 239 */
23054/***/ (function(module, exports, __webpack_require__) {
23055
23056Object.defineProperty(exports, "__esModule", { value: true });
23057var tslib_1 = __webpack_require__(2);
23058var $ = __webpack_require__(3);
23059var moment = __webpack_require__(0);
23060var util_1 = __webpack_require__(4);
23061var InteractiveDateComponent_1 = __webpack_require__(42);
23062var BusinessHourRenderer_1 = __webpack_require__(61);
23063var StandardInteractionsMixin_1 = __webpack_require__(65);
23064var DayTableMixin_1 = __webpack_require__(60);
23065var CoordCache_1 = __webpack_require__(58);
23066var UnzonedRange_1 = __webpack_require__(5);
23067var ComponentFootprint_1 = __webpack_require__(12);
23068var TimeGridEventRenderer_1 = __webpack_require__(240);
23069var TimeGridHelperRenderer_1 = __webpack_require__(241);
23070var TimeGridFillRenderer_1 = __webpack_require__(242);
23071/* A component that renders one or more columns of vertical time slots
23072----------------------------------------------------------------------------------------------------------------------*/
23073// We mixin DayTable, even though there is only a single row of days
23074// potential nice values for the slot-duration and interval-duration
23075// from largest to smallest
23076var AGENDA_STOCK_SUB_DURATIONS = [
23077    { hours: 1 },
23078    { minutes: 30 },
23079    { minutes: 15 },
23080    { seconds: 30 },
23081    { seconds: 15 }
23082];
23083var TimeGrid = /** @class */ (function (_super) {
23084    tslib_1.__extends(TimeGrid, _super);
23085    function TimeGrid(view) {
23086        var _this = _super.call(this, view) || this;
23087        _this.processOptions();
23088        return _this;
23089    }
23090    // Slices up the given span (unzoned start/end with other misc data) into an array of segments
23091    TimeGrid.prototype.componentFootprintToSegs = function (componentFootprint) {
23092        var segs = this.sliceRangeByTimes(componentFootprint.unzonedRange);
23093        var i;
23094        for (i = 0; i < segs.length; i++) {
23095            if (this.isRTL) {
23096                segs[i].col = this.daysPerRow - 1 - segs[i].dayIndex;
23097            }
23098            else {
23099                segs[i].col = segs[i].dayIndex;
23100            }
23101        }
23102        return segs;
23103    };
23104    /* Date Handling
23105    ------------------------------------------------------------------------------------------------------------------*/
23106    TimeGrid.prototype.sliceRangeByTimes = function (unzonedRange) {
23107        var segs = [];
23108        var segRange;
23109        var dayIndex;
23110        for (dayIndex = 0; dayIndex < this.daysPerRow; dayIndex++) {
23111            segRange = unzonedRange.intersect(this.dayRanges[dayIndex]);
23112            if (segRange) {
23113                segs.push({
23114                    startMs: segRange.startMs,
23115                    endMs: segRange.endMs,
23116                    isStart: segRange.isStart,
23117                    isEnd: segRange.isEnd,
23118                    dayIndex: dayIndex
23119                });
23120            }
23121        }
23122        return segs;
23123    };
23124    /* Options
23125    ------------------------------------------------------------------------------------------------------------------*/
23126    // Parses various options into properties of this object
23127    TimeGrid.prototype.processOptions = function () {
23128        var slotDuration = this.opt('slotDuration');
23129        var snapDuration = this.opt('snapDuration');
23130        var input;
23131        slotDuration = moment.duration(slotDuration);
23132        snapDuration = snapDuration ? moment.duration(snapDuration) : slotDuration;
23133        this.slotDuration = slotDuration;
23134        this.snapDuration = snapDuration;
23135        this.snapsPerSlot = slotDuration / snapDuration; // TODO: ensure an integer multiple?
23136        // might be an array value (for TimelineView).
23137        // if so, getting the most granular entry (the last one probably).
23138        input = this.opt('slotLabelFormat');
23139        if ($.isArray(input)) {
23140            input = input[input.length - 1];
23141        }
23142        this.labelFormat = input ||
23143            this.opt('smallTimeFormat'); // the computed default
23144        input = this.opt('slotLabelInterval');
23145        this.labelInterval = input ?
23146            moment.duration(input) :
23147            this.computeLabelInterval(slotDuration);
23148    };
23149    // Computes an automatic value for slotLabelInterval
23150    TimeGrid.prototype.computeLabelInterval = function (slotDuration) {
23151        var i;
23152        var labelInterval;
23153        var slotsPerLabel;
23154        // find the smallest stock label interval that results in more than one slots-per-label
23155        for (i = AGENDA_STOCK_SUB_DURATIONS.length - 1; i >= 0; i--) {
23156            labelInterval = moment.duration(AGENDA_STOCK_SUB_DURATIONS[i]);
23157            slotsPerLabel = util_1.divideDurationByDuration(labelInterval, slotDuration);
23158            if (util_1.isInt(slotsPerLabel) && slotsPerLabel > 1) {
23159                return labelInterval;
23160            }
23161        }
23162        return moment.duration(slotDuration); // fall back. clone
23163    };
23164    /* Date Rendering
23165    ------------------------------------------------------------------------------------------------------------------*/
23166    TimeGrid.prototype.renderDates = function (dateProfile) {
23167        this.dateProfile = dateProfile;
23168        this.updateDayTable();
23169        this.renderSlats();
23170        this.renderColumns();
23171    };
23172    TimeGrid.prototype.unrenderDates = function () {
23173        // this.unrenderSlats(); // don't need this because repeated .html() calls clear
23174        this.unrenderColumns();
23175    };
23176    TimeGrid.prototype.renderSkeleton = function () {
23177        var theme = this.view.calendar.theme;
23178        this.el.html('<div class="fc-bg"></div>' +
23179            '<div class="fc-slats"></div>' +
23180            '<hr class="fc-divider ' + theme.getClass('widgetHeader') + '" style="display:none"></hr>');
23181        this.bottomRuleEl = this.el.find('hr');
23182    };
23183    TimeGrid.prototype.renderSlats = function () {
23184        var theme = this.view.calendar.theme;
23185        this.slatContainerEl = this.el.find('> .fc-slats')
23186            .html(// avoids needing ::unrenderSlats()
23187        '<table class="' + theme.getClass('tableGrid') + '">' +
23188            this.renderSlatRowHtml() +
23189            '</table>');
23190        this.slatEls = this.slatContainerEl.find('tr');
23191        this.slatCoordCache = new CoordCache_1.default({
23192            els: this.slatEls,
23193            isVertical: true
23194        });
23195    };
23196    // Generates the HTML for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL.
23197    TimeGrid.prototype.renderSlatRowHtml = function () {
23198        var view = this.view;
23199        var calendar = view.calendar;
23200        var theme = calendar.theme;
23201        var isRTL = this.isRTL;
23202        var dateProfile = this.dateProfile;
23203        var html = '';
23204        var slotTime = moment.duration(+dateProfile.minTime); // wish there was .clone() for durations
23205        var slotIterator = moment.duration(0);
23206        var slotDate; // will be on the view's first day, but we only care about its time
23207        var isLabeled;
23208        var axisHtml;
23209        // Calculate the time for each slot
23210        while (slotTime < dateProfile.maxTime) {
23211            slotDate = calendar.msToUtcMoment(dateProfile.renderUnzonedRange.startMs).time(slotTime);
23212            isLabeled = util_1.isInt(util_1.divideDurationByDuration(slotIterator, this.labelInterval));
23213            axisHtml =
23214                '<td class="fc-axis fc-time ' + theme.getClass('widgetContent') + '" ' + view.axisStyleAttr() + '>' +
23215                    (isLabeled ?
23216                        '<span>' + // for matchCellWidths
23217                            util_1.htmlEscape(slotDate.format(this.labelFormat)) +
23218                            '</span>' :
23219                        '') +
23220                    '</td>';
23221            html +=
23222                '<tr data-time="' + slotDate.format('HH:mm:ss') + '"' +
23223                    (isLabeled ? '' : ' class="fc-minor"') +
23224                    '>' +
23225                    (!isRTL ? axisHtml : '') +
23226                    '<td class="' + theme.getClass('widgetContent') + '"></td>' +
23227                    (isRTL ? axisHtml : '') +
23228                    '</tr>';
23229            slotTime.add(this.slotDuration);
23230            slotIterator.add(this.slotDuration);
23231        }
23232        return html;
23233    };
23234    TimeGrid.prototype.renderColumns = function () {
23235        var dateProfile = this.dateProfile;
23236        var theme = this.view.calendar.theme;
23237        this.dayRanges = this.dayDates.map(function (dayDate) {
23238            return new UnzonedRange_1.default(dayDate.clone().add(dateProfile.minTime), dayDate.clone().add(dateProfile.maxTime));
23239        });
23240        if (this.headContainerEl) {
23241            this.headContainerEl.html(this.renderHeadHtml());
23242        }
23243        this.el.find('> .fc-bg').html('<table class="' + theme.getClass('tableGrid') + '">' +
23244            this.renderBgTrHtml(0) + // row=0
23245            '</table>');
23246        this.colEls = this.el.find('.fc-day, .fc-disabled-day');
23247        this.colCoordCache = new CoordCache_1.default({
23248            els: this.colEls,
23249            isHorizontal: true
23250        });
23251        this.renderContentSkeleton();
23252    };
23253    TimeGrid.prototype.unrenderColumns = function () {
23254        this.unrenderContentSkeleton();
23255    };
23256    /* Content Skeleton
23257    ------------------------------------------------------------------------------------------------------------------*/
23258    // Renders the DOM that the view's content will live in
23259    TimeGrid.prototype.renderContentSkeleton = function () {
23260        var cellHtml = '';
23261        var i;
23262        var skeletonEl;
23263        for (i = 0; i < this.colCnt; i++) {
23264            cellHtml +=
23265                '<td>' +
23266                    '<div class="fc-content-col">' +
23267                    '<div class="fc-event-container fc-helper-container"></div>' +
23268                    '<div class="fc-event-container"></div>' +
23269                    '<div class="fc-highlight-container"></div>' +
23270                    '<div class="fc-bgevent-container"></div>' +
23271                    '<div class="fc-business-container"></div>' +
23272                    '</div>' +
23273                    '</td>';
23274        }
23275        skeletonEl = this.contentSkeletonEl = $('<div class="fc-content-skeleton">' +
23276            '<table>' +
23277            '<tr>' + cellHtml + '</tr>' +
23278            '</table>' +
23279            '</div>');
23280        this.colContainerEls = skeletonEl.find('.fc-content-col');
23281        this.helperContainerEls = skeletonEl.find('.fc-helper-container');
23282        this.fgContainerEls = skeletonEl.find('.fc-event-container:not(.fc-helper-container)');
23283        this.bgContainerEls = skeletonEl.find('.fc-bgevent-container');
23284        this.highlightContainerEls = skeletonEl.find('.fc-highlight-container');
23285        this.businessContainerEls = skeletonEl.find('.fc-business-container');
23286        this.bookendCells(skeletonEl.find('tr')); // TODO: do this on string level
23287        this.el.append(skeletonEl);
23288    };
23289    TimeGrid.prototype.unrenderContentSkeleton = function () {
23290        if (this.contentSkeletonEl) { // defensive :(
23291            this.contentSkeletonEl.remove();
23292            this.contentSkeletonEl = null;
23293            this.colContainerEls = null;
23294            this.helperContainerEls = null;
23295            this.fgContainerEls = null;
23296            this.bgContainerEls = null;
23297            this.highlightContainerEls = null;
23298            this.businessContainerEls = null;
23299        }
23300    };
23301    // Given a flat array of segments, return an array of sub-arrays, grouped by each segment's col
23302    TimeGrid.prototype.groupSegsByCol = function (segs) {
23303        var segsByCol = [];
23304        var i;
23305        for (i = 0; i < this.colCnt; i++) {
23306            segsByCol.push([]);
23307        }
23308        for (i = 0; i < segs.length; i++) {
23309            segsByCol[segs[i].col].push(segs[i]);
23310        }
23311        return segsByCol;
23312    };
23313    // Given segments grouped by column, insert the segments' elements into a parallel array of container
23314    // elements, each living within a column.
23315    TimeGrid.prototype.attachSegsByCol = function (segsByCol, containerEls) {
23316        var col;
23317        var segs;
23318        var i;
23319        for (col = 0; col < this.colCnt; col++) { // iterate each column grouping
23320            segs = segsByCol[col];
23321            for (i = 0; i < segs.length; i++) {
23322                containerEls.eq(col).append(segs[i].el);
23323            }
23324        }
23325    };
23326    /* Now Indicator
23327    ------------------------------------------------------------------------------------------------------------------*/
23328    TimeGrid.prototype.getNowIndicatorUnit = function () {
23329        return 'minute'; // will refresh on the minute
23330    };
23331    TimeGrid.prototype.renderNowIndicator = function (date) {
23332        // HACK: if date columns not ready for some reason (scheduler)
23333        if (!this.colContainerEls) {
23334            return;
23335        }
23336        // seg system might be overkill, but it handles scenario where line needs to be rendered
23337        //  more than once because of columns with the same date (resources columns for example)
23338        var segs = this.componentFootprintToSegs(new ComponentFootprint_1.default(new UnzonedRange_1.default(date, date.valueOf() + 1), // protect against null range
23339        false // all-day
23340        ));
23341        var top = this.computeDateTop(date, date);
23342        var nodes = [];
23343        var i;
23344        // render lines within the columns
23345        for (i = 0; i < segs.length; i++) {
23346            nodes.push($('<div class="fc-now-indicator fc-now-indicator-line"></div>')
23347                .css('top', top)
23348                .appendTo(this.colContainerEls.eq(segs[i].col))[0]);
23349        }
23350        // render an arrow over the axis
23351        if (segs.length > 0) { // is the current time in view?
23352            nodes.push($('<div class="fc-now-indicator fc-now-indicator-arrow"></div>')
23353                .css('top', top)
23354                .appendTo(this.el.find('.fc-content-skeleton'))[0]);
23355        }
23356        this.nowIndicatorEls = $(nodes);
23357    };
23358    TimeGrid.prototype.unrenderNowIndicator = function () {
23359        if (this.nowIndicatorEls) {
23360            this.nowIndicatorEls.remove();
23361            this.nowIndicatorEls = null;
23362        }
23363    };
23364    /* Coordinates
23365    ------------------------------------------------------------------------------------------------------------------*/
23366    TimeGrid.prototype.updateSize = function (totalHeight, isAuto, isResize) {
23367        _super.prototype.updateSize.call(this, totalHeight, isAuto, isResize);
23368        this.slatCoordCache.build();
23369        if (isResize) {
23370            this.updateSegVerticals([].concat(this.eventRenderer.getSegs(), this.businessSegs || []));
23371        }
23372    };
23373    TimeGrid.prototype.getTotalSlatHeight = function () {
23374        return this.slatContainerEl.outerHeight();
23375    };
23376    // Computes the top coordinate, relative to the bounds of the grid, of the given date.
23377    // `ms` can be a millisecond UTC time OR a UTC moment.
23378    // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight.
23379    TimeGrid.prototype.computeDateTop = function (ms, startOfDayDate) {
23380        return this.computeTimeTop(moment.duration(ms - startOfDayDate.clone().stripTime()));
23381    };
23382    // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration).
23383    TimeGrid.prototype.computeTimeTop = function (time) {
23384        var len = this.slatEls.length;
23385        var dateProfile = this.dateProfile;
23386        var slatCoverage = (time - dateProfile.minTime) / this.slotDuration; // floating-point value of # of slots covered
23387        var slatIndex;
23388        var slatRemainder;
23389        // compute a floating-point number for how many slats should be progressed through.
23390        // from 0 to number of slats (inclusive)
23391        // constrained because minTime/maxTime might be customized.
23392        slatCoverage = Math.max(0, slatCoverage);
23393        slatCoverage = Math.min(len, slatCoverage);
23394        // an integer index of the furthest whole slat
23395        // from 0 to number slats (*exclusive*, so len-1)
23396        slatIndex = Math.floor(slatCoverage);
23397        slatIndex = Math.min(slatIndex, len - 1);
23398        // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition.
23399        // could be 1.0 if slatCoverage is covering *all* the slots
23400        slatRemainder = slatCoverage - slatIndex;
23401        return this.slatCoordCache.getTopPosition(slatIndex) +
23402            this.slatCoordCache.getHeight(slatIndex) * slatRemainder;
23403    };
23404    // Refreshes the CSS top/bottom coordinates for each segment element.
23405    // Works when called after initial render, after a window resize/zoom for example.
23406    TimeGrid.prototype.updateSegVerticals = function (segs) {
23407        this.computeSegVerticals(segs);
23408        this.assignSegVerticals(segs);
23409    };
23410    // For each segment in an array, computes and assigns its top and bottom properties
23411    TimeGrid.prototype.computeSegVerticals = function (segs) {
23412        var eventMinHeight = this.opt('agendaEventMinHeight');
23413        var i;
23414        var seg;
23415        var dayDate;
23416        for (i = 0; i < segs.length; i++) {
23417            seg = segs[i];
23418            dayDate = this.dayDates[seg.dayIndex];
23419            seg.top = this.computeDateTop(seg.startMs, dayDate);
23420            seg.bottom = Math.max(seg.top + eventMinHeight, this.computeDateTop(seg.endMs, dayDate));
23421        }
23422    };
23423    // Given segments that already have their top/bottom properties computed, applies those values to
23424    // the segments' elements.
23425    TimeGrid.prototype.assignSegVerticals = function (segs) {
23426        var i;
23427        var seg;
23428        for (i = 0; i < segs.length; i++) {
23429            seg = segs[i];
23430            seg.el.css(this.generateSegVerticalCss(seg));
23431        }
23432    };
23433    // Generates an object with CSS properties for the top/bottom coordinates of a segment element
23434    TimeGrid.prototype.generateSegVerticalCss = function (seg) {
23435        return {
23436            top: seg.top,
23437            bottom: -seg.bottom // flipped because needs to be space beyond bottom edge of event container
23438        };
23439    };
23440    /* Hit System
23441    ------------------------------------------------------------------------------------------------------------------*/
23442    TimeGrid.prototype.prepareHits = function () {
23443        this.colCoordCache.build();
23444        this.slatCoordCache.build();
23445    };
23446    TimeGrid.prototype.releaseHits = function () {
23447        this.colCoordCache.clear();
23448        // NOTE: don't clear slatCoordCache because we rely on it for computeTimeTop
23449    };
23450    TimeGrid.prototype.queryHit = function (leftOffset, topOffset) {
23451        var snapsPerSlot = this.snapsPerSlot;
23452        var colCoordCache = this.colCoordCache;
23453        var slatCoordCache = this.slatCoordCache;
23454        if (colCoordCache.isLeftInBounds(leftOffset) && slatCoordCache.isTopInBounds(topOffset)) {
23455            var colIndex = colCoordCache.getHorizontalIndex(leftOffset);
23456            var slatIndex = slatCoordCache.getVerticalIndex(topOffset);
23457            if (colIndex != null && slatIndex != null) {
23458                var slatTop = slatCoordCache.getTopOffset(slatIndex);
23459                var slatHeight = slatCoordCache.getHeight(slatIndex);
23460                var partial = (topOffset - slatTop) / slatHeight; // floating point number between 0 and 1
23461                var localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat
23462                var snapIndex = slatIndex * snapsPerSlot + localSnapIndex;
23463                var snapTop = slatTop + (localSnapIndex / snapsPerSlot) * slatHeight;
23464                var snapBottom = slatTop + ((localSnapIndex + 1) / snapsPerSlot) * slatHeight;
23465                return {
23466                    col: colIndex,
23467                    snap: snapIndex,
23468                    component: this,
23469                    left: colCoordCache.getLeftOffset(colIndex),
23470                    right: colCoordCache.getRightOffset(colIndex),
23471                    top: snapTop,
23472                    bottom: snapBottom
23473                };
23474            }
23475        }
23476    };
23477    TimeGrid.prototype.getHitFootprint = function (hit) {
23478        var start = this.getCellDate(0, hit.col); // row=0
23479        var time = this.computeSnapTime(hit.snap); // pass in the snap-index
23480        var end;
23481        start.time(time);
23482        end = start.clone().add(this.snapDuration);
23483        return new ComponentFootprint_1.default(new UnzonedRange_1.default(start, end), false // all-day?
23484        );
23485    };
23486    // Given a row number of the grid, representing a "snap", returns a time (Duration) from its start-of-day
23487    TimeGrid.prototype.computeSnapTime = function (snapIndex) {
23488        return moment.duration(this.dateProfile.minTime + this.snapDuration * snapIndex);
23489    };
23490    TimeGrid.prototype.getHitEl = function (hit) {
23491        return this.colEls.eq(hit.col);
23492    };
23493    /* Event Drag Visualization
23494    ------------------------------------------------------------------------------------------------------------------*/
23495    // Renders a visual indication of an event being dragged over the specified date(s).
23496    // A returned value of `true` signals that a mock "helper" event has been rendered.
23497    TimeGrid.prototype.renderDrag = function (eventFootprints, seg, isTouch) {
23498        var i;
23499        if (seg) { // if there is event information for this drag, render a helper event
23500            if (eventFootprints.length) {
23501                this.helperRenderer.renderEventDraggingFootprints(eventFootprints, seg, isTouch);
23502                // signal that a helper has been rendered
23503                return true;
23504            }
23505        }
23506        else { // otherwise, just render a highlight
23507            for (i = 0; i < eventFootprints.length; i++) {
23508                this.renderHighlight(eventFootprints[i].componentFootprint);
23509            }
23510        }
23511    };
23512    // Unrenders any visual indication of an event being dragged
23513    TimeGrid.prototype.unrenderDrag = function () {
23514        this.unrenderHighlight();
23515        this.helperRenderer.unrender();
23516    };
23517    /* Event Resize Visualization
23518    ------------------------------------------------------------------------------------------------------------------*/
23519    // Renders a visual indication of an event being resized
23520    TimeGrid.prototype.renderEventResize = function (eventFootprints, seg, isTouch) {
23521        this.helperRenderer.renderEventResizingFootprints(eventFootprints, seg, isTouch);
23522    };
23523    // Unrenders any visual indication of an event being resized
23524    TimeGrid.prototype.unrenderEventResize = function () {
23525        this.helperRenderer.unrender();
23526    };
23527    /* Selection
23528    ------------------------------------------------------------------------------------------------------------------*/
23529    // Renders a visual indication of a selection. Overrides the default, which was to simply render a highlight.
23530    TimeGrid.prototype.renderSelectionFootprint = function (componentFootprint) {
23531        if (this.opt('selectHelper')) { // this setting signals that a mock helper event should be rendered
23532            this.helperRenderer.renderComponentFootprint(componentFootprint);
23533        }
23534        else {
23535            this.renderHighlight(componentFootprint);
23536        }
23537    };
23538    // Unrenders any visual indication of a selection
23539    TimeGrid.prototype.unrenderSelection = function () {
23540        this.helperRenderer.unrender();
23541        this.unrenderHighlight();
23542    };
23543    return TimeGrid;
23544}(InteractiveDateComponent_1.default));
23545exports.default = TimeGrid;
23546TimeGrid.prototype.eventRendererClass = TimeGridEventRenderer_1.default;
23547TimeGrid.prototype.businessHourRendererClass = BusinessHourRenderer_1.default;
23548TimeGrid.prototype.helperRendererClass = TimeGridHelperRenderer_1.default;
23549TimeGrid.prototype.fillRendererClass = TimeGridFillRenderer_1.default;
23550StandardInteractionsMixin_1.default.mixInto(TimeGrid);
23551DayTableMixin_1.default.mixInto(TimeGrid);
23552
23553
23554/***/ }),
23555/* 240 */
23556/***/ (function(module, exports, __webpack_require__) {
23557
23558Object.defineProperty(exports, "__esModule", { value: true });
23559var tslib_1 = __webpack_require__(2);
23560var util_1 = __webpack_require__(4);
23561var EventRenderer_1 = __webpack_require__(44);
23562/*
23563Only handles foreground segs.
23564Does not own rendering. Use for low-level util methods by TimeGrid.
23565*/
23566var TimeGridEventRenderer = /** @class */ (function (_super) {
23567    tslib_1.__extends(TimeGridEventRenderer, _super);
23568    function TimeGridEventRenderer(timeGrid, fillRenderer) {
23569        var _this = _super.call(this, timeGrid, fillRenderer) || this;
23570        _this.timeGrid = timeGrid;
23571        return _this;
23572    }
23573    TimeGridEventRenderer.prototype.renderFgSegs = function (segs) {
23574        this.renderFgSegsIntoContainers(segs, this.timeGrid.fgContainerEls);
23575    };
23576    // Given an array of foreground segments, render a DOM element for each, computes position,
23577    // and attaches to the column inner-container elements.
23578    TimeGridEventRenderer.prototype.renderFgSegsIntoContainers = function (segs, containerEls) {
23579        var segsByCol;
23580        var col;
23581        segsByCol = this.timeGrid.groupSegsByCol(segs);
23582        for (col = 0; col < this.timeGrid.colCnt; col++) {
23583            this.updateFgSegCoords(segsByCol[col]);
23584        }
23585        this.timeGrid.attachSegsByCol(segsByCol, containerEls);
23586    };
23587    TimeGridEventRenderer.prototype.unrenderFgSegs = function () {
23588        if (this.fgSegs) { // hack
23589            this.fgSegs.forEach(function (seg) {
23590                seg.el.remove();
23591            });
23592        }
23593    };
23594    // Computes a default event time formatting string if `timeFormat` is not explicitly defined
23595    TimeGridEventRenderer.prototype.computeEventTimeFormat = function () {
23596        return this.opt('noMeridiemTimeFormat'); // like "6:30" (no AM/PM)
23597    };
23598    // Computes a default `displayEventEnd` value if one is not expliclty defined
23599    TimeGridEventRenderer.prototype.computeDisplayEventEnd = function () {
23600        return true;
23601    };
23602    // Renders the HTML for a single event segment's default rendering
23603    TimeGridEventRenderer.prototype.fgSegHtml = function (seg, disableResizing) {
23604        var view = this.view;
23605        var calendar = view.calendar;
23606        var componentFootprint = seg.footprint.componentFootprint;
23607        var isAllDay = componentFootprint.isAllDay;
23608        var eventDef = seg.footprint.eventDef;
23609        var isDraggable = view.isEventDefDraggable(eventDef);
23610        var isResizableFromStart = !disableResizing && seg.isStart && view.isEventDefResizableFromStart(eventDef);
23611        var isResizableFromEnd = !disableResizing && seg.isEnd && view.isEventDefResizableFromEnd(eventDef);
23612        var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd);
23613        var skinCss = util_1.cssToStr(this.getSkinCss(eventDef));
23614        var timeText;
23615        var fullTimeText; // more verbose time text. for the print stylesheet
23616        var startTimeText; // just the start time text
23617        classes.unshift('fc-time-grid-event', 'fc-v-event');
23618        // if the event appears to span more than one day...
23619        if (view.isMultiDayRange(componentFootprint.unzonedRange)) {
23620            // Don't display time text on segments that run entirely through a day.
23621            // That would appear as midnight-midnight and would look dumb.
23622            // Otherwise, display the time text for the *segment's* times (like 6pm-midnight or midnight-10am)
23623            if (seg.isStart || seg.isEnd) {
23624                var zonedStart = calendar.msToMoment(seg.startMs);
23625                var zonedEnd = calendar.msToMoment(seg.endMs);
23626                timeText = this._getTimeText(zonedStart, zonedEnd, isAllDay);
23627                fullTimeText = this._getTimeText(zonedStart, zonedEnd, isAllDay, 'LT');
23628                startTimeText = this._getTimeText(zonedStart, zonedEnd, isAllDay, null, false); // displayEnd=false
23629            }
23630        }
23631        else {
23632            // Display the normal time text for the *event's* times
23633            timeText = this.getTimeText(seg.footprint);
23634            fullTimeText = this.getTimeText(seg.footprint, 'LT');
23635            startTimeText = this.getTimeText(seg.footprint, null, false); // displayEnd=false
23636        }
23637        return '<a class="' + classes.join(' ') + '"' +
23638            (eventDef.url ?
23639                ' href="' + util_1.htmlEscape(eventDef.url) + '"' :
23640                '') +
23641            (skinCss ?
23642                ' style="' + skinCss + '"' :
23643                '') +
23644            '>' +
23645            '<div class="fc-content">' +
23646            (timeText ?
23647                '<div class="fc-time"' +
23648                    ' data-start="' + util_1.htmlEscape(startTimeText) + '"' +
23649                    ' data-full="' + util_1.htmlEscape(fullTimeText) + '"' +
23650                    '>' +
23651                    '<span>' + util_1.htmlEscape(timeText) + '</span>' +
23652                    '</div>' :
23653                '') +
23654            (eventDef.title ?
23655                '<div class="fc-title">' +
23656                    util_1.htmlEscape(eventDef.title) +
23657                    '</div>' :
23658                '') +
23659            '</div>' +
23660            '<div class="fc-bg"></div>' +
23661            /* TODO: write CSS for this
23662            (isResizableFromStart ?
23663              '<div class="fc-resizer fc-start-resizer"></div>' :
23664              ''
23665              ) +
23666            */
23667            (isResizableFromEnd ?
23668                '<div class="fc-resizer fc-end-resizer"></div>' :
23669                '') +
23670            '</a>';
23671    };
23672    // Given segments that are assumed to all live in the *same column*,
23673    // compute their verical/horizontal coordinates and assign to their elements.
23674    TimeGridEventRenderer.prototype.updateFgSegCoords = function (segs) {
23675        this.timeGrid.computeSegVerticals(segs); // horizontals relies on this
23676        this.computeFgSegHorizontals(segs); // compute horizontal coordinates, z-index's, and reorder the array
23677        this.timeGrid.assignSegVerticals(segs);
23678        this.assignFgSegHorizontals(segs);
23679    };
23680    // Given an array of segments that are all in the same column, set
23680s the backwardCoord and forwardCoord on each.
23681    // NOTE: Also reorders the given array by date!
23682    TimeGridEventRenderer.prototype.computeFgSegHorizontals = function (segs) {
23683        var levels;
23684        var level0;
23685        var i;
23686        this.sortEventSegs(segs); // order by certain criteria
23687        levels = buildSlotSegLevels(segs);
23688        computeForwardSlotSegs(levels);
23689        if ((level0 = levels[0])) {
23690            for (i = 0; i < level0.length; i++) {
23691                computeSlotSegPressures(level0[i]);
23692            }
23693            for (i = 0; i < level0.length; i++) {
23694                this.computeFgSegForwardBack(level0[i], 0, 0);
23695            }
23696        }
23697    };
23698    // Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range
23699    // from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and
23700    // seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left.
23701    //
23702    // The segment might be part of a "series", which means consecutive segments with the same pressure
23703    // who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of
23704    // segments behind this one in the current series, and `seriesBackwardCoord` is the starting
23705    // coordinate of the first segment in the series.
23706    TimeGridEventRenderer.prototype.computeFgSegForwardBack = function (seg, seriesBackwardPressure, seriesBackwardCoord) {
23707        var forwardSegs = seg.forwardSegs;
23708        var i;
23709        if (seg.forwardCoord === undefined) { // not already computed
23710            if (!forwardSegs.length) {
23711                // if there are no forward segments, this segment should butt up against the edge
23712                seg.forwardCoord = 1;
23713            }
23714            else {
23715                // sort highest pressure first
23716                this.sortForwardSegs(forwardSegs);
23717                // this segment's forwardCoord will be calculated from the backwardCoord of the
23718                // highest-pressure forward segment.
23719                this.computeFgSegForwardBack(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord);
23720                seg.forwardCoord = forwardSegs[0].backwardCoord;
23721            }
23722            // calculate the backwardCoord from the forwardCoord. consider the series
23723            seg.backwardCoord = seg.forwardCoord -
23724                (seg.forwardCoord - seriesBackwardCoord) / // available width for series
23725                    (seriesBackwardPressure + 1); // # of segments in the series
23726            // use this segment's coordinates to computed the coordinates of the less-pressurized
23727            // forward segments
23728            for (i = 0; i < forwardSegs.length; i++) {
23729                this.computeFgSegForwardBack(forwardSegs[i], 0, seg.forwardCoord);
23730            }
23731        }
23732    };
23733    TimeGridEventRenderer.prototype.sortForwardSegs = function (forwardSegs) {
23734        forwardSegs.sort(util_1.proxy(this, 'compareForwardSegs'));
23735    };
23736    // A cmp function for determining which forward segment to rely on more when computing coordinates.
23737    TimeGridEventRenderer.prototype.compareForwardSegs = function (seg1, seg2) {
23738        // put higher-pressure first
23739        return seg2.forwardPressure - seg1.forwardPressure ||
23740            // put segments that are closer to initial edge first (and favor ones with no coords yet)
23741            (seg1.backwardCoord || 0) - (seg2.backwardCoord || 0) ||
23742            // do normal sorting...
23743            this.compareEventSegs(seg1, seg2);
23744    };
23745    // Given foreground event segments that have already had their position coordinates computed,
23746    // assigns position-related CSS values to their elements.
23747    TimeGridEventRenderer.prototype.assignFgSegHorizontals = function (segs) {
23748        var i;
23749        var seg;
23750        for (i = 0; i < segs.length; i++) {
23751            seg = segs[i];
23752            seg.el.css(this.generateFgSegHorizontalCss(seg));
23753            // if the event is short that the title will be cut off,
23754            // attach a className that condenses the title into the time area.
23755            if (seg.footprint.eventDef.title && seg.bottom - seg.top < 30) {
23756                seg.el.addClass('fc-short'); // TODO: "condensed" is a better name
23757            }
23758        }
23759    };
23760    // Generates an object with CSS properties/values that should be applied to an event segment element.
23761    // Contains important positioning-related properties that should be applied to any event element, customized or not.
23762    TimeGridEventRenderer.prototype.generateFgSegHorizontalCss = function (seg) {
23763        var shouldOverlap = this.opt('slotEventOverlap');
23764        var backwardCoord = seg.backwardCoord; // the left side if LTR. the right side if RTL. floating-point
23765        var forwardCoord = seg.forwardCoord; // the right side if LTR. the left side if RTL. floating-point
23766        var props = this.timeGrid.generateSegVerticalCss(seg); // get top/bottom first
23767        var isRTL = this.timeGrid.isRTL;
23768        var left; // amount of space from left edge, a fraction of the total width
23769        var right; // amount of space from right edge, a fraction of the total width
23770        if (shouldOverlap) {
23771            // double the width, but don't go beyond the maximum forward coordinate (1.0)
23772            forwardCoord = Math.min(1, backwardCoord + (forwardCoord - backwardCoord) * 2);
23773        }
23774        if (isRTL) {
23775            left = 1 - forwardCoord;
23776            right = backwardCoord;
23777        }
23778        else {
23779            left = backwardCoord;
23780            right = 1 - forwardCoord;
23781        }
23782        props.zIndex = seg.level + 1; // convert from 0-base to 1-based
23783        props.left = left * 100 + '%';
23784        props.right = right * 100 + '%';
23785        if (shouldOverlap && seg.forwardPressure) {
23786            // add padding to the edge so that forward stacked events don't cover the resizer's icon
23787            props[isRTL ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width
23788        }
23789        return props;
23790    };
23791    return TimeGridEventRenderer;
23792}(EventRenderer_1.default));
23793exports.default = TimeGridEventRenderer;
23794// Builds an array of segments "levels". The first level will be the leftmost tier of segments if the calendar is
23795// left-to-right, or the rightmost if the calendar is right-to-left. Assumes the segments are already ordered by date.
23796function buildSlotSegLevels(segs) {
23797    var levels = [];
23798    var i;
23799    var seg;
23800    var j;
23801    for (i = 0; i < segs.length; i++) {
23802        seg = segs[i];
23803        // go through all the levels and stop on the first level where there are no collisions
23804        for (j = 0; j < levels.length; j++) {
23805            if (!computeSlotSegCollisions(seg, levels[j]).length) {
23806                break;
23807            }
23808        }
23809        seg.level = j;
23810        (levels[j] || (levels[j] = [])).push(seg);
23811    }
23812    return levels;
23813}
23814// For every segment, figure out the other segments that are in subsequent
23815// levels that also occupy the same vertical space. Accumulate in seg.forwardSegs
23816function computeForwardSlotSegs(levels) {
23817    var i;
23818    var level;
23819    var j;
23820    var seg;
23821    var k;
23822    for (i = 0; i < levels.length; i++) {
23823        level = levels[i];
23824        for (j = 0; j < level.length; j++) {
23825            seg = level[j];
23826            seg.forwardSegs = [];
23827            for (k = i + 1; k < levels.length; k++) {
23828                computeSlotSegCollisions(seg, levels[k], seg.forwardSegs);
23829            }
23830        }
23831    }
23832}
23833// Figure out which path forward (via seg.forwardSegs) results in the longest path until
23834// the furthest edge is reached. The number of segments in this path will be seg.forwardPressure
23835function computeSlotSegPressures(seg) {
23836    var forwardSegs = seg.forwardSegs;
23837    var forwardPressure = 0;
23838    var i;
23839    var forwardSeg;
23840    if (seg.forwardPressure === undefined) { // not already computed
23841        for (i = 0; i < forwardSegs.length; i++) {
23842            forwardSeg = forwardSegs[i];
23843            // figure out the child's maximum forward path
23844            computeSlotSegPressures(forwardSeg);
23845            // either use the existing maximum, or use the child's forward pressure
23846            // plus one (for the forwardSeg itself)
23847            forwardPressure = Math.max(forwardPressure, 1 + forwardSeg.forwardPressure);
23848        }
23849        seg.forwardPressure = forwardPressure;
23850    }
23851}
23852// Find all the segments in `otherSegs` that vertically collide with `seg`.
23853// Append into an optionally-supplied `results` array and return.
23854function computeSlotSegCollisions(seg, otherSegs, results) {
23855    if (results === void 0) { results = []; }
23856    for (var i = 0; i < otherSegs.length; i++) {
23857        if (isSlotSegCollision(seg, otherSegs[i])) {
23858            results.push(otherSegs[i]);
23859        }
23860    }
23861    return results;
23862}
23863// Do these segments occupy the same vertical space?
23864function isSlotSegCollision(seg1, seg2) {
23865    return seg1.bottom > seg2.top && seg1.top < seg2.bottom;
23866}
23867
23868
23869/***/ }),
23870/* 241 */
23871/***/ (function(module, exports, __webpack_require__) {
23872
23873Object.defineProperty(exports, "__esModule", { value: true });
23874var tslib_1 = __webpack_require__(2);
23875var $ = __webpack_require__(3);
23876var HelperRenderer_1 = __webpack_require__(63);
23877var TimeGridHelperRenderer = /** @class */ (function (_super) {
23878    tslib_1.__extends(TimeGridHelperRenderer, _super);
23879    function TimeGridHelperRenderer() {
23880        return _super !== null && _super.apply(this, arguments) || this;
23881    }
23882    TimeGridHelperRenderer.prototype.renderSegs = function (segs, sourceSeg) {
23883        var helperNodes = [];
23884        var i;
23885        var seg;
23886        var sourceEl;
23887        // TODO: not good to call eventRenderer this way
23888        this.eventRenderer.renderFgSegsIntoContainers(segs, this.component.helperContainerEls);
23889        // Try to make the segment that is in the same row as sourceSeg look the same
23890        for (i = 0; i < segs.length; i++) {
23891            seg = segs[i];
23892            if (sourceSeg && sourceSeg.col === seg.col) {
23893                sourceEl = sourceSeg.el;
23894                seg.el.css({
23895                    left: sourceEl.css('left'),
23896                    right: sourceEl.css('right'),
23897                    'margin-left': sourceEl.css('margin-left'),
23898                    'margin-right': sourceEl.css('margin-right')
23899                });
23900            }
23901            helperNodes.push(seg.el[0]);
23902        }
23903        return $(helperNodes); // must return the elements rendered
23904    };
23905    return TimeGridHelperRenderer;
23906}(HelperRenderer_1.default));
23907exports.default = TimeGridHelperRenderer;
23908
23909
23910/***/ }),
23911/* 242 */
23912/***/ (function(module, exports, __webpack_require__) {
23913
23914Object.defineProperty(exports, "__esModule", { value: true });
23915var tslib_1 = __webpack_require__(2);
23916var FillRenderer_1 = __webpack_require__(62);
23917var TimeGridFillRenderer = /** @class */ (function (_super) {
23918    tslib_1.__extends(TimeGridFillRenderer, _super);
23919    function TimeGridFillRenderer() {
23920        return _super !== null && _super.apply(this, arguments) || this;
23921    }
23922    TimeGridFillRenderer.prototype.attachSegEls = function (type, segs) {
23923        var timeGrid = this.component;
23924        var containerEls;
23925        // TODO: more efficient lookup
23926        if (type === 'bgEvent') {
23927            containerEls = timeGrid.bgContainerEls;
23928        }
23929        else if (type === 'businessHours') {
23930            containerEls = timeGrid.businessContainerEls;
23931        }
23932        else if (type === 'highlight') {
23933            containerEls = timeGrid.highlightContainerEls;
23934        }
23935        timeGrid.updateSegVerticals(segs);
23936        timeGrid.attachSegsByCol(timeGrid.groupSegsByCol(segs), containerEls);
23937        return segs.map(function (seg) {
23938            return seg.el[0];
23939        });
23940    };
23941    return TimeGridFillRenderer;
23942}(FillRenderer_1.default));
23943exports.default = TimeGridFillRenderer;
23944
23945
23946/***/ }),
23947/* 243 */
23948/***/ (function(module, exports, __webpack_require__) {
23949
23950Object.defineProperty(exports, "__esModule", { value: true });
23951var tslib_1 = __webpack_require__(2);
23952var $ = __webpack_require__(3);
23953var util_1 = __webpack_require__(4);
23954var EventRenderer_1 = __webpack_require__(44);
23955/* Event-rendering methods for the DayGrid class
23956----------------------------------------------------------------------------------------------------------------------*/
23957var DayGridEventRenderer = /** @class */ (function (_super) {
23958    tslib_1.__extends(DayGridEventRenderer, _super);
23959    function DayGridEventRenderer(dayGrid, fillRenderer) {
23960        var _this = _super.call(this, dayGrid, fillRenderer) || this;
23961        _this.dayGrid = dayGrid;
23962        return _this;
23963    }
23964    DayGridEventRenderer.prototype.renderBgRanges = function (eventRanges) {
23965        // don't render timed background events
23966        eventRanges = $.grep(eventRanges, function (eventRange) {
23967            return eventRange.eventDef.isAllDay();
23968        });
23969        _super.prototype.renderBgRanges.call(this, eventRanges);
23970    };
23971    // Renders the given foreground event segments onto the grid
23972    DayGridEventRenderer.prototype.renderFgSegs = function (segs) {
23973        var rowStructs = this.rowStructs = this.renderSegRows(segs);
23974        // append to each row's content skeleton
23975        this.dayGrid.rowEls.each(function (i, rowNode) {
23976            $(rowNode).find('.fc-content-skeleton > table').append(rowStructs[i].tbodyEl);
23977        });
23978    };
23979    // Unrenders all currently rendered foreground event segments
23980    DayGridEventRenderer.prototype.unrenderFgSegs = function () {
23981        var rowStructs = this.rowStructs || [];
23982        var rowStruct;
23983        while ((rowStruct = rowStructs.pop())) {
23984            rowStruct.tbodyEl.remove();
23985        }
23986        this.rowStructs = null;
23987    };
23988    // Uses the given events array to generate <tbody> elements that should be appended to each row's content skeleton.
23989    // Returns an array of rowStruct objects (see the bottom of `renderSegRow`).
23990    // PRECONDITION: each segment shoud already have a rendered and assigned `.el`
23991    DayGridEventRenderer.prototype.renderSegRows = function (segs) {
23992        var rowStructs = [];
23993        var segRows;
23994        var row;
23995        segRows = this.groupSegRows(segs); // group into nested arrays
23996        // iterate each row of segment groupings
23997        for (row = 0; row < segRows.length; row++) {
23998            rowStructs.push(this.renderSegRow(row, segRows[row]));
23999        }
24000        return rowStructs;
24001    };
24002    // Given a row # and an array of segments all in the same row, render a <tbody> element, a skeleton that contains
24003    // the segments. Returns object with a bunch of internal data about how the render was calculated.
24004    // NOTE: modifies rowSegs
24005    DayGridEventRenderer.prototype.renderSegRow = function (row, rowSegs) {
24006        var colCnt = this.dayGrid.colCnt;
24007        var segLevels = this.buildSegLevels(rowSegs); // group into sub-arrays of levels
24008        var levelCnt = Math.max(1, segLevels.length); // ensure at least one level
24009        var tbody = $('<tbody>');
24010        var segMatrix = []; // lookup for which segments are rendered into which level+col cells
24011        var cellMatrix = []; // lookup for all <td> elements of the level+col matrix
24012        var loneCellMatrix = []; // lookup for <td> elements that only take up a single column
24013        var i;
24014        var levelSegs;
24015        var col;
24016        var tr;
24017        var j;
24018        var seg;
24019        var td;
24020        // populates empty cells from the current column (`col`) to `endCol`
24021        function emptyCellsUntil(endCol) {
24022            while (col < endCol) {
24023                // try to grab a cell from the level above and extend its rowspan. otherwise, create a fresh cell
24024                td = (loneCellMatrix[i - 1] || [])[col];
24025                if (td) {
24026                    td.attr('rowspan', parseInt(td.attr('rowspan') || 1, 10) + 1);
24027                }
24028                else {
24029                    td = $('<td>');
24030                    tr.append(td);
24031                }
24032                cellMatrix[i][col] = td;
24033                loneCellMatrix[i][col] = td;
24034                col++;
24035            }
24036        }
24037        for (i = 0; i < levelCnt; i++) { // iterate through all levels
24038            levelSegs = segLevels[i];
24039            col = 0;
24040            tr = $('<tr>');
24041            segMatrix.push([]);
24042            cellMatrix.push([]);
24043            loneCellMatrix.push([]);
24044            // levelCnt might be 1 even though there are no actual levels. protect against this.
24045            // this single empty row is useful for styling.
24046            if (levelSegs) {
24047                for (j = 0; j < levelSegs.length; j++) { // iterate through segments in level
24048                    seg = levelSegs[j];
24049                    emptyCellsUntil(seg.leftCol);
24050                    // create a container that occupies or more columns. append the event element.
24051                    td = $('<td class="fc-event-container">').append(seg.el);
24052                    if (seg.leftCol !== seg.rightCol) {
24053                        td.attr('colspan', seg.rightCol - seg.leftCol + 1);
24054                    }
24055                    else { // a single-column segment
24056                        loneCellMatrix[i][col] = td;
24057                    }
24058                    while (col <= seg.rightCol) {
24059                        cellMatrix[i][col] = td;
24060                        segMatrix[i][col] = seg;
24061                        col++;
24062                    }
24063                    tr.append(td);
24064                }
24065            }
24066            emptyCellsUntil(colCnt); // finish off the row
24067            this.dayGrid.bookendCells(tr);
24068            tbody.append(tr);
24069        }
24070        return {
24071            row: row,
24072            tbodyEl: tbody,
24073            cellMatrix: cellMatrix,
24074            segMatrix: segMatrix,
24075            segLevels: segLevels,
24076            segs: rowSegs
24077        };
24078    };
24079    // Stacks a flat array of segments, which are all assumed to be in the same row, into subarrays of vertical levels.
24080    // NOTE: modifies segs
24081    DayGridEventRenderer.prototype.buildSegLevels = function (segs) {
24082        var levels = [];
24083        var i;
24084        var seg;
24085        var j;
24086        // Give preference to elements with certain criteria, so they have
24087        // a chance to be closer to the top.
24088        this.sortEventSegs(segs);
24089        for (i = 0; i < segs.length; i++) {
24090            seg = segs[i];
24091            // loop through levels, starting with the topmost, until the segment doesn't collide with other segments
24092            for (j = 0; j < levels.length; j++) {
24093                if (!isDaySegCollision(seg, levels[j])) {
24094                    break;
24095                }
24096            }
24097            // `j` now holds the desired subrow index
24098            seg.level = j;
24099            // create new level array if needed and append segment
24100            (levels[j] || (levels[j] = [])).push(seg);
24101        }
24102        // order segments left-to-right. very important if calendar is RTL
24103        for (j = 0; j < levels.length; j++) {
24104            levels[j].sort(compareDaySegCols);
24105        }
24106        return levels;
24107    };
24108    // Given a flat array of segments, return an array of sub-arrays, grouped by each segment's row
24109    DayGridEventRenderer.prototype.groupSegRows = function (segs) {
24110        var segRows = [];
24111        var i;
24112        for (i = 0; i < this.dayGrid.rowCnt; i++) {
24113            segRows.push([]);
24114        }
24115        for (i = 0; i < segs.length; i++) {
24116            segRows[segs[i].row].push(segs[i]);
24117        }
24118        return segRows;
24119    };
24120    // Computes a default event time formatting string if `timeFormat` is not explicitly defined
24121    DayGridEventRenderer.prototype.computeEventTimeFormat = function () {
24122        return this.opt('extraSmallTimeFormat'); // like "6p" or "6:30p"
24123    };
24124    // Computes a default `displayEventEnd` value if one is not expliclty defined
24125    DayGridEventRenderer.prototype.computeDisplayEventEnd = function () {
24126        return this.dayGrid.colCnt === 1; // we'll likely have space if there's only one day
24127    };
24128    // Builds the HTML to be used for the default element for an individual segment
24129    DayGridEventRenderer.prototype.fgSegHtml = function (seg, disableResizing) {
24130        var view = this.view;
24131        var eventDef = seg.footprint.eventDef;
24132        var isAllDay = seg.footprint.componentFootprint.isAllDay;
24133        var isDraggable = view.isEventDefDraggable(eventDef);
24134        var isResizableFromStart = !disableResizing && isAllDay &&
24135            seg.isStart && view.isEventDefResizableFromStart(eventDef);
24136        var isResizableFromEnd = !disableResizing && isAllDay &&
24137            seg.isEnd && view.isEventDefResizableFromEnd(eventDef);
24138        var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd);
24139        var skinCss = util_1.cssToStr(this.getSkinCss(eventDef));
24140        var timeHtml = '';
24141        var timeText;
24142        var titleHtml;
24143        classes.unshift('fc-day-grid-event', 'fc-h-event');
24144        // Only display a timed events time if it is the starting segment
24145        if (seg.isStart) {
24146            timeText = this.getTimeText(seg.footprint);
24147            if (timeText) {
24148                timeHtml = '<span class="fc-time">' + util_1.htmlEscape(timeText) + '</span>';
24149            }
24150        }
24151        titleHtml =
24152            '<span class="fc-title">' +
24153                (util_1.htmlEscape(eventDef.title || '') || '&nbsp;') + // we always want one line of height
24154                '</span>';
24155        return '<a class="' + classes.join(' ') + '"' +
24156            (eventDef.url ?
24157                ' href="' + util_1.htmlEscape(eventDef.url) + '"' :
24158                '') +
24159            (skinCss ?
24160                ' style="' + skinCss + '"' :
24161                '') +
24162            '>' +
24163            '<div class="fc-content">' +
24164            (this.dayGrid.isRTL ?
24165                titleHtml + ' ' + timeHtml : // put a natural space in between
24166                timeHtml + ' ' + titleHtml //
24167            ) +
24168            '</div>' +
24169            (isResizableFromStart ?
24170                '<div class="fc-resizer fc-start-resizer"></div>' :
24171                '') +
24172            (isResizableFromEnd ?
24173                '<div class="fc-resizer fc-end-resizer"></div>' :
24174                '') +
24175            '</a>';
24176    };
24177    return DayGridEventRenderer;
24178}(EventRenderer_1.default));
24179exports.default = DayGridEventRenderer;
24180// Computes whether two segments' columns collide. They are assumed to be in the same row.
24181function isDaySegCollision(seg, otherSegs) {
24182    var i;
24183    var otherSeg;
24184    for (i = 0; i < otherSegs.length; i++) {
24185        otherSeg = otherSegs[i];
24186        if (otherSeg.leftCol <= seg.rightCol &&
24187            otherSeg.rightCol >= seg.leftCol) {
24188            return true;
24189        }
24190    }
24191    return false;
24192}
24193// A cmp function for determining the leftmost event
24194function compareDaySegCols(a, b) {
24195    return a.leftCol - b.leftCol;
24196}
24197
24198
24199/***/ }),
24200/* 244 */
24201/***/ (function(module, exports, __webpack_require__) {
24202
24203Object.defineProperty(exports, "__esModule", { value: true });
24204var tslib_1 = __webpack_require__(2);
24205var $ = __webpack_require__(3);
24206var HelperRenderer_1 = __webpack_require__(63);
24207var DayGridHelperRenderer = /** @class */ (function (_super) {
24208    tslib_1.__extends(DayGridHelperRenderer, _super);
24209    function DayGridHelperRenderer() {
24210        return _super !== null && _super.apply(this, arguments) || this;
24211    }
24212    // Renders a mock "helper" event. `sourceSeg` is the associated internal segment object. It can be null.
24213    DayGridHelperRenderer.prototype.renderSegs = function (segs, sourceSeg) {
24214        var helperNodes = [];
24215        var rowStructs;
24216        // TODO: not good to call eventRenderer this way
24217        rowStructs = this.eventRenderer.renderSegRows(segs);
24218        // inject each new event skeleton into each associated row
24219        this.component.rowEls.each(function (row, rowNode) {
24220            var rowEl = $(rowNode); // the .fc-row
24221            var skeletonEl = $('<div class="fc-helper-skeleton"><table></table></div>'); // will be absolutely positioned
24222            var skeletonTopEl;
24223            var skeletonTop;
24224            // If there is an original segment, match the top position. Otherwise, put it at the row's top level
24225            if (sourceSeg && sourceSeg.row === row) {
24226                skeletonTop = sourceSeg.el.position().top;
24227            }
24228            else {
24229                skeletonTopEl = rowEl.find('.fc-content-skeleton tbody');
24230                if (!skeletonTopEl.length) { // when no events
24231                    skeletonTopEl = rowEl.find('.fc-content-skeleton table');
24232                }
24233                skeletonTop = skeletonTopEl.position().top;
24234            }
24235            skeletonEl.css('top', skeletonTop)
24236                .find('table')
24237                .append(rowStructs[row].tbodyEl);
24238            rowEl.append(skeletonEl);
24239            helperNodes.push(skeletonEl[0]);
24240        });
24241        return $(helperNodes); // must return the elements rendered
24242    };
24243    return DayGridHelperRenderer;
24244}(HelperRenderer_1.default));
24245exports.default = DayGridHelperRenderer;
24246
24247
24248/***/ }),
24249/* 245 */
24250/***/ (function(module, exports, __webpack_require__) {
24251
24252Object.defineProperty(exports, "__esModule", { value: true });
24253var tslib_1 = __webpack_require__(2);
24254var $ = __webpack_require__(3);
24255var FillRenderer_1 = __webpack_require__(62);
24256var DayGridFillRenderer = /** @class */ (function (_super) {
24257    tslib_1.__extends(DayGridFillRenderer, _super);
24258    function DayGridFillRenderer() {
24259        var _this = _super !== null && _super.apply(this, arguments) || this;
24260        _this.fillSegTag = 'td'; // override the default tag name
24261        return _this;
24262    }
24263    DayGridFillRenderer.prototype.attachSegEls = function (type, segs) {
24264        var nodes = [];
24265        var i;
24266        var seg;
24267        var skeletonEl;
24268        for (i = 0; i < segs.length; i++) {
24269            seg = segs[i];
24270            skeletonEl = this.renderFillRow(type, seg);
24271            this.component.rowEls.eq(seg.row).append(skeletonEl);
24272            nodes.push(skeletonEl[0]);
24273        }
24274        return nodes;
24275    };
24276    // Generates the HTML needed for one row of a fill. Requires the seg's el to be rendered.
24277    DayGridFillRenderer.prototype.renderFillRow = function (type, seg) {
24278        var colCnt = this.component.colCnt;
24279        var startCol = seg.leftCol;
24280        var endCol = seg.rightCol + 1;
24281        var className;
24282        var skeletonEl;
24283        var trEl;
24284        if (type === 'businessHours') {
24285            className = 'bgevent';
24286        }
24287        else {
24288            className = type.toLowerCase();
24289        }
24290        skeletonEl = $('<div class="fc-' + className + '-skeleton">' +
24291            '<table><tr></tr></table>' +
24292            '</div>');
24293        trEl = skeletonEl.find('tr');
24294        if (startCol > 0) {
24295            trEl.append(
24296            // will create (startCol + 1) td's
24297            new Array(startCol + 1).join('<td></td>'));
24298        }
24299        trEl.append(seg.el.attr('colspan', endCol - startCol));
24300        if (endCol < colCnt) {
24301            trEl.append(
24302            // will create (colCnt - endCol) td's
24303            new Array(colCnt - endCol + 1).join('<td></td>'));
24304        }
24305        this.component.bookendCells(trEl);
24306        return skeletonEl;
24307    };
24308    return DayGridFillRenderer;
24309}(FillRenderer_1.default));
24310exports.default = DayGridFillRenderer;
24311
24312
24313/***/ }),
24314/* 246 */
24315/***/ (function(module, exports, __webpack_require__) {
24316
24317Object.defineProperty(exports, "__esModule", { value: true });
24318var tslib_1 = __webpack_require__(2);
24319var moment = __webpack_require__(0);
24320var util_1 = __webpack_require__(4);
24321var BasicView_1 = __webpack_require__(67);
24322var MonthViewDateProfileGenerator_1 = __webpack_require__(247);
24323/* A month view with day cells running in rows (one-per-week) and columns
24324----------------------------------------------------------------------------------------------------------------------*/
24325var MonthView = /** @class */ (function (_super) {
24326    tslib_1.__extends(MonthView, _super);
24327    function MonthView() {
24328        return _super !== null && _super.apply(this, arguments) || this;
24329    }
24330    // Overrides the default BasicView behavior to have special multi-week auto-height logic
24331    MonthView.prototype.setGridHeight = function (height, isAuto) {
24332        // if auto, make the height of each row the height that it would be if there were 6 weeks
24333        if (isAuto) {
24334            height *= this.dayGrid.rowCnt / 6;
24335        }
24336        util_1.distributeHeight(this.dayGrid.rowEls, height, !isAuto); // if auto, don't compensate for height-hogging rows
24337    };
24338    MonthView.prototype.isDateInOtherMonth = function (date, dateProfile) {
24339        return date.month() !== moment.utc(dateProfile.currentUnzonedRange.startMs).month(); // TODO: optimize
24340    };
24341    return MonthView;
24342}(BasicView_1.default));
24343exports.default = MonthView;
24344MonthView.prototype.dateProfileGeneratorClass = MonthViewDateProfileGenerator_1.default;
24345
24346
24347/***/ }),
24348/* 247 */
24349/***/ (function(module, exports, __webpack_require__) {
24350
24351Object.defineProperty(exports, "__esModule", { value: true });
24352var tslib_1 = __webpack_require__(2);
24353var BasicViewDateProfileGenerator_1 = __webpack_require__(68);
24354var UnzonedRange_1 = __webpack_require__(5);
24355var MonthViewDateProfileGenerator = /** @class */ (function (_super) {
24356    tslib_1.__extends(MonthViewDateProfileGenerator, _super);
24357    function MonthViewDateProfileGenerator() {
24358        return _super !== null && _super.apply(this, arguments) || this;
24359    }
24360    // Computes the date range that will be rendered.
24361    MonthViewDateProfileGenerator.prototype.buildRenderRange = function (currentUnzonedRange, currentRangeUnit, isRangeAllDay) {
24362        var renderUnzonedRange = _super.prototype.buildRenderRange.call(this, currentUnzonedRange, currentRangeUnit, isRangeAllDay);
24363        var start = this.msToUtcMoment(renderUnzonedRange.startMs, isRangeAllDay);
24364        var end = this.msToUtcMoment(renderUnzonedRange.endMs, isRangeAllDay);
24365        var rowCnt;
24366        // ensure 6 weeks
24367        if (this.opt('fixedWeekCount')) {
24368            rowCnt = Math.ceil(// could be partial weeks due to hiddenDays
24369            end.diff(start, 'weeks', true) // dontRound=true
24370            );
24371            end.add(6 - rowCnt, 'weeks');
24372        }
24373        return new UnzonedRange_1.default(start, end);
24374    };
24375    return MonthViewDateProfileGenerator;
24376}(BasicViewDateProfileGenerator_1.default));
24377exports.default = MonthViewDateProfileGenerator;
24378
24379
24380/***/ }),
24381/* 248 */
24382/***/ (function(module, exports, __webpack_require__) {
24383
24384Object.defineProperty(exports, "__esModule", { value: true });
24385var tslib_1 = __webpack_require__(2);
24386var $ = __webpack_require__(3);
24387var util_1 = __webpack_require__(4);
24388var UnzonedRange_1 = __webpack_require__(5);
24389var View_1 = __webpack_require__(43);
24390var Scroller_1 = __webpack_require__(41);
24391var ListEventRenderer_1 = __webpack_require__(249);
24392var ListEventPointing_1 = __webpack_require__(250);
24393/*
24394Responsible for the scroller, and forwarding event-related actions into the "grid".
24395*/
24396var ListView = /** @class */ (function (_super) {
24397    tslib_1.__extends(ListView, _super);
24398    function ListView(calendar, viewSpec) {
24399        var _this = _super.call(this, calendar, viewSpec) || this;
24400        _this.segSelector = '.fc-list-item'; // which elements accept event actions
24401        _this.scroller = new Scroller_1.default({
24402            overflowX: 'hidden',
24403            overflowY: 'auto'
24404        });
24405        return _this;
24406    }
24407    ListView.prototype.renderSkeleton = function () {
24408        this.el.addClass('fc-list-view ' +
24409            this.calendar.theme.getClass('listView'));
24410        this.scroller.render();
24411        this.scroller.el.appendTo(this.el);
24412        this.contentEl = this.scroller.scrollEl; // shortcut
24413    };
24414    ListView.prototype.unrenderSkeleton = function () {
24415        this.scroller.destroy(); // will remove the Grid too
24416    };
24417    ListView.prototype.updateSize = function (totalHeight, isAuto, isResize) {
24418        _super.prototype.updateSize.call(this, totalHeight, isAuto, isResize);
24419        this.scroller.clear(); // sets height to 'auto' and clears overflow
24420        if (!isAuto) {
24421            this.scroller.setHeight(this.computeScrollerHeight(totalHeight));
24422        }
24423    };
24424    ListView.prototype.computeScrollerHeight = function (totalHeight) {
24425        return totalHeight -
24426            util_1.subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
24427    };
24428    ListView.prototype.renderDates = function (dateProfile) {
24429        var calendar = this.calendar;
24430        var dayStart = calendar.msToUtcMoment(dateProfile.renderUnzonedRange.startMs, true);
24431        var viewEnd = calendar.msToUtcMoment(dateProfile.renderUnzonedRange.endMs, true);
24432        var dayDates = [];
24433        var dayRanges = [];
24434        while (dayStart < viewEnd) {
24435            dayDates.push(dayStart.clone());
24436            dayRanges.push(new UnzonedRange_1.default(dayStart, dayStart.clone().add(1, 'day')));
24437            dayStart.add(1, 'day');
24438        }
24439        this.dayDates = dayDates;
24440        this.dayRanges = dayRanges;
24441        // all real rendering happens in EventRenderer
24442    };
24443    // slices by day
24444    ListView.prototype.componentFootprintToSegs = function (footprint) {
24445        var dayRanges = this.dayRanges;
24446        var dayIndex;
24447        var segRange;
24448        var seg;
24449        var segs = [];
24450        for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex++) {
24451            segRange = footprint.unzonedRange.intersect(dayRanges[dayIndex]);
24452            if (segRange) {
24453                seg = {
24454                    startMs: segRange.startMs,
24455                    endMs: segRange.endMs,
24456                    isStart: segRange.isStart,
24457                    isEnd: segRange.isEnd,
24458                    dayIndex: dayIndex
24459                };
24460                segs.push(seg);
24461                // detect when footprint won't go fully into the next day,
24462                // and mutate the latest seg to the be the end.
24463                if (!seg.isEnd && !footprint.isAllDay &&
24464                    dayIndex + 1 < dayRanges.length &&
24465                    footprint.unzonedRange.endMs < dayRanges[dayIndex + 1].startMs + this.nextDayThreshold) {
24466                    seg.endMs = footprint.unzonedRange.endMs;
24467                    seg.isEnd = true;
24468                    break;
24469                }
24470            }
24471        }
24472        return segs;
24473    };
24474    ListView.prototype.renderEmptyMessage = function () {
24475        this.contentEl.html('<div class="fc-list-empty-wrap2">' + // TODO: try less wraps
24476            '<div class="fc-list-empty-wrap1">' +
24477            '<div class="fc-list-empty">' +
24478            util_1.htmlEscape(this.opt('noEventsMessage')) +
24479            '</div>' +
24480            '</div>' +
24481            '</div>');
24482    };
24483    // render the event segments in the view
24484    ListView.prototype.renderSegList = function (allSegs) {
24485        var segsByDay = this.groupSegsByDay(allSegs); // sparse array
24486        var dayIndex;
24487        var daySegs;
24488        var i;
24489        var tableEl = $('<table class="fc-list-table ' + this.calendar.theme.getClass('tableList') + '"><tbody></tbody></table>');
24490        var tbodyEl = tableEl.find('tbody');
24491        for (dayIndex = 0; dayIndex < segsByDay.length; dayIndex++) {
24492            daySegs = segsByDay[dayIndex];
24493            if (daySegs) { // sparse array, so might be undefined
24494                // append a day header
24495                tbodyEl.append(this.dayHeaderHtml(this.dayDates[dayIndex]));
24496                this.eventRenderer.sortEventSegs(daySegs);
24497                for (i = 0;
24497 i < daySegs.length; i++) {
24498                    tbodyEl.append(daySegs[i].el); // append event row
24499                }
24500            }
24501        }
24502        this.contentEl.empty().append(tableEl);
24503    };
24504    // Returns a sparse array of arrays, segs grouped by their dayIndex
24505    ListView.prototype.groupSegsByDay = function (segs) {
24506        var segsByDay = []; // sparse array
24507        var i;
24508        var seg;
24509        for (i = 0; i < segs.length; i++) {
24510            seg = segs[i];
24511            (segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = []))
24512                .push(seg);
24513        }
24514        return segsByDay;
24515    };
24516    // generates the HTML for the day headers that live amongst the event rows
24517    ListView.prototype.dayHeaderHtml = function (dayDate) {
24518        var mainFormat = this.opt('listDayFormat');
24519        var altFormat = this.opt('listDayAltFormat');
24520        return '<tr class="fc-list-heading" data-date="' + dayDate.format('YYYY-MM-DD') + '">' +
24521            '<td class="' + (this.calendar.theme.getClass('tableListHeading') ||
24522            this.calendar.theme.getClass('widgetHeader')) + '" colspan="3">' +
24523            (mainFormat ?
24524                this.buildGotoAnchorHtml(dayDate, { 'class': 'fc-list-heading-main' }, util_1.htmlEscape(dayDate.format(mainFormat)) // inner HTML
24525                ) :
24526                '') +
24527            (altFormat ?
24528                this.buildGotoAnchorHtml(dayDate, { 'class': 'fc-list-heading-alt' }, util_1.htmlEscape(dayDate.format(altFormat)) // inner HTML
24529                ) :
24530                '') +
24531            '</td>' +
24532            '</tr>';
24533    };
24534    return ListView;
24535}(View_1.default));
24536exports.default = ListView;
24537ListView.prototype.eventRendererClass = ListEventRenderer_1.default;
24538ListView.prototype.eventPointingClass = ListEventPointing_1.default;
24539
24540
24541/***/ }),
24542/* 249 */
24543/***/ (function(module, exports, __webpack_require__) {
24544
24545Object.defineProperty(exports, "__esModule", { value: true });
24546var tslib_1 = __webpack_require__(2);
24547var util_1 = __webpack_require__(4);
24548var EventRenderer_1 = __webpack_require__(44);
24549var ListEventRenderer = /** @class */ (function (_super) {
24550    tslib_1.__extends(ListEventRenderer, _super);
24551    function ListEventRenderer() {
24552        return _super !== null && _super.apply(this, arguments) || this;
24553    }
24554    ListEventRenderer.prototype.renderFgSegs = function (segs) {
24555        if (!segs.length) {
24556            this.component.renderEmptyMessage();
24557        }
24558        else {
24559            this.component.renderSegList(segs);
24560        }
24561    };
24562    // generates the HTML for a single event row
24563    ListEventRenderer.prototype.fgSegHtml = function (seg) {
24564        var view = this.view;
24565        var calendar = view.calendar;
24566        var theme = calendar.theme;
24567        var eventFootprint = seg.footprint;
24568        var eventDef = eventFootprint.eventDef;
24569        var componentFootprint = eventFootprint.componentFootprint;
24570        var url = eventDef.url;
24571        var classes = ['fc-list-item'].concat(this.getClasses(eventDef));
24572        var bgColor = this.getBgColor(eventDef);
24573        var timeHtml;
24574        if (componentFootprint.isAllDay) {
24575            timeHtml = view.getAllDayHtml();
24576        }
24577        else if (view.isMultiDayRange(componentFootprint.unzonedRange)) {
24578            if (seg.isStart || seg.isEnd) { // outer segment that probably lasts part of the day
24579                timeHtml = util_1.htmlEscape(this._getTimeText(calendar.msToMoment(seg.startMs), calendar.msToMoment(seg.endMs), componentFootprint.isAllDay));
24580            }
24581            else { // inner segment that lasts the whole day
24582                timeHtml = view.getAllDayHtml();
24583            }
24584        }
24585        else {
24586            // Display the normal time text for the *event's* times
24587            timeHtml = util_1.htmlEscape(this.getTimeText(eventFootprint));
24588        }
24589        if (url) {
24590            classes.push('fc-has-url');
24591        }
24592        return '<tr class="' + classes.join(' ') + '">' +
24593            (this.displayEventTime ?
24594                '<td class="fc-list-item-time ' + theme.getClass('widgetContent') + '">' +
24595                    (timeHtml || '') +
24596                    '</td>' :
24597                '') +
24598            '<td class="fc-list-item-marker ' + theme.getClass('widgetContent') + '">' +
24599            '<span class="fc-event-dot"' +
24600            (bgColor ?
24601                ' style="background-color:' + bgColor + '"' :
24602                '') +
24603            '></span>' +
24604            '</td>' +
24605            '<td class="fc-list-item-title ' + theme.getClass('widgetContent') + '">' +
24606            '<a' + (url ? ' href="' + util_1.htmlEscape(url) + '"' : '') + '>
24606' +
24607            util_1.htmlEscape(eventDef.title || '') +
24608            '</a>' +
24609            '</td>' +
24610            '</tr>';
24611    };
24612    // like "4:00am"
24613    ListEventRenderer.prototype.computeEventTimeFormat = function () {
24614        return this.opt('mediumTimeFormat');
24615    };
24616    return ListEventRenderer;
24617}(EventRenderer_1.default));
24618exports.default = ListEventRenderer;
24619
24620
24621/***/ }),
24622/* 250 */
24623/***/ (function(module, exports, __webpack_require__) {
24624
24625Object.defineProperty(exports, "__esModule", { value: true });
24626var tslib_1 = __webpack_require__(2);
24627var $ = __webpack_require__(3);
24628var EventPointing_1 = __webpack_require__(64);
24629var ListEventPointing = /** @class */ (function (_super) {
24630    tslib_1.__extends(ListEventPointing, _super);
24631    function ListEventPointing() {
24632        return _super !== null && _super.apply(this, arguments) || this;
24633    }
24634    // for events with a url, the whole <tr> should be clickable,
24635    // but it's impossible to wrap with an <a> tag. simulate this.
24636    ListEventPointing.prototype.handleClick = function (seg, ev) {
24637        var url;
24638        _super.prototype.handleClick.call(this, seg, ev); // might prevent the default action
24639        // not clicking on or within an <a> with an href
24640        if (!$(ev.target).closest('a[href]').length) {
24641            url = seg.footprint.eventDef.url;
24642            if (url && !ev.isDefaultPrevented()) { // jsEvent not cancelled in handler
24643                window.location.href = url; // simulate link click
24644            }
24645        }
24646    };
24647    return ListEventPointing;
24648}(EventPointing_1.default));
24649exports.default = ListEventPointing;
24650
24651
24652/***/ }),
24653/* 251 */,
24654/* 252 */,
24655/* 253 */,
24656/* 254 */,
24657/* 255 */,
24658/* 256 */
24659/***/ (function(module, exports, __webpack_require__) {
24660
24661var $ = __webpack_require__(3);
24662var exportHooks = __webpack_require__(18);
24663var util_1 = __webpack_require__(4);
24664var Calendar_1 = __webpack_require__(232);
24665// for intentional side-effects
24666__webpack_require__(11);
24667__webpack_require__(49);
24668__webpack_require__(260);
24669__webpack_require__(261);
24670__webpack_require__(264);
24671__webpack_require__(265);
24672__webpack_require__(266);
24673__webpack_require__(267);
24674$.fullCalendar = exportHooks;
24675$.fn.fullCalendar = function (options) {
24676    var args = Array.prototype.slice.call(arguments, 1); // for a possible method call
24677    var res = this; // what this function will return (this jQuery object by default)
24678    this.each(function (i, _element) {
24679        var element = $(_element);
24680        var calendar = element.data('fullCalendar'); // get the existing calendar object (if any)
24681        var singleRes; // the returned value of this single method call
24682        // a method call
24683        if (typeof options === 'string') {
24684            if (options === 'getCalendar') {
24685                if (!i) { // first element only
24686                    res = calendar;
24687                }
24688            }
24689            else if (options === 'destroy') { // don't warn if no calendar object
24690                if (calendar) {
24691                    calendar.destroy();
24692                    element.removeData('fullCalendar');
24693                }
24694            }
24695            else if (!calendar) {
24696                util_1.warn('Attempting to call a FullCalendar method on an element with no calendar.');
24697            }
24698            else if ($.isFunction(calendar[options])) {
24699                singleRes = calendar[options].apply(calendar, args);
24700                if (!i) {
24701                    res = singleRes; // record the first method call result
24702                }
24703                if (options === 'destroy') { // for the destroy method, must remove Calendar object data
24704                    element.removeData('fullCalendar');
24705                }
24706            }
24707            else {
24708                util_1.warn("'" + options + "' is an unknown FullCalendar method.");
24709            }
24710        }
24711        else if (!calendar) { // don't initialize twice
24712            calendar = new Calendar_1.default(element, options);
24713            element.data('fullCalendar', calendar);
24714            calendar.render();
24715        }
24716    });
24717    return res;
24718};
24719module.exports = exportHooks;
24720
24721
24722/***/ }),
24723/* 257 */
24724/***/ (function(module, exports, __webpack_require__) {
24725
24726Object.defineProperty(exports, "__esModule", { value: true });
24727var $ = __webpack_require__(3);
24728var util_1 = __webpack_require__(4);
24729/* Toolbar with buttons and title
24730----------------------------------------------------------------------------------------------------------------------*/
24731var Toolbar = /** @class */ (function () {
24732    function Toolbar(calendar, toolbarOptions) {
24733        this.el = null; // mirrors local `el`
24734        this.viewsWithButtons = [];
24735        this.calendar = calendar;
24736        this.toolbarOptions = toolbarOptions;
24737    }
24738    // method to update toolbar-specific options, not calendar-wide options
24739    Toolbar.prototype.setToolbarOptions = function (newToolbarOptions) {
24740        this.toolbarOptions = newToolbarOptions;
24741    };
24742    // can be called repeatedly and will rerender
24743    Toolbar.prototype.render = function () {
24744        var sections = this.toolbarOptions.layout;
24745        var el = this.el;
24746        if (sections) {
24747            if (!el) {
24748                el = this.el = $("<div class='fc-toolbar " + this.toolbarOptions.extraClasse
24748s + "'>");
24749            }
24750            else {
24751                el.empty();
24752            }
24753            el.append(this.renderSection('left'))
24754                .append(this.renderSection('right'))
24755                .append(this.renderSection('center'))
24756                .append('<div class="fc-clear"></div>');
24757        }
24758        else {
24759            this.removeElement();
24760        }
24761    };
24762    Toolbar.prototype.removeElement = function () {
24763        if (this.el) {
24764            this.el.remove();
24765            this.el = null;
24766        }
24767    };
24768    Toolbar.prototype.renderSection = function (position) {
24769        var _this = this;
24770        var calendar = this.calendar;
24771        var theme = calendar.theme;
24772        var optionsManager = calendar.optionsManager;
24773        var viewSpecManager = calendar.viewSpecManager;
24774        var sectionEl = $('<div class="fc-' + position + '">');
24775        var buttonStr = this.toolbarOptions.layout[position];
24776        var calendarCustomButtons = optionsManager.get('customButtons') || {};
24777        var calendarButtonTextOverrides = optionsManager.overrides.buttonText || {};
24778        var calendarButtonText = optionsManager.get('buttonText') || {};
24779        if (buttonStr) {
24780            $.each(buttonStr.split(' '), function (i, buttonGroupStr) {
24781                var groupChildren = $();
24782                var isOnlyButtons = true;
24783                var groupEl;
24784                $.each(buttonGroupStr.split(','), function (j, buttonName) {
24785                    var customButtonProps;
24786                    var viewSpec;
24787                    var buttonClick;
24788                    var buttonIcon; // only one of these will be set
24789                    var buttonText; // "
24790                    var buttonInnerHtml;
24791                    var buttonClasses;
24792                    var buttonEl;
24793                    var buttonAriaAttr;
24794                    if (buttonName === 'title') {
24795                        groupChildren = groupChildren.add($('<h2>&nbsp;</h2>')); // we always want it to take up height
24796                        isOnlyButtons = false;
24797                    }
24798                    else {
24799                        if ((customButtonProps = calendarCustomButtons[buttonName])) {
24800                            buttonClick = function (ev) {
24801                                if (customButtonProps.click) {
24802                                    customButtonProps.click.call(buttonEl[0], ev);
24803                                }
24804                            };
24805                            (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) ||
24806                                (buttonIcon = theme.getIconClass(buttonName)) ||
24807                                (buttonText = customButtonProps.text);
24808                        }
24809                        else if ((viewSpec = viewSpecManager.getViewSpec(buttonName))) {
24810                            _this.viewsWithButtons.push(buttonName);
24811                            buttonClick = function () {
24812                                calendar.changeView(buttonName);
24813                            };
24814                            (buttonText = viewSpec.buttonTextOverride) ||
24815                                (buttonIcon = theme.getIconClass(buttonName)) ||
24816                                (buttonText = viewSpec.buttonTextDefault);
24817                        }
24818                        else if (calendar[buttonName]) { // a calendar method
24819                            buttonClick = function () {
24820                                calendar[buttonName]();
24821                            };
24822                            (buttonText = calendarButtonTextOverrides[buttonName]) ||
24823                                (buttonIcon = theme.getIconClass(buttonName)) ||
24824                                (buttonText = calendarButtonText[buttonName]);
24825                            //            ^ everything else is considered default
24826                        }
24827                        if (buttonClick) {
24828                            buttonClasses = [
24829                                'fc-' + buttonName + '-button',
24830                                theme.getClass('button'),
24831                                theme.getClass('stateDefault')
24832                            ];
24833                            if (buttonText) {
24834                                buttonInnerHtml = util_1.htmlEscape(buttonText);
24835                                buttonAriaAttr = '';
24836                            }
24837                            else if (buttonIcon) {
24838                                buttonInnerHtml = "<span class='" + buttonIcon + "'></span>";
24839                                buttonAriaAttr = ' aria-label="' + buttonName + '"';
24840                            }
24841                            buttonEl = $(// type="button" so that it doesn't submit a form
24842                            '<button type="button" class="' + buttonClasse
24842s.join(' ') + '"' +
24843                                buttonAriaAttr +
24844                                '>' + buttonInnerHtml + '</button>')
24845                                .click(function (ev) {
24846                                // don't process clicks for disabled buttons
24847                                if (!buttonEl.hasClass(theme.getClass('stateDisabled'))) {
24848                                    buttonClick(ev);
24849                                    // after the click action, if the button becomes the "active" tab, or disabled,
24850                                    // it should never have a hover class, so remove it now.
24851                                    if (buttonEl.hasClass(theme.getClass('stateActive')) ||
24852                                        buttonEl.hasClass(theme.getClass('stateDisabled'))) {
24853                                        buttonEl.removeClass(theme.getClass('stateHover'));
24854                                    }
24855                                }
24856                            })
24857                                .mousedown(function () {
24858                                // the *down* effect (mouse pressed in).
24859                                // only on buttons that are not the "active" tab, or disabled
24860                                buttonEl
24861                                    .not('.' + theme.getClass('stateActive'))
24862                                    .not('.' + theme.getClass('stateDisabled'))
24863                                    .addClass(theme.getClass('stateDown'));
24864                            })
24865                                .mouseup(function () {
24866                                // undo the *down* effect
24867                                buttonEl.removeClass(theme.getClass('stateDown'));
24868                            })
24869                                .hover(function () {
24870                                // the *hover* effect.
24871                                // only on buttons that are not the "active" tab, or disabled
24872                                buttonEl
24873                                    .not('.' + theme.getClass('stateActive'))
24874                                    .not('.' + theme.getClass('stateDisabled'))
24875                                    .addClass(theme.getClass('stateHover'));
24876                            }, function () {
24877                                // undo the *hover* effect
24878                                buttonEl
24879                                    .removeClass(theme.getClass('stateHover'))
24880                                    .removeClass(theme.getClass('stateDown')); // if mouseleave happens before mouseup
24881                            });
24882                            groupChildren = groupChildren.add(buttonEl);
24883                        }
24884                    }
24885                });
24886                if (isOnlyButtons) {
24887                    groupChildren
24888                        .first().addClass(theme.getClass('cornerLeft')).end()
24889                        .last().addClass(theme.getClass('cornerRight')).end();
24890                }
24891                if (groupChildren.length > 1) {
24892                    groupEl = $('<div>');
24893                    if (isOnlyButtons) {
24894                        groupEl.addClass(theme.getClass('buttonGroup'));
24895                    }
24896                    groupEl.append(groupChildren);
24897                    sectionEl.append(groupEl);
24898                }
24899                else {
24900                    sectionEl.append(groupChildren); // 1 or 0 children
24901                }
24902            });
24903        }
24904        return sectionEl;
24905    };
24906    Toolbar.prototype.updateTitle = function (text) {
24907        if (this.el) {
24908            this.el.find('h2').text(text);
24909        }
24910    };
24911    Toolbar.prototype.activateButton = function (buttonName) {
24912        if (this.el) {
24913            this.el.find('.fc-' + buttonName + '-button')
24914                .addClass(this.calendar.theme.getClass('stateActive'));
24915        }
24916    };
24917    Toolbar.prototype.deactivateButton = function (buttonName) {
24918        if (this.el) {
24919            this.el.find('.fc-' + buttonName + '-button')
24920                .removeClass(this.calendar.theme.getClass('stateActive'));
24921        }
24922    };
24923    Toolbar.prototype.disableButton = function (buttonName) {
24924        if (this.el) {
24925            this.el.find('.fc-' + buttonName + '-button')
24926                .prop('disabled', true)
24927                .addClass(this.calendar.theme.getClass('stateDisabled'));
24928        }
24929    };
24930    Toolbar.prototype.enableButton = function (buttonName) {
24931        if (this.el) {
24932            this.el.find('.fc-' + buttonName + '-button')
24933                .prop('disabled', false)
24934                .removeClass(this.calendar.theme.getClass('stateDisabled'));
24935        }
24936    };
24937    Toolbar.prototype.getViewsWithButtons = function () {
24938        return this.viewsWithButtons;
24939    };
24940    return Toolbar;
24941}());
24942exports.default = Toolbar;
24943
24944
24945/***/ }),
24946/* 258 */
24947/***/ (function(module, exports, __webpack_require__) {
24948
24949Object.defineProperty(exports, "__esModule", { value: true });
24950var tslib_1 = __webpack_require__(2);
24951var $ = __webpack_require__(3);
24952var util_1 = __webpack_require__(4);
24953var options_1 = __webpack_require__(33);
24954var locale_1 = __webpack_require__(32);
24955var Model_1 = __webpack_require__(51);
24956var OptionsManager = /** @class */ (function (_super) {
24957    tslib_1.__extends(OptionsManager, _super);
24958    function OptionsManager(_calendar, overrides) {
24959        var _this = _super.call(this) || this;
24960        _this._calendar = _calendar;
24961        _this.overrides = $.extend({}, overrides); // make a copy
24962        _this.dynamicOverrides = {};
24963        _this.compute();
24964        return _this;
24965    }
24966    OptionsManager.prototype.add = function (newOptionHash) {
24967        var optionCnt = 0;
24968        var optionName;
24969        this.recordOverrides(newOptionHash); // will trigger this model's watchers
24970        for (optionName in newOptionHash) {
24971            optionCnt++;
24972        }
24973        // special-case handling of single option change.
24974        // if only one option change, `optionName` will be its name.
24975        if (optionCnt === 1) {
24976            if (optionName === 'height' || optionName === 'contentHeight' || optionName === 'aspectRatio') {
24977                this._calendar.updateViewSize(true); // isResize=true
24978                return;
24979            }
24980            else if (optionName === 'defaultDate') {
24981                return; // can't change date this way. use gotoDate instead
24982            }
24983            else if (optionName === 'businessHours') {
24984                return; // this model already reacts to this
24985            }
24986            else if (/^(event|select)(Overlap|Constraint|Allow)$/.test(optionName)) {
24987                return; // doesn't affect rendering. only interactions.
24988            }
24989            else if (optionName === 'timezone') {
24990                this._calendar.view.flash('initialEvents');
24991                return;
24992            }
24993        }
24994        // catch-all. rerender the header and footer and rebuild/rerender the current view
24995        this._calendar.renderHeader();
24996        this._calendar.renderFooter();
24997        // even non-current views will be affected by this option change. do before rerender
24998        // TODO: detangle
24999        this._calendar.viewsByType = {};
25000        this._calendar.reinitView();
25001    };
25002    // Computes the flattened options hash for the calendar and assigns to `this.options`.
25003    // Assumes this.overrides and this.dynamicOverrides have already been initialized.
25004    OptionsManager.prototype.compute = function () {
25005        var locale;
25006        var localeDefaults;
25007        var isRTL;
25008        var dirDefaults;
25009        var rawOptions;
25010        locale = util_1.firstDefined(// explicit locale option given?
25011        this.dynamicOverrides.locale, this.overrides.locale);
25012        localeDefaults = locale_1.localeOptionHash[locale];
25013        if (!localeDefaults) { // explicit locale option not given or invalid?
25014            locale = options_1.globalDefaults.locale;
25015            localeDefaults = locale_1.localeOptionHash[locale] || {};
25016        }
25017        isRTL = util_1.firstDefined(// based on options computed so far, is direction RTL?
25018        this.dynamicOverrides.isRTL, this.overrides.isRTL, localeDefaults.isRTL, options_1.globalDefaults.isRTL);
25019        dirDefaults = isRTL ? options_1.rtlDefaults : {};
25020        this.dirDefaults = dirDefaults;
25021        this.localeDefaults = localeDefaults;
25022        rawOptions = options_1.mergeOptions([
25023            options_1.globalDefaults,
25024            dirDefaults,
25025            localeDefaults,
25026            this.overrides,
25027            this.dynamicOverrides
25028        ]);
25029        locale_1.populateInstanceComputableOptions(rawOptions); // fill in gaps with computed options
25030        this.reset(rawOptions);
25031    };
25032    // stores the new options internally, but does not rerender anything.
25033    OptionsManager.prototype.recordOverrides = function (newOptionHash) {
25034        var optionName;
25035        for (optionName in newOptionHash) {
25036            this.dynamicOverrides[optionName] = newOptionHash[optionName];
25037        }
25038        this._calendar.viewSpecManager.clearCache(); // the dynamic override invalidates the options in this cache, so just clear it
25039        this.compute(); // this.options needs to be recomputed after the dynamic override
25040    };
25041    return OptionsManager;
25042}(Model_1.default));
25043exports.default = OptionsManager;
25044
25045
25046/***/ }),
25047/* 259 */
25048/***/ (function(module, exports, __webpack_require__) {
25049
25050Object.defineProperty(exports, "__esModule", { value: true });
25051var moment = __webpack_require__(0);
25052var $ = __webpack_require__(3);
25053var ViewRegistry_1 = __webpack_require__(24);
25054var util_1 = __webpack_require__(4);
25055var options_1 = __webpack_require__(33);
25056var locale_1 = __webpack_require__(32);
25057var ViewSpecManager = /** @class */ (function () {
25058    function ViewSpecManager(optionsManager, _calendar) {
25059        this.optionsManager = optionsManager;
25060        this._calendar = _calendar;
25061        this.clearCache();
25062    }
25063    ViewSpecManager.prototype.clearCache = function () {
25064        this.viewSpecCache = {};
25065    };
25066    // Gets information about how to create a view. Will use a cache.
25067    ViewSpecManager.prototype.getViewSpec = function (viewType) {
25068        var cache = this.viewSpecCache;
25069        return cache[viewType] || (cache[viewType] = this.buildViewSpec(viewType));
25070    };
25071    // Given a duration singular unit, like "week" or "day", finds a matching view spec.
25072    // Preference is given to views that have corresponding buttons.
25073    ViewSpecManager.prototype.getUnitViewSpec = function (unit) {
25074        var viewTypes;
25075        var i;
25076        var spec;
25077        if ($.inArray(unit, util_1.unitsDesc) !== -1) {
25078            // put views that have buttons first. there will be duplicates, but oh well
25079            viewTypes = this._calendar.header.getViewsWithButtons(); // TODO: include footer as well?
25080            $.each(ViewRegistry_1.viewHash, function (viewType) {
25081                viewTypes.push(viewType);
25082            });
25083            for (i = 0; i < viewTypes.length; i++) {
25084                spec = this.getViewSpec(viewTypes[i]);
25085                if (spec) {
25086                    if (spec.singleUnit === unit) {
25087                        return spec;
25088                    }
25089                }
25090            }
25091        }
25092    };
25093    // Builds an object with information on how to create a given view
25094    ViewSpecManager.prototype.buildViewSpec = function (requestedViewType) {
25095        var viewOverrides = this.optionsManager.overrides.views || {};
25096        var specChain = []; // for the view. lowest to highest priority
25097        var defaultsChain = []; // for the view. lowest to highest priority
25098        var overridesChain = []; // for the view. lowest to highest priority
25099        var viewType = requestedViewType;
25100        var spec; // for the view
25101        var overrides; // for the view
25102        var durationInput;
25103        var duration;
25104        var unit;
25105        // iterate from the specific view definition to a more general one until we hit an actual View class
25106        while (viewType) {
25107            spec = ViewRegistry_1.viewHash[viewType];
25108            overrides = viewOverrides[viewType];
25109            viewType = null; // clear. might repopulate for another iteration
25110            if (typeof spec === 'function') { // TODO: deprecate
25111                spec = { 'class': spec };
25112            }
25113            if (spec) {
25114                specChain.unshift(spec);
25115                defaultsChain.unshift(spec.defaults || {});
25116                durationInput = durationInput || spec.duration;
25117                viewType = viewType || spec.type;
25118            }
25119            if (overrides) {
25120                overridesChain.unshift(overrides); // view-specific option hashes have options at zero-level
25121                durationInput = durationInput || overrides.duration;
25122                viewType = viewType || overrides.type;
25123            }
25124        }
25125        spec = util_1.mergeProps(specChain);
25126        spec.type = requestedViewType;
25127        if (!spec['class']) {
25128            return false;
25129        }
25130        // fall back to top-level `duration` option
25131        durationInput = durationInput ||
25132            this.optionsManager.dynamicOverrides.duration ||
25133            this.optionsManager.overrides.duration;
25134        if (durationInput) {
25135            duration = moment.duration(durationInput);
25136            if (duration.valueOf()) { // valid?
25137                unit = util_1.computeDurationGreatestUnit(duration, durationInput);
25138                spec.duration = duration;
25139                spec.durationUnit = unit;
25140                // view is a single-unit duration, like "week" or "day"
25141                // incorporate options for this. lowest priority
25142                if (duration.as(unit) === 1) {
25143                    spec.singleUnit = unit;
25144                    overridesChain.unshift(viewOverrides[unit] || {});
25145                }
25146            }
25147        }
25148        spec.defaults = options_1.mergeOptions(defaultsChain);
25149        spec.overrides = options_1.mergeOptions(overridesChain);
25150        this.buildViewSpecOptions(spec);
25151        this.buildViewSpecButtonText(spec, requestedViewType);
25152        return spec;
25153    };
25154    // Builds and assigns a view spec's options object from its already-assigned defaults and overrides
25155    ViewSpecManager.prototype.buildViewSpecOptions = function (spec) {
25156        var optionsManager = this.optionsManager;
25157        spec.options = options_1.mergeOptions([
25158            options_1.globalDefaults,
25159            spec.defaults,
25160            optionsManager.dirDefaults,
25161            optionsManager.localeDefaults,
25162            optionsManager.overrides,
25163            spec.overrides,
25164            optionsManager.dynamicOverrides // dynamically set via setter. highest precedence
25165        ]);
25166        locale_1.populateInstanceComputableOptions(spec.options);
25167    };
25168    // Computes and assigns a view spec's buttonText-related options
25169    ViewSpecManager.prototype.buildViewSpecButtonText = function (spec, requestedViewType) {
25170        var optionsManager = this.optionsManager;
25171        // given an options object with a possible `buttonText` hash, lookup the buttonText for the
25172        // requested view, falling back to a generic unit entry like "week" or "day"
25173        function queryButtonText(options) {
25174            var buttonText = options.buttonText || {};
25175            return buttonText[requestedViewType] ||
25176                // view can decide to look up a certain key
25177                (spec.buttonTextKey ? buttonText[spec.buttonTextKey] : null) ||
25178                // a key like "month"
25179                (spec.singleUnit ? buttonText[spec.singleUnit] : null);
25180        }
25181        // highest to lowest priority
25182        spec.buttonTextOverride =
25183            queryButtonText(optionsManager.dynamicOverrides) ||
25184                queryButtonText(optionsManager.overrides) || // constructor-specified buttonText lookup hash takes precedence
25185                spec.overrides.buttonText; // `buttonText` for view-specific options is a string
25186        // highest to lowest priority. mirrors buildViewSpecOptions
25187        spec.buttonTextDefault =
25188            queryButtonText(optionsManager.localeDefaults) ||
25189                queryButtonText(optionsManager.dirDefaults) ||
25190                spec.defaults.buttonText || // a single string. from ViewSubclass.defaults
25191                queryButtonText(options_1.globalDefaults) ||
25192                (spec.duration ? this._calendar.humanizeDuration(spec.duration) : null) || // like "3 days"
25193                requestedViewType; // fall back to given view name
25194    };
25195    return ViewSpecManager;
25196}());
25197exports.default = ViewSpecManager;
25198
25199
25200/***/ }),
25201/* 260 */
25202/***/ (function(module, exports, __webpack_require__) {
25203
25204Object.defineProperty(exports, "__esModule", { value: true });
25205var EventSourceParser_1 = __webpack_require__(38);
25206var ArrayEventSource_1 = __webpack_require__(56);
25207var FuncEventSource_1 = __webpack_require__(223);
25208var JsonFeedEventSource_1 = __webpack_require__(224);
25209EventSourceParser_1.default.registerClass(ArrayEventSource_1.default);
25210EventSourceParser_1.default.registerClass(FuncEventSource_1.default);
25211EventSourceParser_1.default.registerClass(JsonFeedEventSource_1.default);
25212
25213
25214/***/ }),
25215/* 261 */
25216/***/ (function(module, exports, __webpack_require__) {
25217
25218Object.defineProperty(exports, "__esModule", { value: true });
25219var ThemeRegistry_1 = __webpack_require__(57);
25220var StandardTheme_1 = __webpack_require__(221);
25221var JqueryUiTheme_1 = __webpack_require__(222);
25222var Bootstrap3Theme_1 = __webpack_require__(262);
25223var Bootstrap4Theme_1 = __webpack_require__(263);
25224ThemeRegistry_1.defineThemeSystem('standard', StandardTheme_1.default);
25225ThemeRegistry_1.defineThemeSystem('jquery-ui', JqueryUiTheme_1.default);
25226ThemeRegistry_1.defineThemeSystem('bootstrap3', Bootstrap3Theme_1.default);
25227ThemeRegistry_1.defineThemeSystem('bootstrap4', Bootstrap4Theme_1.default);
25228
25229
25230/***/ }),
25231/* 262 */
25232/***/ (function(module, exports, __webpack_require__) {
25233
25234Object.defineProperty(exports, "__esModule", { value: true });
25235var tslib_1 = __webpack_require__(2);
25236var Theme_1 = __webpack_require__(22);
25237var Bootstrap3Theme = /** @class */ (function (_super) {
25238    tslib_1.__extends(Bootstrap3Theme, _super);
25239    function Bootstrap3Theme() {
25240        return _super !== null && _super.apply(this, arguments) || this;
25241    }
25242    return Bootstrap3Theme;
25243}(Theme_1.default));
25244exports.default = Bootstrap3Theme;
25245Bootstrap3Theme.prototype.classes = {
25246    widget: 'fc-bootstrap3',
25247    tableGrid: 'table-bordered',
25248    tableList: 'table',
25249    tableListHeading: 'active',
25250    buttonGroup: 'btn-group',
25251    button: 'btn btn-default',
25252    stateActive: 'active',
25253    stateDisabled: 'disabled',
25254    today: 'alert alert-info',
25255    popover: 'panel panel-default',
25256    popoverHeader: 'panel-heading',
25257    popoverContent: 'panel-body',
25258    // day grid
25259    // for left/right border color when border is inset from edges (all-day in agenda view)
25260    // avoid `panel` class b/c don't want margins/radius. only border color.
25261    headerRow: 'panel-default',
25262    dayRow: 'panel-default',
25263    // list view
25264    listView: 'panel panel-default'
25265};
25266Bootstrap3Theme.prototype.baseIconClass = 'glyphicon';
25267Bootstrap3Theme.prototype.iconClasses = {
25268    close: 'glyphicon-remove',
25269    prev: 'glyphicon-chevron-left',
25270    next: 'glyphicon-chevron-right',
25271    prevYear: 'glyphicon-backward',
25272    nextYear: 'glyphicon-forward'
25273};
25274Bootstrap3Theme.prototype.iconOverrideOption = 'bootstrapGlyphicons';
25275Bootstrap3Theme.prototype.iconOverrideCustomButtonOption = 'bootstrapGlyphicon';
25276Bootstrap3Theme.prototype.iconOverridePrefix = 'glyphicon-';
25277
25278
25279/***/ }),
25280/* 263 */
25281/***/ (function(module, exports, __webpack_require__) {
25282
25283Object.defineProperty(exports, "__esModule", { value: true });
25284var tslib_1 = __webpack_require__(2);
25285var Theme_1 = __webpack_require__(22);
25286var Bootstrap4Theme = /** @class */ (function (_super) {
25287    tslib_1.__extends(Bootstrap4Theme, _super);
25288    function Bootstrap4Theme() {
25289        return _super !== null && _super.apply(this, arguments) || this;
25290    }
25291    return Bootstrap4Theme;
25292}(Theme_1.default));
25293exports.default = Bootstrap4Theme;
25294Bootstrap4Theme.prototype.classes = {
25295    widget: 'fc-bootstrap4',
25296    tableGrid: 'table-bordered',
25297    tableList: 'table',
25298    tableListHeading: 'table-active',
25299    buttonGroup: 'btn-group',
25300    button: 'btn btn-primary',
25301    stateActive: 'active',
25302    stateDisabled: 'disabled',
25303    today: 'alert alert-info',
25304    popover: 'card card-primary',
25305    popoverHeader: 'card-header',
25306    popoverContent: 'card-body',
25307    // day grid
25308    // for left/right border color when border is inset from edges (all-day in agenda view)
25309    // avoid `table` class b/c don't want margins/padding/structure. only border color.
25310    headerRow: 'table-bordered',
25311    dayRow: 'table-bordered',
25312    // list view
25313    listView: 'card card-primary'
25314};
25315Bootstrap4Theme.prototype.baseIconClass = 'fa';
25316Bootstrap4Theme.prototype.iconClasses = {
25317    close: 'fa-times',
25318    prev: 'fa-chevron-left',
25319    next: 'fa-chevron-right',
25320    prevYear: 'fa-angle-double-left',
25321    nextYear: 'fa-angle-double-right'
25322};
25323Bootstrap4Theme.prototype.iconOverrideOption = 'bootstrapFontAwesome';
25324Bootstrap4Theme.prototype.iconOverrideCustomButtonOption = 'bootstrapFontAwesome';
25325Bootstrap4Theme.prototype.iconOverridePrefix = 'fa-';
25326
25327
25328/***/ }),
25329/* 264 */
25330/***/ (function(module, exports, __webpack_require__) {
25331
25332Object.defineProperty(exports, "__esModule", { value: true });
25333var ViewRegistry_1 = __webpack_require__(24);
25334var BasicView_1 = __webpack_require__(67);
25335var MonthView_1 = __webpack_require__(246);
25336ViewRegistry_1.defineView('basic', {
25337    'class': BasicView_1.default
25338});
25339ViewRegistry_1.defineView('basicDay', {
25340    type: 'basic',
25341    duration: { days: 1 }
25342});
25343ViewRegistry_1.defineView('basicWeek', {
25344    type: 'basic',
25345    duration: { weeks: 1 }
25346});
25347ViewRegistry_1.defineView('month', {
25348    'class': MonthView_1.default,
25349    duration: { months: 1 },
25350    defaults: {
25351        fixedWeekCount: true
25352    }
25353});
25354
25355
25356/***/ }),
25357/* 265 */
25358/***/ (function(module, exports, __webpack_require__) {
25359
25360Object.defineProperty(exports, "__esModule", { value: true });
25361var ViewRegistry_1 = __webpack_require__(24);
25362var AgendaView_1 = __webpack_require__(238);
25363ViewRegistry_1.defineView('agenda', {
25364    'class': AgendaView_1.default,
25365    defaults: {
25366        allDaySlot: true,
25367        slotDuration: '00:30:00',
25368        slotEventOverlap: true // a bad name. confused with overlap/constraint system
25369    }
25370});
25371ViewRegistry_1.defineView('agendaDay', {
25372    type: 'agenda',
25373    duration: { days: 1 }
25374});
25375ViewRegistry_1.defineView('agendaWeek', {
25376    type: 'agenda',
25377    duration: { weeks: 1 }
25378});
25379
25380
25381/***/ }),
25382/* 266 */
25383/***/ (function(module, exports, __webpack_require__) {
25384
25385Object.defineProperty(exports, "__esModule", { value: true });
25386var ViewRegistry_1 = __webpack_require__(24);
25387var ListView_1 = __webpack_require__(248);
25388ViewRegistry_1.defineView('list', {
25389    'class': ListView_1.default,
25390    buttonTextKey: 'list',
25391    defaults: {
25392        buttonText: 'list',
25393        listDayFormat: 'LL',
25394        noEventsMessage: 'No events to display'
25395    }
25396});
25397ViewRegistry_1.defineView('listDay', {
25398    type: 'list',
25399    duration: { days: 1 },
25400    defaults: {
25401        listDayFormat: 'dddd' // day-of-week is all we need. full date is probably in header
25402    }
25403});
25404ViewRegistry_1.defineView('listWeek', {
25405    type: 'list',
25406    duration: { weeks: 1 },
25407    defaults: {
25408        listDayFormat: 'dddd',
25409        listDayAltFormat: 'LL'
25410    }
25411});
25412ViewRegistry_1.defineView('listMonth', {
25413    type: 'list',
25414    duration: { month: 1 },
25415    defaults: {
25416        listDayAltFormat: 'dddd' // day-of-week is nice-to-have
25417    }
25418});
25419ViewRegistry_1.defineView('listYear', {
25420    type: 'list',
25421    duration: { year: 1 },
25422    defaults: {
25423        listDayAltFormat: 'dddd' // day-of-week is nice-to-have
25424    }
25425});
25426
25427
25428/***/ }),
25429/* 267 */
25430/***/ (function(module, exports) {
25431
25432Object.defineProperty(exports, "__esModule", { value: true });
25433
25434
25435/***/ })
25436/******/ ]);
25437});
25438!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("moment"),require("fullcalendar")):"function"==typeof define&&define.amd?define(["moment","fullcalendar"],t):"object"==typeof exports?t(require("moment"),require("fullcalendar")):t(e.moment,e.FullCalendar)}("undefined"!=typeof self?self:this,function(e,t){return function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,t),a.l=!0,a.exports}var n={};return t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=103)}({0:function(t,n){t.exports=e},1:function(e,n){e.exports=t},103:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),n(104);var r=n(1);r.datepickerLocale("de","de",{closeText:"Schließen",prevText:"&#x3C;Zurück",nextText:"Vor&#x3E;",currentText:"Heute",monthNames:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthNamesShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],dayNames:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],dayNamesShort:["So","Mo","Di","Mi","Do","Fr","Sa"],dayNamesMin:["So","Mo","Di","Mi","Do","Fr","Sa"],weekHeader:"KW",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),r.locale("de",{buttonText:{year:"Jahr",month:"Monat",week:"Woche",day:"Tag",list:"Terminübersicht"},allDayText:"Ganztägig",eventLimitText:function(e){return"+ weitere "+e},noEventsMessage:"Keine Ereignisse anzuzeigen",dayOfMonthFormat:"ddd DD.MM."})},104:function(e,t,n){!function(e,t){t(n(0))}(0,function(e){function t(e,t,n,r){var a={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[e+" Tage",e+" Tagen"],M:["ein Monat","einem Monat"],MM:[e+" Monate",e+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[e+" Jahre",e+" Jahren"]};return t?a[n][0]:a[n][1]}return e.defineLocale("de",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:t,mm:"%d Minuten",h:t,hh:"%d Stunden",d:t,dd:t,M:t,MM:t,y:t,yy:t},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})}})});
25439
25440!function(e,r){"object"==typeof exports&&"object"==typeof module?module.exports=r(require("moment"),require("fullcalendar")):"function"==typeof define&&define.amd?define(["moment","fullcalendar"],r):"object"==typeof exports?r(require("moment"),require("fullcalendar")):r(e.moment,e.FullCalendar)}("undefined"!=typeof self?self:this,function(e,r){return function(e){function r(t){if(n[t])return n[t].exports;var a=n[t]={i:t,l:!1,exports:{}};return e[t].call(a.exports,a,a.exports,r),a.l=!0,a.exports}var n={};return r.m=e,r.c=n,r.d=function(e,n,t){r.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:t})},r.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(n,"a",n),n},r.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},r.p="",r(r.s=135)}({0:function(r,n){r.exports=e}
25440,1:function(e,n){e.exports=r},135:function(e,r,n){Object.defineProperty(r,"__esModule",{value:!0}),n(136);var t=n(1);t.datepickerLocale("fr","fr",{closeText:"Fermer",prevText:"Précédent",nextText:"Suivant",currentText:"Aujourd'hui",monthNames:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthNamesShort:["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],dayNames:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],dayNamesShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],dayNamesMin:["D","L","M","M","J","V","S"],weekHeader:"Sem.",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),t.locale("fr",{buttonText:{year:"Année",month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},allDayHtml:"Toute la<br/>journée",eventLimitText:"en plus",noEventsMessage:"Aucun événement à afficher"})},136:function(e,r,n){!function(e,r){r(n(0))}(0,function(e){return e.defineLocale("fr",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd’hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|)/,ordinal:function(e,r){switch(r){case"D":return e+(1===e?"er":"");default:case"M":case"Q":case"DDD":case"d":return e+(1===e?"er":"e");case"w":case"W":return e+(1===e?"re":"e")}},week:{dow:1,doy:4}})})}})});
25441!function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n(require("moment"),require("fullcalendar")):"function"==typeof define&&define.amd?define(["moment","fullcalendar"],n):"object"==typeof exports?n(require("moment"),require("fullcalendar")):n(e.moment,e.FullCalendar)}("undefined"!=typeof self?self:this,function(e,n){return function(e){function n(t){if(a[t])return a[t].exports;var r=a[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,n),r.l=!0,r.exports}var a={};return n.m=e,n.c=a,n.d=function(e,a,t){n.o(e,a)||Object.defineProperty(e,a,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var a=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(a,"a",a),a},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="",n(n.s=177)}({0:function(n,a){n.exports=e},1:function(e,a){e.exports=n},177:function(e,n,a){Object.defineProperty(n,"__esModule",{value:!0}),a(178);var t=a(1);t.datepickerLocale("nl","nl",{closeText:"Sluiten",prevText:"←",nextText:"→",currentText:"Vandaag",monthNames:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],monthNamesShort:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],dayNames:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],dayNamesShort:["zon","maa","din","woe","don","vri","zat"],dayNamesMin:["zo","ma","di","wo","do","vr","za"],weekHeader:"Wk",dateFormat:"dd-mm-yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),t.locale("nl",{buttonText:{year:"Jaar",month:"Maand",week:"Week",day:"Dag",list:"Agenda"},allDayText:"Hele dag",eventLimitText:"extra",noEventsMessage:"Geen evenementen om te laten zien"})}
25441,178:function(e,n,a){!function(e,n){n(a(0))}(0,function(e){var n="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),a="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),t=[/^jan/i,/^feb/i,/^maart|mrt.?$/i,/^apr/i,/^mei$/i,/^jun[i.]?$/i,/^jul[i.]?$/i,/^aug/i,/^sep/i,/^okt/i,/^nov/i,/^dec/i],r=/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;return e.defineLocale("nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(e,t){return e?/-MMM-/.test(t)?a[e.month()]:n[e.month()]:n},monthsRegex:r,monthsShortRegex:r,monthsStrictRegex:/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december)/i,monthsShortStrictRegex:/^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,monthsParse:t,longMonthsParse:t,shortMonthsParse:t,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"zo_ma_di_wo_do_vr_za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",ss:"%d seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(e){return e+(1===e||8===e||e>=20?"ste":"de")},week:{dow:1,doy:4}})})}})});
25442!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("moment"),require("fullcalendar")):"function"==typeof define&&define.amd?define(["moment","fullcalendar"],t):"object"==typeof exports?t(require("moment"),require("fullcalendar")):t(e.moment,e.FullCalendar)}("undefined"!=typeof self?self:this,function(e,t){return function(e){function t(n){if(r[n])return r[n].exports;var s=r[n]={i:n,l:!1,exports:{}};return e[n].call(s.exports,s,s.exports,t),s.l=!0,s.exports}var r={};return t.m=e,t.c=r,t.d=function(e,r,n){t.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:n})},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=189)}({0:function(t,r){t.exports=e},1:function(e,r){e.exports=t},189:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),r(190);var n=r(1);n.datepickerLocale("ru","ru",{closeText:"Закрыть",prevText:"&#x3C;Пред",nextText:"След&#x3E;",currentText:"Сегодня",monthNames:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthNamesShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],dayNames:["воскресенье","понедельник","вторник","среда","четверг","пятница","суббота"],dayNamesShort:["вск","пнд","втр","срд","чтв","птн","сбт"],dayNamesMin:["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],weekHeader:"Нед",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("ru",{buttonText:{month:"Месяц",week:"Неделя",day:"День",list:"Повестка дня"},allDayText:"Весь день",eventLimitText:function(e){return"+ ещё "+e},noEventsMessage:"Нет событий для отображения"})},190:function(e,t,r){!function(e,t){t(r(0))}(0,function(e){function t(e,t){var r=e.split("_");return t%10==1&&t%100!=11?r[0]:t%10>=2&&t%10<=4&&(t%100<10||t%100>=20)?r[1]:r[2]}function r(e,r,n){var s={ss:r?"секунда_секунды_секунд":"секунду_секунды_секунд",mm:r?"минута_минуты_минут":"минуту_минуты_минут",hh:"час_часа_часов",dd:"день_дня_дней",MM:"месяц_месяца_месяцев",yy:"год_года_лет"};
vendor: 4,956 bytes, lines 25442-25471
25442return"m"===n?r?"минута":"минуту":e+" "+t(s[n],+e)}var n=[/^янв/i,/^фев/i,/^мар/i,/^апр/i,/^ма[йя]/i,/^июн/i,/^июл/i,/^авг/i,/^сен/i,/^окт/i,/^ноя/i,/^дек/i];return e.defineLocale("ru",{months:{format:"января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря".split("_"),standalone:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_")},monthsShort:{format:"янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.".split("_"),standalone:"янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.".split("_")},weekdays:{standalone:"воскресенье_понедельник_вторник_среда_четверг_пятница_суббота".split("_"),format:"воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу".split("_"),isFormat:/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/},weekdaysShort:"вс_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"вс_пн_вт_ср_чт_пт_сб".split("_"),monthsParse:n,longMonthsParse:n,shortMonthsParse:n,monthsRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,monthsShortRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,monthsStrictRegex:/^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i,monthsShortStrictRegex:/^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., H:mm",LLLL:"dddd, D MMMM YYYY г., H:mm"},calendar:{sameDay:"[Сегодня, в] LT",nextDay:"[Завтра, в] LT",lastDay:"[Вчера, в] LT",nextWeek:function(e){if(e.week()===this.week())return 2===this.day()?"[Во] dddd, [в] LT":"[В] dddd, [в] LT";switch(this.day()){case 0:return"[В следующее] dddd, [в] LT";case 1:case 2:case 4:return"[В следующий] dddd, [в] LT";case 3:case 5:case 6:return"[В следующую] dddd, [в] LT"}},lastWeek:function(e){if(e.week()===this.week())return 2===this.day()?"[Во] dddd, [в] LT":"[В] dddd, [в] LT";switch(this.day()){case 0:return"[В прошлое] dddd, [в] LT";case 1:case 2:case 4:return"[В прошлый] dddd, [в] LT";case 3:case 5:case 6:return"[В прошлую] dddd, [в] LT"}},sameElse:"L"},relativeTime:{future:"через %s",past:"%s назад",s:"несколько секунд",ss:r,m:r,mm:r,h:"час",hh:r,d:"день",dd:r,M:"месяц",MM:r,y:"год",yy:r},meridiemParse:/ночи|утра|дня|вечера/i,isPM:function(e){return/^(дня|вечера)$/.test(e)},meridiem:function(e,t,r){return e<4?"ночи":e<12?"утра":e<17?"дня":"вечера"},dayOfMonthOrdinalParse:/\d{1,2}-(й|го|я)/,ordinal:function(e,t){switch(t){case"M":case"d":case"DDD":return e+"-й";case"D":return e+"-го";case"w":case"W":return e+"-я";default:return e}},week:{dow:1,doy:4}})})}})});
25443/**
25444 * @preserve jQuery DateTimePicker plugin v2.4.5
25445 * @homepage http://xdsoft.net/jqplugins/datetimepicker/
25446 * (c) 2014, Chupurnov Valeriy.
25447 */
25448/*global document,window,jQuery,setTimeout,clearTimeout,HighlightedDate,getCurrentValue*/
25449(function ($) {
25450	'use strict';
25451	var default_options  = {
25452		i18n: {
25453			ar: { // Arabic
25454				months: [
25455					"كانون الثاني", "شباط", "آذار", "نيسان", "مايو", "حزيران", "تموز", "آب", "أيلول", "تشرين الأول", "تشرين الثاني", "كانون الأول"
25456				],
25457				dayOfWeek: [
25458					"ن", "ث", "ع", "خ", "ج", "س", "ح"
25459				]
25460			},
25461			ro: { // Romanian
25462				months: [
25463					"ianuarie", "februarie", "martie", "aprilie", "mai", "iunie", "iulie", "august", "septembrie", "octombrie", "noiembrie", "decembrie"
25464				],
25465				dayOfWeek: [
25466					"l", "ma", "mi", "j", "v", "s", "d"
25467				]
25468			},
25469			id: { // Indonesian
25470				months: [
25471					"Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "
25471November", "Desember"
25472				],
25473				dayOfWeek: [
25474					"Min", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab"
25475				]
25476			},
25477			is: { // Icelandic
25478				months: [
25479					"Janúar", "Febrúar", "Mars", "Apríl", "Maí", "Júní", "Júlí", "Ágúst", "September", "Október", "Nóvember", "Desember"
25480				],
25481				dayOfWeek: [
25482					"Sun", "Mán", "Þrið", "Mið", "Fim", "Fös", "Lau"
25483				]
25484			},
25485			bg: { // Bulgarian
25486				months: [
25487					"Януари", "Февруари", "Март", "Април", "Май", "Юни", "Юли", "Август", "Септември", "Октомври", "Ноември", "Декември"
25488				],
25489				dayOfWeek: [
25490					"Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"
25491				]
25492			},
25493			fa: { // Persian/Farsi
25494				months: [
25495					'فروردین', 'اردیبهشت', 'خرداد', 'تیر', 'مرداد', 'شهریور', 'مهر', 'آبان', 'آذر', 'دی', 'بهمن', 'اسفند'
25496				],
25497				dayOfWeek: [
25498					'یکشنبه', 'دوشنبه', 'سه شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'
25499				]
25500			},
25501			ru: { // Russian
25502				months: [
25503					'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'
25504				],
25505				dayOfWeek: [
25506					"Вск", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"
25507				]
25508			},
25509			uk: { // Ukrainian
25510				months: [
25511					'Січень', 'Лютий', 'Березень', 'Квітень', 'Травень', 'Червень', 'Липень', 'Серпень', 'Вересень', 'Жовтень', 'Листопад', 'Грудень'
25512				],
25513				dayOfWeek: [
25514					"Ндл", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Сбт"
25515				]
25516			},
25517			en: { // English
25518				months: [
25519					"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "
25519November", "December"
25520				],
25521				dayOfWeek: [
25522					"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
25523				]
25524			},
25525			el: { // Ελληνικά
25526				months: [
25527					"Ιανουάριος", "Φεβρουάριος", "Μάρτιος", "Απρίλιος", "Μάιος", "Ιούνιος", "Ιούλιος", "Αύγουστος", "Σεπτέμβριος", "Οκτώβριος", "Νοέμβριος", "Δεκέμβριος"
25528				],
25529				dayOfWeek: [
25530					"Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ"
25531				]
25532			},
25533			de: { // German
25534				months: [
25535					'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'
25536				],
25537				dayOfWeek: [
25538					"So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"
25539				]
25540			},
25541			nl: { // Dutch
25542				months: [
25543					"januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"
25544				],
25545				dayOfWeek: [
25546					"zo", "ma", "di", "wo", "do", "vr", "za"
25547				]
25548			},
25549			tr: { // Turkish
25550				months: [
25551					"Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"
25552				],
25553				dayOfWeek: [
25554					"Paz", "Pts", "Sal", "Çar", "Per", "Cum", "Cts"
25555				]
25556			},
25557			fr: { //French
25558				months: [
25559					"Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"
25560				],
25561				dayOfWeek: [
25562					"Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"
25563				]
25564			},
25565			es: { // Spanish
25566				months: [
25567					"Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"
25568				],
25569				dayOfWeek: [
25570					"Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb"
25571				]
25572			},
25573			th: { // Thai
25574				months: [
25575					'มกราคม', 'กุมภาพันธ์', 'มีนาคม', 'เมษายน', 'พฤษภาคม', 'มิถุนายน', 'กรกฎาคม', 'สิงหาคม', 'กันยายน', 'ตุลาคม', 'พฤศจิกายน', 'ธันวาคม'
25576				],
25577				dayOfWeek: [
25578					'อา.', 'จ.', 'อ.', 'พ.', 'พฤ.', 'ศ.', 'ส.'
25579				]
25580			},
25581			pl: { // Polish
25582				months: [
25583					"styczeń", "luty", "marzec", "kwiecień", "maj", "czerwiec", "lipiec", "sierpień", "wrzesień", "październik", "listopad", "grudzień"
25584				],
25585				dayOfWeek: [
25586					"nd", "pn", "wt", "śr", "cz", "pt", "sb"
25587				]
25588			},
25589			pt: { // Portuguese
25590				months: [
25591					"Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"
25592				],
25593				dayOfWeek: [
25594					"Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab"
25595				]
25596			},
25597			ch: { // Simplified Chinese
25598				months: [
25599					"一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"
25600				],
25601				dayOfWeek: [
25602					"日", "一", "二", "三", "四", "五", "六"
25603				]
25604			},
25605			se: { // Swedish
25606				months: [
25607					"Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September",  "Oktober", "November", "December"
25608				],
25609				dayOfWeek: [
25610					"Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör"
25611				]
25612			},
25613			kr: { // Korean
25614				months: [
25615					"1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"
25616				],
25617				dayOfWeek: [
25618					"일", "월", "화", "수", "목", "금", "토"
25619				]
25620			},
25621			it: { // Italian
25622				months: [
25623					"Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"
25624				],
25625				dayOfWeek: [
25626					"Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"
25627				]
25628			},
25629			da: { // Dansk
25630				months: [
25631					"January", "Februar", "Marts", "April", "Maj", "Juni", "July", "August", "September", "Oktober", "November", "December"
25632				],
25633				dayOfWeek: [
25634					"Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør"
25635				]
25636			},
25637			no: { // Norwegian
25638				months: [
25639					"Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"
25640				],
25641				dayOfWeek: [
25642					"Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør"
25643				]
25644			},
25645			ja: { // Japanese
25646				months: [
25647					"1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"
25648				],
25649				dayOfWeek: [
25650					"日", "月", "火", "水", "木", "金", "土"
25651				]
25652			},
25653			vi: { // Vietnamese
25654				months: [
25655					"Tháng 1", "Tháng 2", "Tháng 3", "Tháng 4", "Tháng 5", "Tháng 6", "Tháng 7", "Tháng 8", "Tháng 9", "Tháng 10", "Tháng 11", "Tháng 12"
25656				],
25657				dayOfWeek: [
25658					"CN", "T2", "T3", "T4", "T5", "T6", "T7"
25659				]
25660			},
25661			sl: { // Slovenščina
25662				months: [
25663					"Januar", "Februar", "Marec", "April", "Maj", "Junij", "Julij", "Avgust", "September", "Oktober", "
25663November", "December"
25664				],
25665				dayOfWeek: [
25666					"Ned", "Pon", "Tor", "Sre", "Čet", "Pet", "Sob"
25667				]
25668			},
25669			cs: { // Čeština
25670				months: [
25671					"Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec"
25672				],
25673				dayOfWeek: [
25674					"Ne", "Po", "Út", "St", "Čt", "Pá", "So"
25675				]
25676			},
25677			hu: { // Hungarian
25678				months: [
25679					"Január", "Február", "Március", "Április", "Május", "Június", "Július", "Augusztus", "Szeptember", "Október", "November", "December"
25680				],
25681				dayOfWeek: [
25682					"Va", "Hé", "Ke", "Sze", "Cs", "Pé", "Szo"
25683				]
25684			},
25685			az: { //Azerbaijanian (Azeri)
25686				months: [
25687					"Yanvar", "Fevral", "Mart", "Aprel", "May", "Iyun", "Iyul", "Avqust", "Sentyabr", "Oktyabr", "Noyabr", "Dekabr"
25688				],
25689				dayOfWeek: [
25690					"B", "Be", "Ça", "Ç", "Ca", "C", "Ş"
25691				]
25692			},
25693			bs: { //Bosanski
25694				months: [
25695					"Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar"
25696				],
25697				dayOfWeek: [
25698					"Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub"
25699				]
25700			},
25701			ca: { //Català
25702				months: [
25703					"Gener", "Febrer", "Març", "Abril", "Maig", "Juny", "Juliol", "Agost", "Setembre", "Octubre", "Novembre", "Desembre"
25704				],
25705				dayOfWeek: [
25706					"Dg", "Dl", "Dt", "Dc", "Dj", "Dv", "Ds"
25707				]
25708			},
25709			'en-GB': { //English (British)
25710				months: [
25711					"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "
25711November", "December"
25712				],
25713				dayOfWeek: [
25714					"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
25715				]
25716			},
25717			et: { //"Eesti"
25718				months: [
25719					"Jaanuar", "Veebruar", "Märts", "Aprill", "Mai", "Juuni", "Juuli", "August", "September", "Oktoober", "November", "Detsember"
25720				],
25721				dayOfWeek: [
25722					"P", "E", "T", "K", "N", "R", "L"
25723				]
25724			},
25725			eu: { //Euskara
25726				months: [
25727					"Urtarrila", "Otsaila", "Martxoa", "Apirila", "Maiatza", "Ekaina", "Uztaila", "Abuztua", "Iraila", "Urria", "Azaroa", "Abendua"
25728				],
25729				dayOfWeek: [
25730					"Ig.", "Al.", "Ar.", "Az.", "Og.", "Or.", "La."
25731				]
25732			},
25733			fi: { //Finnish (Suomi)
25734				months: [
25735					"Tammikuu", "Helmikuu", "Maaliskuu", "Huhtikuu", "Toukokuu", "Kesäkuu", "Heinäkuu", "Elokuu", "Syyskuu", "Lokakuu", "Marraskuu", "Joulukuu"
25736				],
25737				dayOfWeek: [
25738					"Su", "Ma", "Ti", "Ke", "To", "Pe", "La"
25739				]
25740			},
25741			gl: { //Galego
25742				months: [
25743					"Xan", "Feb", "Maz", "Abr", "Mai", "Xun", "Xul", "Ago", "Set", "Out", "Nov", "Dec"
25744				],
25745				dayOfWeek: [
25746					"Dom", "Lun", "Mar", "Mer", "Xov", "Ven", "Sab"
25747				]
25748			},
25749			hr: { //Hrvatski
25750				months: [
25751					"Siječanj", "Veljača", "Ožujak", "Travanj", "Svibanj", "Lipanj", "Srpanj", "Kolovoz", "Rujan", "Listopad", "Studeni", "Prosinac"
25752				],
25753				dayOfWeek: [
25754					"Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub"
25755				]
25756			},
25757			ko: { //Korean (한국어)
25758				months: [
25759					"1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"
25760				],
25761				dayOfWeek: [
25762					"일", "월", "화", "수", "목", "금", "토"
25763				]
25764			},
25765			lt: { //Lithuanian (lietuvių)
25766				months: [
25767					"Sausio", "Vasario", "Kovo", "Balandžio", "Gegužės", "Birželio", "Liepos", "Rugpjūčio", "Rugsėjo", "Spalio", "Lapkričio", "Gruodžio"
25768				],
25769				dayOfWeek: [
25770					"Sek", "Pir", "Ant", "Tre", "Ket", "Pen", "Šeš"
25771				]
25772			},
25773			lv: { //Latvian (Latviešu)
25774				months: [
25775					"Janvāris", "Februāris", "Marts", "Aprīlis ", "Maijs", "Jūnijs", "Jūlijs", "Augusts", "Septembris", "Oktobris", "Novembris", "Decembris"
25776				],
25777				dayOfWeek: [
25778					"Sv", "Pr", "Ot", "Tr", "Ct", "Pk", "St"
25779				]
25780			},
25781			mk: { //Macedonian (Македонски)
25782				months: [
25783					"јануари", "февруари", "март", "април", "мај", "јуни", "јули", "август", "септември", "октомври", "ноември", "декември"
25784				],
25785				dayOfWeek: [
25786					"нед", "пон", "вто", "сре", "чет", "пет", "саб"
25787				]
25788			},
25789			mn: { //Mongolian (Монгол)
25790				months: [
25791					"1-р сар", "2-р сар", "3-р сар", "4-р сар", "5-р сар", "6-р сар", "7-р сар", "8-р сар", "9-р сар", "10-р сар", "11-р сар", "12-р сар"
25792				],
25793				dayOfWeek: [
25794					"Дав", "Мяг", "Лха", "Пүр", "Бсн", "Бям", "Ням"
25795				]
25796			},
25797			'pt-BR': { //Português(Brasil)
25798				months: [
25799					"Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"
25800				],
25801				dayOfWeek: [
25802					"Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"
25803				]
25804			},
25805			sk: { //Slovenčina
25806				months: [
25807					"Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Október", "November", "December"
25808				],
25809				dayOfWeek: [
25810					"Ne", "Po", "Ut", "St", "Å t", "Pi", "So"
25811				]
25812			},
25813			sq: { //Albanian (Shqip)
25814				months: [
25815					"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "
vendor: 21,325 bytes, lines 25815-26467
25815November", "December"
25816				],
25817				dayOfWeek: [
25818					"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
25819				]
25820			},
25821			'sr-YU': { //Serbian (Srpski)
25822				months: [
25823					"Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar"
25824				],
25825				dayOfWeek: [
25826					"Ned", "Pon", "Uto", "Sre", "čet", "Pet", "Sub"
25827				]
25828			},
25829			sr: { //Serbian Cyrillic (Српски)
25830				months: [
25831					"јануар", "фебруар", "март", "април", "мај", "јун", "јул", "август", "септембар", "октобар", "новембар", "децембар"
25832				],
25833				dayOfWeek: [
25834					"нед", "пон", "уто", "сре", "чет", "пет", "суб"
25835				]
25836			},
25837			sv: { //Svenska
25838				months: [
25839					"Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December"
25840				],
25841				dayOfWeek: [
25842					"Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör"
25843				]
25844			},
25845			'zh-TW': { //Traditional Chinese (繁體中文)
25846				months: [
25847					"一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"
25848				],
25849				dayOfWeek: [
25850					"日", "一", "二", "三", "四", "五", "六"
25851				]
25852			},
25853			zh: { //Simplified Chinese (简体中文)
25854				months: [
25855					"一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"
25856				],
25857				dayOfWeek: [
25858					"日", "一", "二", "三", "四", "五", "六"
25859				]
25860			},
25861			he: { //Hebrew (עברית)
25862				months: [
25863					'ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר'
25864				],
25865				dayOfWeek: [
25866					'א\'', 'ב\'', 'ג\'', 'ד\'', 'ה\'', 'ו\'', 'שבת'
25867				]
25868			},
25869			hy: { // Armenian
25870				months: [
25871					"Հունվար", "Փետրվար", "Մարտ", "Ապրիլ", "Մայիս", "Հունիս", "Հուլիս", "Օգոստոս", "Սեպտեմբեր", "Հոկտեմբեր", "Նոյեմբեր", "Դեկտեմբեր"
25872				],
25873				dayOfWeek: [
25874					"Կի", "Երկ", "Երք", "Չոր", "Հնգ", "Ուրբ", "Շբթ"
25875				]
25876			},
25877            kg: { // Kyrgyz
25878                months: [
25879                    'Үчтүн айы', 'Бирдин айы', 'Жалган Куран', 'Чын Куран', 'Бугу', 'Кулжа', 'Теке', 'Баш Оона', 'Аяк Оона', 'Тогуздун айы', 'Жетинин айы', 'Бештин айы'
25880                ],
25881                dayOfWeek: [
25882                    "Жек", "Дүй", "Шей", "Шар", "Бей", "Жум", "Ише"
25883                ]
25884            }
25885		},
25886		value: '',
25887		lang: 'en',
25888
25889		format:	'Y/m/d H:i',
25890		formatTime:	'H:i',
25891		formatDate:	'Y/m/d',
25892
25893		startDate:	false, // new Date(), '1986/12/08', '-1970/01/05','-1970/01/05',
25894		step: 60,
25895		monthChangeSpinner: true,
25896
25897		closeOnDateSelect: false,
25898		closeOnTimeSelect: true,
25899		closeOnWithoutClick: true,
25900		closeOnInputClick: true,
25901
25902		timepicker: true,
25903		datepicker: true,
25904		weeks: false,
25905
25906		defaultTime: false,	// use formatTime format (ex. '10:00' for formatTime:	'H:i')
25907		defaultDate: false,	// use formatDate format (ex new Date() or '1986/12/08' or '-1970/01/05' or '-1970/01/05')
25908
25909		minDate: false,
25910		maxDate: false,
25911		minTime: false,
25912		maxTime: false,
25913		disabledMinTime: false,
25914		disabledMaxTime: false,
25915
25916		allowTimes: [],
25917		opened: false,
25918		initTime: true,
25919		inline: false,
25920		theme: '',
25921
25922		onSelectDate: function () {},
25923		onSelectTime: function () {},
25924		onChangeMonth: function () {},
25925		onChangeYear: function () {},
25926		onChangeDateTime: function () {},
25927		onShow: function () {},
25928		onClose: function () {},
25929		onGenerate: function () {},
25930
25931		withoutCopyright: true,
25932		inverseButton: false,
25933		hours12: false,
25934		next: 'xdsoft_next',
25935		prev : 'xdsoft_prev',
25936		dayOfWeekStart: 0,
25937		parentID: 'body',
25938		timeHeightInTimePicker: 25,
25939		timepickerScrollbar: true,
25940		todayButton: true,
25941		prevButton: true,
25942		nextButton: true,
25943		defaultSelect: true,
25944
25945		scrollMonth: true,
25946		scrollTime: true,
25947		scrollInput: true,
25948
25949		lazyInit: false,
25950		mask: false,
25951		validateOnBlur: true,
25952		allowBlank: true,
25953		yearStart: 1950,
25954		yearEnd: 2050,
25955		monthStart: 0,
25956		monthEnd: 11,
25957		style: '',
25958		id: '',
25959		fixed: false,
25960		roundTime: 'round', // ceil, floor
25961		className: '',
25962		weekends: [],
25963		highlightedDates: [],
25964		highlightedPeriods: [],
25965		disabledDates : [],
25966		disabledWeekDays: [],
25967		yearOffset: 0,
25968		beforeShowDay: null,
25969
25970		enterLikeTab: true,
25971        showApplyButton: false
25972	};
25973	// fix for ie8
25974	if (!window.getComputedStyle) {
25975		window.getComputedStyle = function (el, pseudo) {
25976			this.el = el;
25977			this.getPropertyValue = function (prop) {
25978				var re = /(\-([a-z]){1})/g;
25979				if (prop === 'float') {
25980					prop = 'styleFloat';
25981				}
25982				if (re.test(prop)) {
25983					prop = prop.replace(re, function (a, b, c) {
25984						return c.toUpperCase();
25985					});
25986				}
25987				return el.currentStyle[prop] || null;
25988			};
25989			return this;
25990		};
25991	}
25992	if (!Array.prototype.indexOf) {
25993		Array.prototype.indexOf = function (obj, start) {
25994			var i, j;
25995			for (i = (start || 0), j = this.length; i < j; i += 1) {
25996				if (this[i] === obj) { return i; }
25997			}
25998			return -1;
25999		};
26000	}
26001	Date.prototype.countDaysInMonth = function () {
26002		return new Date(this.getFullYear(), this.getMonth() + 1, 0).getDate();
26003	};
26004	$.fn.xdsoftScroller = function (percent) {
26005		return this.each(function () {
26006			var timeboxparent = $(this),
26007				pointerEventToXY = function (e) {
26008					var out = {x: 0, y: 0},
26009						touch;
26010					if (e.type === 'touchstart' || e.type === 'touchmove' || e.type === 'touchend' || e.type === 'touchcancel') {
26011						touch  = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
26012						out.x = touch.clientX;
26013						out.y = touch.clientY;
26014					} else if (e.type === 'mousedown' || e.type === 'mouseup' || e.type === 'mousemove' || e.type === 'mouseover' || e.type === 'mouseout' || e.type === 'mouseenter' || e.type === 'mouseleave') {
26015						out.x = e.clientX;
26016						out.y = e.clientY;
26017					}
26018					return out;
26019				},
26020				move = 0,
26021				timebox,
26022				parentHeight,
26023				height,
26024				scrollbar,
26025				scroller,
26026				maximumOffset = 100,
26027				start = false,
26028				startY = 0,
26029				startTop = 0,
26030				h1 = 0,
26031				touchStart = false,
26032				startTopScroll = 0,
26033				calcOffset = function () {};
26034			if (percent === 'hide') {
26035				timeboxparent.find('.xdsoft_scrollbar').hide();
26036				return;
26037			}
26038			if (!$(this).hasClass('xdsoft_scroller_box')) {
26039				timebox = timeboxparent.children().eq(0);
26040				parentHeight = timeboxparent[0].clientHeight;
26041				height = timebox[0].offsetHeight;
26042				scrollbar = $('<div class="xdsoft_scrollbar"></div>');
26043				scroller = $('<div class="xdsoft_scroller"></div>');
26044				scrollbar.append(scroller);
26045
26046				timeboxparent.addClass('xdsoft_scroller_box').append(scrollbar);
26047				calcOffset = function calcOffset(event) {
26048					var offset = pointerEventToXY(event).y - startY + startTopScroll;
26049					if (offset < 0) {
26050						offset = 0;
26051					}
26052					if (offset + scroller[0].offsetHeight > h1) {
26053						offset = h1 - scroller[0].offsetHeight;
26054					}
26055					timeboxparent.trigger('scroll_element.xdsoft_scroller', [maximumOffset ? offset / maximumOffset : 0]);
26056				};
26057
26058				scroller
26059					.on('touchstart.xdsoft_scroller mousedown.xdsoft_scroller', function (event) {
26060						if (!parentHeight) {
26061							timeboxparent.trigger('resize_scroll.xdsoft_scroller', [percent]);
26062						}
26063
26064						startY = pointerEventToXY(event).y;
26065						startTopScroll = parseInt(scroller.css('margin-top'), 10);
26066						h1 = scrollbar[0].offsetHeight;
26067
26068						if (event.type === 'mousedown') {
26069							if (document) {
26070								$(document.body).addClass('xdsoft_noselect');
26071							}
26072							$([document.body, window]).on('mouseup.xdsoft_scroller', function arguments_callee() {
26073								$([document.body, window]).off('mouseup.xdsoft_scroller', arguments_callee)
26074									.off('mousemove.xdsoft_scroller', calcOffset)
26075									.removeClass('xdsoft_noselect');
26076							});
26077							$(document.body).on('mousemove.xdsoft_scroller', calcOffset);
26078						} else {
26079							touchStart = true;
26080							event.stopPropagation();
26081							event.preventDefault();
26082						}
26083					})
26084					.on('touchmove', function (event) {
26085						if (touchStart) {
26086							event.preventDefault();
26087							calcOffset(event);
26088						}
26089					})
26090					.on('touchend touchcancel', function (event) {
26091						touchStart =  false;
26092						startTopScroll = 0;
26093					});
26094
26095				timeboxparent
26096					.on('scroll_element.xdsoft_scroller', function (event, percentage) {
26097						if (!parentHeight) {
26098							timeboxparent.trigger('resize_scroll.xdsoft_scroller', [percentage, true]);
26099						}
26100						percentage = percentage > 1 ? 1 : (percentage < 0 || isNaN(percentage)) ? 0 : percentage;
26101
26102						scroller.css('margin-top', maximumOffset * percentage);
26103
26104						setTimeout(function () {
26105							timebox.css('marginTop', -parseInt((timebox[0].offsetHeight - parentHeight) * percentage, 10));
26106						}, 10);
26107					})
26108					.on('resize_scroll.xdsoft_scroller', function (event, percentage, noTriggerScroll) {
26109						var percent, sh;
26110						parentHeight = timeboxparent[0].clientHeight;
26111						height = timebox[0].offsetHeight;
26112						percent = parentHeight / height;
26113						sh = percent * scrollbar[0].offsetHeight;
26114						if (percent > 1) {
26115							scroller.hide();
26116						} else {
26117							scroller.show();
26118							scroller.css('height', parseInt(sh > 10 ? sh : 10, 10));
26119							maximumOffset = scrollbar[0].offsetHeight - scroller[0].offsetHeight;
26120							if (noTriggerScroll !== true) {
26121								timeboxparent.trigger('scroll_element.xdsoft_scroller', [percentage || Math.abs(parseInt(timebox.css('marginTop'), 10)) / (height - parentHeight)]);
26122							}
26123						}
26124					});
26125
26126				timeboxparent.on('mousewheel', function (event) {
26127					var top = Math.abs(parseInt(timebox.css('marginTop'), 10));
26128
26129					top = top - (event.deltaY * 20);
26130					if (top < 0) {
26131						top = 0;
26132					}
26133
26134					timeboxparent.trigger('scroll_element.xdsoft_scroller', [top / (height - parentHeight)]);
26135					event.stopPropagation();
26136					return false;
26137				});
26138
26139				timeboxparent.on('touchstart', function (event) {
26140					start = pointerEventToXY(event);
26141					startTop = Math.abs(parseInt(timebox.css('marginTop'), 10));
26142				});
26143
26144				timeboxparent.on('touchmove', function (event) {
26145					if (start) {
26146						event.preventDefault();
26147						var coord = pointerEventToXY(event);
26148						timeboxparent.trigger('scroll_element.xdsoft_scroller', [(startTop - (coord.y - start.y)) / (height - parentHeight)]);
26149					}
26150				});
26151
26152				timeboxparent.on('touchend touchcancel', function (event) {
26153					start = false;
26154					startTop = 0;
26155				});
26156			}
26157			timeboxparent.trigger('resize_scroll.xdsoft_scroller', [percent]);
26158		});
26159	};
26160
26161	$.fn.datetimepicker = function (opt) {
26162		var KEY0 = 48,
26163			KEY9 = 57,
26164			_KEY0 = 96,
26165			_KEY9 = 105,
26166			CTRLKEY = 17,
26167			DEL = 46,
26168			ENTER = 13,
26169			ESC = 27,
26170			BACKSPACE = 8,
26171			ARROWLEFT = 37,
26172			ARROWUP = 38,
26173			ARROWRIGHT = 39,
26174			ARROWDOWN = 40,
26175			TAB = 9,
26176			F5 = 116,
26177			AKEY = 65,
26178			CKEY = 67,
26179			VKEY = 86,
26180			ZKEY = 90,
26181			YKEY = 89,
26182			ctrlDown	=	false,
26183			options = ($.isPlainObject(opt) || !opt) ? $.extend(true, {}, default_options, opt) : $.extend(true, {}, default_options),
26184
26185			lazyInitTimer = 0,
26186			createDateTimePicker,
26187			destroyDateTimePicker,
26188
26189			lazyInit = function (input) {
26190				input
26191					.on('open.xdsoft focusin.xdsoft mousedown.xdsoft', function initOnActionCallback(event) {
26192						if (input.is(':disabled') || input.data('xdsoft_datetimepicker')) {
26193							return;
26194						}
26195						clearTimeout(lazyInitTimer);
26196						lazyInitTimer = setTimeout(function () {
26197
26198							if (!input.data('xdsoft_datetimepicker')) {
26199								createDateTimePicker(input);
26200							}
26201							input
26202								.off('open.xdsoft focusin.xdsoft mousedown.xdsoft', initOnActionCallback)
26203								.trigger('open.xdsoft');
26204						}, 100);
26205					});
26206			};
26207
26208		createDateTimePicker = function (input) {
26209			var datetimepicker = $('<div class="xdsoft_datetimepicker xdsoft_noselect"></div>'),
26210				xdsoft_copyright = $('<div class="xdsoft_copyright"><a target="_blank" href="http://xdsoft.net/jqplugins/datetimepicker/">xdsoft.net</a></div>'),
26211				datepicker = $('<div class="xdsoft_datepicker active"></div>'),
26212				mounth_picker = $('<div class="xdsoft_mounthpicker"><button type="button" class="xdsoft_prev"></button><button type="button" class="xdsoft_today_button"></button>' +
26213					'<div class="xdsoft_label xdsoft_month"><span></span><i></i></div>' +
26214					'<div class="xdsoft_label xdsoft_year"><span></span><i></i></div>' +
26215					'<button type="button" class="xdsoft_next"></button></div>'),
26216				calendar = $('<div class="xdsoft_calendar"></div>'),
26217				timepicker = $('<div class="xdsoft_timepicker active"><button type="button" class="xdsoft_prev"></button><div class="xdsoft_time_box"></div><button type="button" class="xdsoft_next"></button></div>'),
26218				timeboxparent = timepicker.find('.xdsoft_time_box').eq(0),
26219				timebox = $('<div class="xdsoft_time_variant"></div>'),
26220                applyButton = $('<button type="button" class="xdsoft_save_selected blue-gradient-button">Save Selected</button>'),
26221				/*scrollbar = $('<div class="xdsoft_scrollbar"></div>'),
26222				scroller = $('<div class="xdsoft_scroller"></div>'),*/
26223				monthselect = $('<div class="xdsoft_select xdsoft_monthselect"><div></div></div>'),
26224				yearselect = $('<div class="xdsoft_select xdsoft_yearselect"><div></div></div>'),
26225				triggerAfterOpen = false,
26226				XDSoft_datetime,
26227				//scroll_element,
26228				xchangeTimer,
26229				timerclick,
26230				current_time_index,
26231				setPos,
26232				timer = 0,
26233				timer1 = 0,
26234				_xdsoft_datetime;
26235
26236			if (options.id) {
26237				datetimepicker.attr('id', options.id);
26238			}
26239			if (options.style) {
26240				datetimepicker.attr('style', options.style);
26241			}
26242			if (options.weeks) {
26243				datetimepicker.addClass('xdsoft_showweeks');
26244			}
26245
26246			datetimepicker.addClass('xdsoft_' + options.theme);
26247			datetimepicker.addClass(options.className);
26248
26249			mounth_picker
26250				.find('.xdsoft_month span')
26251					.after(monthselect);
26252			mounth_picker
26253				.find('.xdsoft_year span')
26254					.after(yearselect);
26255
26256			mounth_picker
26257				.find('.xdsoft_month,.xdsoft_year')
26258					.on('mousedown.xdsoft', function (event) {
26259					var select = $(this).find('.xdsoft_select').eq(0),
26260						val = 0,
26261						top = 0,
26262						visible = select.is(':visible'),
26263						items,
26264						i;
26265
26266					mounth_picker
26267						.find('.xdsoft_select')
26268							.hide();
26269					if (_xdsoft_datetime.currentTime) {
26270						val = _xdsoft_datetime.currentTime[$(this).hasClass('xdsoft_month') ? 'getMonth' : 'getFullYear']();
26271					}
26272
26273					select[visible ? 'hide' : 'show']();
26274					for (items = select.find('div.xdsoft_option'), i = 0; i < items.length; i += 1) {
26275						if (items.eq(i).data('value') === val) {
26276							break;
26277						} else {
26278							top += items[0].offsetHeight;
26279						}
26280					}
26281
26282					select.xdsoftScroller(top / (select.children()[0].offsetHeight - (select[0].clientHeight)));
26283					event.stopPropagation();
26284					return false;
26285				});
26286
26287			mounth_picker
26288				.find('.xdsoft_select')
26289					.xdsoftScroller()
26290				.on('mousedown.xdsoft', function (event) {
26291					event.stopPropagation();
26292					event.preventDefault();
26293				})
26294				.on('mousedown.xdsoft', '.xdsoft_option', function (event) {
26295
26296					if (_xdsoft_datetime.currentTime === undefined || _xdsoft_datetime.currentTime === null) {
26297						_xdsoft_datetime.currentTime = _xdsoft_datetime.now();
26298					}
26299
26300					var year = _xdsoft_datetime.currentTime.getFullYear();
26301					if (_xdsoft_datetime && _xdsoft_datetime.currentTime) {
26302						_xdsoft_datetime.currentTime[$(this).parent().parent().hasClass('xdsoft_monthselect') ? 'setMonth' : 'setFullYear']($(this).data('value'));
26303					}
26304
26305					$(this).parent().parent().hide();
26306
26307					datetimepicker.trigger('xchange.xdsoft');
26308					if (options.onChangeMonth && $.isFunction(options.onChangeMonth)) {
26309						options.onChangeMonth.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
26310					}
26311
26312					if (year !== _xdsoft_datetime.currentTime.getFullYear() && $.isFunction(options.onChangeYear)) {
26313						options.onChangeYear.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
26314					}
26315				});
26316
26317			datetimepicker.setOptions = function (_options) {
26318				var highlightedDates = {},
26319					getCaretPos = function (input) {
26320						try {
26321							if (document.selection && document.selection.createRange) {
26322								var range = document.selection.createRange();
26323								return range.getBookmark().charCodeAt(2) - 2;
26324							}
26325							if (input.setSelectionRange) {
26326								return input.selectionStart;
26327							}
26328						} catch (e) {
26329							return 0;
26330						}
26331					},
26332					setCaretPos = function (node, pos) {
26333						node = (typeof node === "string" || node instanceof String) ? document.getElementById(node) : node;
26334						if (!node) {
26335							return false;
26336						}
26337						if (node.createTextRange) {
26338							var textRange = node.createTextRange();
26339							textRange.collapse(true);
26340							textRange.moveEnd('character', pos);
26341							textRange.moveStart('character', pos);
26342							textRange.select();
26343							return true;
26344						}
26345						if (node.setSelectionRange) {
26346							node.setSelectionRange(pos, pos);
26347							return true;
26348						}
26349						return false;
26350					},
26351					isValidValue = function (mask, value) {
26352						var reg = mask
26353							.replace(/([\[\]\/\{\}\(\)\-\.\+]{1})/g, '\\$1')
26354							.replace(/_/g, '{digit+}')
26355							.replace(/([0-9]{1})/g, '{digit$1}')
26356							.replace(/\{digit([0-9]{1})\}/g, '[0-$1_]{1}')
26357							.replace(/\{digit[\+]\}/g, '[0-9_]{1}');
26358						return (new RegExp(reg)).test(value);
26359					};
26360				options = $.extend(true, {}, options, _options);
26361
26362				if (_options.allowTimes && $.isArray(_options.allowTimes) && _options.allowTimes.length) {
26363					options.allowTimes = $.extend(true, [], _options.allowTimes);
26364				}
26365
26366				if (_options.weekends && $.isArray(_options.weekends) && _options.weekends.length) {
26367					options.weekends = $.extend(true, [], _options.weekends);
26368				}
26369
26370				if (_options.highlightedDates && $.isArray(_options.highlightedDates) && _options.highlightedDates.length) {
26371					$.each(_options.highlightedDates, function (index, value) {
26372						var splitData = $.map(value.split(','), $.trim),
26373							exDesc,
26374							hDate = new HighlightedDate(Date.parseDate(splitData[0], options.formatDate), splitData[1], splitData[2]), // date, desc, style
26375							keyDate = hDate.date.dateFormat(options.formatDate);
26376						if (highlightedDates[keyDate] !== undefined) {
26377							exDesc = highlightedDates[keyDate].desc;
26378							if (exDesc && exDesc.length && hDate.desc && hDate.desc.length) {
26379								highlightedDates[keyDate].desc = exDesc + "\n" + hDate.desc;
26380							}
26381						} else {
26382							highlightedDates[keyDate] = hDate;
26383						}
26384					});
26385
26386					options.highlightedDates = $.extend(true, [], highlightedDates);
26387				}
26388
26389				if (_options.highlightedPeriods && $.isArray(_options.highlightedPeriods) && _options.highlightedPeriods.length) {
26390					highlightedDates = $.extend(true, [], options.highlightedDates);
26391					$.each(_options.highlightedPeriods, function (index, value) {
26392						var splitData = $.map(value.split(','), $.trim),
26393							dateTest = Date.parseDate(splitData[0], options.formatDate), // start date
26394							dateEnd = Date.parseDate(splitData[1], options.formatDate),
26395							desc = splitData[2],
26396							hDate,
26397							keyDate,
26398							exDesc,
26399							style = splitData[3];
26400
26401						while (dateTest <= dateEnd) {
26402							hDate = new HighlightedDate(dateTest, desc, style);
26403							keyDate = dateTest.dateFormat(options.formatDate);
26404							dateTest.setDate(dateTest.getDate() + 1);
26405							if (highlightedDates[keyDate] !== undefined) {
26406								exDesc = highlightedDates[keyDate].desc;
26407								if (exDesc && exDesc.length && hDate.desc && hDate.desc.length) {
26408									highlightedDates[keyDate].desc = exDesc + "\n" + hDate.desc;
26409								}
26410							} else {
26411								highlightedDates[keyDate] = hDate;
26412							}
26413						}
26414					});
26415
26416					options.highlightedDates = $.extend(true, [], highlightedDates);
26417				}
26418
26419				if (_options.disabledDates && $.isArray(_options.disabledDates) && _options.disabledDates.length) {
26420					options.disabledDates = $.extend(true, [], _options.disabledDates);
26421				}
26422
26423				if (_options.disabledWeekDays && $.isArray(_options.disabledWeekDays) && _options.disabledWeekDays.length) {
26424				    options.disabledWeekDays = $.extend(true, [], _options.disabledWeekDays);
26425				}
26426
26427				if ((options.open || options.opened) && (!options.inline)) {
26428					input.trigger('open.xdsoft');
26429				}
26430
26431				if (options.inline) {
26432					triggerAfterOpen = true;
26433					datetimepicker.addClass('xdsoft_inline');
26434					input.after(datetimepicker).hide();
26435				}
26436
26437				if (options.inverseButton) {
26438					options.next = 'xdsoft_prev';
26439					options.prev = 'xdsoft_next';
26440				}
26441
26442				if (options.datepicker) {
26443					datepicker.addClass('active');
26444				} else {
26445					datepicker.removeClass('active');
26446				}
26447
26448				if (options.timepicker) {
26449					timepicker.addClass('active');
26450				} else {
26451					timepicker.removeClass('active');
26452				}
26453
26454				if (options.value) {
26455					_xdsoft_datetime.setCurrentTime(options.value);
26456					if (input && input.val) {
26457						input.val(_xdsoft_datetime.str);
26458					}
26459				}
26460
26461				if (isNaN(options.dayOfWeekStart)) {
26462					options.dayOfWeekStart = 0;
26463				} else {
26464					options.dayOfWeekStart = parseInt(options.dayOfWeekStart, 10) % 7;
26465				}
26466
26467				if (!options.timepickerScrollbar) {
26468					timeboxparent.xdsoftScroller('hide');
26469				}
26470
26471				if (options.minDate && /^-(.*)$/.test(options.minDate)) {
26472					options.minDate = _xdsoft_datetime.strToDateTime(options.minDate).dateFormat(options.formatDate);
26473				}
26474
26475				if (options.maxDate &&  /^\+(.*)$/.test(options.maxDate)) {
26476					options.maxDate = _xdsoft_datetime.strToDateTime(options.maxDate).dateFormat(options.formatDate);
26477				}
26478
26479				applyButton.toggle(options.showApplyButton);
26480
26481				mounth_picker
26482					.find('.xdsoft_today_button')
26483						.css('visibility', !options.todayButton ? 'hidden' : 'visible');
26484
26485				mounth_picker
26486					.find('.' + options.prev)
26487						.css('visibility', !options.prevButton ? 'hidden' : 'visible');
26488
26489				mounth_picker
26490					.find('.' + options.next)
26491						.css('visibility', !options.nextButton ? 'hidden' : 'visible');
26492
26493				if (options.mask) {
26494					input.off('keydown.xdsoft');
26495
26496					if (options.mask === true) {
26497						options.mask = options.format
26498							.replace(/Y/g, '9999')
26499							.replace(/F/g, '9999')
26500							.replace(/m/g, '19')
26501							.replace(/d/g, '39')
26502							.replace(/H/g, '29')
26503							.replace(/i/g, '59')
26504							.replace(/s/g, '59');
26505					}
26506
26507					if ($.type(options.mask) === 'string') {
26508						if (!isValidValue(options.mask, input.val())) {
26509							input.val(options.mask.replace(/[0-9]/g, '_'));
26510						}
26511
26512						input.on('keydown.xdsoft', function (event) {
26513							var val = this.value,
26514								key = event.which,
26515								pos,
26516								digit;
26517
26518							if (((key >= KEY0 && key <= KEY9) || (key >= _KEY0 && key <= _KEY9)) || (key === BACKSPACE || key === DEL)) {
26519								pos = getCaretPos(this);
26520								digit = (key !== BACKSPACE && key !== DEL) ? String.fromCharCode((_KEY0 <= key && key <= _KEY9) ? key - KEY0 : key) : '_';
26521
26522								if ((key === BACKSPACE || key === DEL) && pos) {
26523									pos -= 1;
26524									digit = '_';
26525								}
26526
26527								while (/[^0-9_]/.test(options.mask.substr(pos, 1)) && pos < options.mask.length && pos > 0) {
26528									pos += (key === BACKSPACE || key === DEL) ? -1 : 1;
26529								}
26530
26531								val = val.substr(0, pos) + digit + val.substr(pos + 1);
26532								if ($.trim(val) === '') {
26533									val = options.mask.replace(/[0-9]/g, '_');
26534								} else {
26535									if (pos === options.mask.length) {
26536										event.preventDefault();
26537										return false;
26538									}
26539								}
26540
26541								pos += (key === BACKSPACE || key === DEL) ? 0 : 1;
26542								while (/[^0-9_]/.test(options.mask.substr(pos, 1)) && pos < options.mask.length && pos > 0) {
26543									pos += (key === BACKSPACE || key === DEL) ? -1 : 1;
26544								}
26545
26546								if (isValidValue(options.mask, val)) {
26547									this.value = val;
26548									setCaretPos(this, pos);
26549								} else if ($.trim(val) === '') {
26550									this.value = options.mask.replace(/[0-9]/g, '_');
26551								} else {
26552									input.trigger('error_input.xdsoft');
26553								}
26554							} else {
26555								if (([AKEY, CKEY, VKEY, ZKEY, YKEY].indexOf(key) !== -1 && ctrlDown) || [ESC, ARROWUP, ARROWDOWN, ARROWLEFT, ARROWRIGHT, F5, CTRLKEY, TAB, ENTER].indexOf(key) !== -1) {
26556									return true;
26557								}
26558							}
26559
26560							event.preventDefault();
26561							return false;
26562						});
26563					}
26564				}
26565				if (options.validateOnBlur) {
26566					input
26567						.off('blur.xdsoft')
26568						.on('blur.xdsoft', function () {
26569							if (options.allowBlank && !$.trim($(this).val()).length) {
26570								$(this).val(null);
26571								datetimepicker.data('xdsoft_datetime').empty();
26572							} else if (!Date.parseDate($(this).val(), options.format)) {
26573								var splittedHours   = +([$(this).val()[0], $(this).val()[1]].join('')),
26574									splittedMinutes = +([$(this).val()[2], $(this).val()[3]].join(''));
26575
26576								// parse the numbers as 0312 => 03:12
26577								if (!options.datepicker && options.timepicker && splittedHours >= 0 && splittedHours < 24 && splittedMinutes >= 0 && splittedMinutes < 60) {
26578									$(this).val([splittedHours, splittedMinutes].map(function (item) {
26579										return item > 9 ? item : '0' + item;
26580									}).join(':'));
26581								} else {
26582									$(this).val((_xdsoft_datetime.now()).dateFormat(options.format));
26583								}
26584
26585								datetimepicker.data('xdsoft_datetime').setCurrentTime($(this).val());
26586							} else {
26587								datetimepicker.data('xdsoft_datetime').setCurrentTime($(this).val());
26588							}
26589
26590							datetimepicker.trigger('changedatetime.xdsoft');
26591						});
26592				}
26593				options.dayOfWeekStartPrev = (options.dayOfWeekStart === 0) ? 6 : options.dayOfWeekStart - 1;
26594
26595				datetimepicker
26596					.trigger('xchange.xdsoft')
26597					.trigger('afterOpen.xdsoft');
26598			};
26599
26600			datetimepicker
26601				.data('options', options)
26602				.on('mousedown.xdsoft', function (event) {
26603					event.stopPropagation();
26604					event.preventDefault();
26605					yearselect.hide();
26606					monthselect.hide();
26607					return false;
vendor: 11,069 bytes, lines 26608-26960
26608				});
26609
26610			//scroll_element = timepicker.find('.xdsoft_time_box');
26611			timeboxparent.append(timebox);
26612			timeboxparent.xdsoftScroller();
26613
26614			datetimepicker.on('afterOpen.xdsoft', function () {
26615				timeboxparent.xdsoftScroller();
26616			});
26617
26618			datetimepicker
26619				.append(datepicker)
26620				.append(timepicker);
26621
26622			if (options.withoutCopyright !== true) {
26623				datetimepicker
26624					.append(xdsoft_copyright);
26625			}
26626
26627			datepicker
26628				.append(mounth_picker)
26629				.append(calendar)
26630				.append(applyButton);
26631
26632			$(options.parentID)
26633				.append(datetimepicker);
26634
26635			XDSoft_datetime = function () {
26636				var _this = this;
26637				_this.now = function (norecursion) {
26638					var d = new Date(),
26639						date,
26640						time;
26641
26642					if (!norecursion && options.defaultDate) {
26643						date = _this.strToDateTime(options.defaultDate);
26644						d.setFullYear(date.getFullYear());
26645						d.setMonth(date.getMonth());
26646						d.setDate(date.getDate());
26647					}
26648
26649					if (options.yearOffset) {
26650						d.setFullYear(d.getFullYear() + options.yearOffset);
26651					}
26652
26653					if (!norecursion && options.defaultTime) {
26654						time = _this.strtotime(options.defaultTime);
26655						d.setHours(time.getHours());
26656						d.setMinutes(time.getMinutes());
26657					}
26658					return d;
26659				};
26660
26661				_this.isValidDate = function (d) {
26662					if (Object.prototype.toString.call(d) !== "[object Date]") {
26663						return false;
26664					}
26665					return !isNaN(d.getTime());
26666				};
26667
26668				_this.setCurrentTime = function (dTime) {
26669					_this.currentTime = (typeof dTime === 'string') ? _this.strToDateTime(dTime) : _this.isValidDate(dTime) ? dTime : _this.now();
26670					datetimepicker.trigger('xchange.xdsoft');
26671				};
26672
26673				_this.empty = function () {
26674					_this.currentTime = null;
26675				};
26676
26677				_this.getCurrentTime = function (dTime) {
26678					return _this.currentTime;
26679				};
26680
26681				_this.nextMonth = function () {
26682
26683					if (_this.currentTime === undefined || _this.currentTime === null) {
26684						_this.currentTime = _this.now();
26685					}
26686
26687					var month = _this.currentTime.getMonth() + 1,
26688						year;
26689					if (month === 12) {
26690						_this.currentTime.setFullYear(_this.currentTime.getFullYear() + 1);
26691						month = 0;
26692					}
26693
26694					year = _this.currentTime.getFullYear();
26695
26696					_this.currentTime.setDate(
26697						Math.min(
26698							new Date(_this.currentTime.getFullYear(), month + 1, 0).getDate(),
26699							_this.currentTime.getDate()
26700						)
26701					);
26702					_this.currentTime.setMonth(month);
26703
26704					if (options.onChangeMonth && $.isFunction(options.onChangeMonth)) {
26705						options.onChangeMonth.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
26706					}
26707
26708					if (year !== _this.currentTime.getFullYear() && $.isFunction(options.onChangeYear)) {
26709						options.onChangeYear.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
26710					}
26711
26712					datetimepicker.trigger('xchange.xdsoft');
26713					return month;
26714				};
26715
26716				_this.prevMonth = function () {
26717
26718					if (_this.currentTime === undefined || _this.currentTime === null) {
26719						_this.currentTime = _this.now();
26720					}
26721
26722					var month = _this.currentTime.getMonth() - 1;
26723					if (month === -1) {
26724						_this.currentTime.setFullYear(_this.currentTime.getFullYear() - 1);
26725						month = 11;
26726					}
26727					_this.currentTime.setDate(
26728						Math.min(
26729							new Date(_this.currentTime.getFullYear(), month + 1, 0).getDate(),
26730							_this.currentTime.getDate()
26731						)
26732					);
26733					_this.currentTime.setMonth(month);
26734					if (options.onChangeMonth && $.isFunction(options.onChangeMonth)) {
26735						options.onChangeMonth.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
26736					}
26737					datetimepicker.trigger('xchange.xdsoft');
26738					return month;
26739				};
26740
26741				_this.getWeekOfYear = function (datetime) {
26742					var onejan = new Date(datetime.getFullYear(), 0, 1);
26743					return Math.ceil((((datetime - onejan) / 86400000) + onejan.getDay() + 1) / 7);
26744				};
26745
26746				_this.strToDateTime = function (sDateTime) {
26747					var tmpDate = [], timeOffset, currentTime;
26748
26749					if (sDateTime && sDateTime instanceof Date && _this.isValidDate(sDateTime)) {
26750						return sDateTime;
26751					}
26752
26753					tmpDate = /^(\+|\-)(.*)$/.exec(sDateTime);
26754					if (tmpDate) {
26755						tmpDate[2] = Date.parseDate(tmpDate[2], options.formatDate);
26756					}
26757					if (tmpDate  && tmpDate[2]) {
26758						timeOffset = tmpDate[2].getTime() - (tmpDate[2].getTimezoneOffset()) * 60000;
26759						currentTime = new Date((_this.now(true)).getTime() + parseInt(tmpDate[1] + '1', 10) * timeOffset);
26760					} else {
26761						currentTime = sDateTime ? Date.parseDate(sDateTime, options.format) : _this.now();
26762					}
26763
26764					if (!_this.isValidDate(currentTime)) {
26765						currentTime = _this.now();
26766					}
26767
26768					return currentTime;
26769				};
26770
26771				_this.strToDate = function (sDate) {
26772					if (sDate && sDate instanceof Date && _this.isValidDate(sDate)) {
26773						return sDate;
26774					}
26775
26776					var currentTime = sDate ? Date.parseDate(sDate, options.formatDate) : _this.now(true);
26777					if (!_this.isValidDate(currentTime)) {
26778						currentTime = _this.now(true);
26779					}
26780					return currentTime;
26781				};
26782
26783				_this.strtotime = function (sTime) {
26784					if (sTime && sTime instanceof Date && _this.isValidDate(sTime)) {
26785						return sTime;
26786					}
26787					var currentTime = sTime ? Date.parseDate(sTime, options.formatTime) : _this.now(true);
26788					if (!_this.isValidDate(currentTime)) {
26789						currentTime = _this.now(true);
26790					}
26791					return currentTime;
26792				};
26793
26794				_this.str = function () {
26795					return _this.currentTime.dateFormat(options.format);
26796				};
26797				_this.currentTime = this.now();
26798			};
26799
26800			_xdsoft_datetime = new XDSoft_datetime();
26801
26802			applyButton.on('click', function (e) {//pathbrite
26803                e.preventDefault();
26804                datetimepicker.data('changed', true);
26805                _xdsoft_datetime.setCurrentTime(getCurrentValue());
26806                input.val(_xdsoft_datetime.str());
26807                datetimepicker.trigger('close.xdsoft');
26808            });
26809			mounth_picker
26810				.find('.xdsoft_today_button')
26811				.on('mousedown.xdsoft', function () {
26812					datetimepicker.data('changed', true);
26813					_xdsoft_datetime.setCurrentTime(0);
26814					datetimepicker.trigger('afterOpen.xdsoft');
26815				}).on('dblclick.xdsoft', function () {
26816					var currentDate = _xdsoft_datetime.getCurrentTime(), minDate, maxDate;
26817					currentDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate());
26818					minDate = _xdsoft_datetime.strToDate(options.minDate);
26819					minDate = new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate());
26820					if (currentDate < minDate) {
26821						return;
26822					}
26823					maxDate = _xdsoft_datetime.strToDate(options.maxDate);
26824					maxDate = new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate());
26825					if (currentDate > maxDate) {
26826						return;
26827					}
26828					input.val(_xdsoft_datetime.str());
26829					datetimepicker.trigger('close.xdsoft');
26830				});
26831			mounth_picker
26832				.find('.xdsoft_prev,.xdsoft_next')
26833				.on('mousedown.xdsoft', function () {
26834					var $this = $(this),
26835						timer = 0,
26836						stop = false;
26837
26838					(function arguments_callee1(v) {
26839						if ($this.hasClass(options.next)) {
26840							_xdsoft_datetime.nextMonth();
26841						} else if ($this.hasClass(options.prev)) {
26842							_xdsoft_datetime.prevMonth();
26843						}
26844						if (options.monthChangeSpinner) {
26845							if (!stop) {
26846								timer = setTimeout(arguments_callee1, v || 100);
26847							}
26848						}
26849					}(500));
26850
26851					$([document.body, window]).on('mouseup.xdsoft', function arguments_callee2() {
26852						clearTimeout(timer);
26853						stop = true;
26854						$([document.body, window]).off('mouseup.xdsoft', arguments_callee2);
26855					});
26856				});
26857
26858			timepicker
26859				.find('.xdsoft_prev,.xdsoft_next')
26860				.on('mousedown.xdsoft', function () {
26861					var $this = $(this),
26862						timer = 0,
26863						stop = false,
26864						period = 110;
26865					(function arguments_callee4(v) {
26866						var pheight = timeboxparent[0].clientHeight,
26867							height = timebox[0].offsetHeight,
26868							top = Math.abs(parseInt(timebox.css('marginTop'), 10));
26869						if ($this.hasClass(options.next) && (height - pheight) - options.timeHeightInTimePicker >= top) {
26870							timebox.css('marginTop', '-' + (top + options.timeHeightInTimePicker) + 'px');
26871						} else if ($this.hasClass(options.prev) && top - options.timeHeightInTimePicker >= 0) {
26872							timebox.css('marginTop', '-' + (top - options.timeHeightInTimePicker) + 'px');
26873						}
26874						timeboxparent.trigger('scroll_element.xdsoft_scroller', [Math.abs(parseInt(timebox.css('marginTop'), 10) / (height - pheight))]);
26875						period = (period > 10) ? 10 : period - 10;
26876						if (!stop) {
26877							timer = setTimeout(arguments_callee4, v || period);
26878						}
26879					}(500));
26880					$([document.body, window]).on('mouseup.xdsoft', function arguments_callee5() {
26881						clearTimeout(timer);
26882						stop = true;
26883						$([document.body, window])
26884							.off('mouseup.xdsoft', arguments_callee5);
26885					});
26886				});
26887
26888			xchangeTimer = 0;
26889			// base handler - generating a calendar and timepicker
26890			datetimepicker
26891				.on('xchange.xdsoft', function (event) {
26892					clearTimeout(xchangeTimer);
26893					xchangeTimer = setTimeout(function () {
26894
26895						if (_xdsoft_datetime.currentTime === undefined || _xdsoft_datetime.currentTime === null) {
26896							_xdsoft_datetime.currentTime = _xdsoft_datetime.now();
26897						}
26898
26899						var table =	'',
26900							start = new Date(_xdsoft_datetime.currentTime.getFullYear(), _xdsoft_datetime.currentTime.getMonth(), 1, 12, 0, 0),
26901							i = 0,
26902							j,
26903							today = _xdsoft_datetime.now(),
26904							maxDate = false,
26905							minDate = false,
26906							hDate,
26907							day,
26908							d,
26909							y,
26910							m,
26911							w,
26912							classes = [],
26913							customDateSettings,
26914							newRow = true,
26915							time = '',
26916							h = '',
26917							line_time,
26918							description;
26919
26920						while (start.getDay() !== options.dayOfWeekStart) {
26921							start.setDate(start.getDate() - 1);
26922						}
26923
26924						table += '<table><thead><tr>';
26925
26926						if (options.weeks) {
26927							table += '<th></th>';
26928						}
26929
26930						for (j = 0; j < 7; j += 1) {
26931							table += '<th>' + options.i18n[options.lang].dayOfWeek[(j + options.dayOfWeekStart) % 7] + '</th>';
26932						}
26933
26934						table += '</tr></thead>';
26935						table += '<tbody>';
26936
26937						if (options.maxDate !== false) {
26938							maxDate = _xdsoft_datetime.strToDate(options.maxDate);
26939							maxDate = new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate(), 23, 59, 59, 999);
26940						}
26941
26942						if (options.minDate !== false) {
26943							minDate = _xdsoft_datetime.strToDate(options.minDate);
26944							minDate = new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate());
26945						}
26946
26947						while (i < _xdsoft_datetime.currentTime.countDaysInMonth() || start.getDay() !== options.dayOfWeekStart || _xdsoft_datetime.currentTime.getMonth() === start.getMonth()) {
26948							classes = [];
26949							i += 1;
26950
26951							day = start.getDay();
26952							d = start.getDate();
26953							y = start.getFullYear();
26954							m = start.getMonth();
26955							w = _xdsoft_datetime.getWeekOfYear(start);
26956							description = '';
26957
26958							classes.push('xdsoft_date');
26959
26960							if (options.beforeShowDay && $.isFunction(options.beforeShowDay.call)) {
26961								customDateSettings = options.beforeShowDay.call(datetimepicker, start);
26962							} else {
26963								customDateSettings = null;
26964							}
26965
26966							if ((maxDate !== false && start > maxDate) || (minDate !== false && start < minDate) || (customDateSettings && customDateSettings[0] === false)) {
26967								classes.push('xdsoft_disabled');
26968							} else if (options.disabledDates.indexOf(start.dateFormat(options.formatDate)) !== -1) {
26969								classes.push('xdsoft_disabled');
26970							} else if (options.disabledWeekDays.indexOf(day) !== -1) {
26971							    classes.push('xdsoft_disabled');
26972							}
26973
26974							if (customDateSettings && customDateSettings[1] !== "") {
26975								classes.push(customDateSettings[1]);
26976							}
26977
26978							if (_xdsoft_datetime.currentTime.getMonth() !== m) {
26979								classes.push('xdsoft_other_month');
26980							}
26981
26982							if ((options.defaultSelect || datetimepicker.data('changed')) && _xdsoft_datetime.currentTime.dateFormat(options.formatDate) === start.dateFormat(options.formatDate)) {
26983								classes.push('xdsoft_current');
26984							}
26985
26986							if (today.dateFormat(options.formatDate) === start.dateFormat(options.formatDate)) {
26987								classes.push('xdsoft_today');
26988							}
26989
26990							if (start.getDay() === 0 || start.getDay() === 6 || options.weekends.indexOf(start.dateFormat(options.formatDate)) !== -1) {
26991								classes.push('xdsoft_weekend');
26992							}
26993
26994							if (options.highlightedDates[start.dateFormat(options.formatDate)] !== undefined) {
26995								hDate = options.highlightedDates[start.dateFormat(options.formatDate)];
26996								classes.push(hDate.style === undefined ? 'xdsoft_highlighted_default' : hDate.style);
26997								description = hDate.desc === undefined ? '' : hDate.desc;
26998							}
26999
27000							if (options.beforeShowDay && $.isFunction(options.beforeShowDay)) {
27001								classes.push(options.beforeShowDay(start));
27002							}
27003
27004							if (newRow) {
27005								table += '<tr>';
27006								newRow = false;
27007								if (options.weeks) {
27008									table += '<th>' + w + '</th>';
27009								}
27010							}
27011
27012							table += '<td data-date="' + d + '" data-month="' + m + '" data-year="' + y + '"' + ' class="xdsoft_date xdsoft_day_of_week' + start.getDay() + ' ' + classes.join(' ') + '" title="' + description + '">' +
27013										'<div>' + d + '</div>' +
27014									'</td>';
27015
27016							if (start.getDay() === options.dayOfWeekStartPrev) {
27017								table += '</tr>';
27018								newRow = true;
27019							}
27020
27021							start.setDate(d + 1);
27022						}
27023						table += '</tbody></table>';
27024
27025						calendar.html(table);
27026
27027						mounth_picker.find('.xdsoft_label span').eq(0).text(options.i18n[options.lang].months[_xdsoft_datetime.currentTime.getMonth()]);
27028						mounth_picker.find('.xdsoft_label span').eq(1).text(_xdsoft_datetime.currentTime.getFullYear());
27029
27030						// generate timebox
27031						time = '';
27032						h = '';
27033						m = '';
27034						line_time = function line_time(h, m) {
27035							var now = _xdsoft_datetime.now(), optionDateTime, current_time;
27036							now.setHours(h);
27037							h = parseInt(now.getHours(), 10);
27038							now.setMinutes(m);
27039							m = parseInt(now.getMinutes(), 10);
27040							optionDateTime = new Date(_xdsoft_datetime.currentTime);
27041							optionDateTime.setHours(h);
27042							optionDateTime.setMinutes(m);
27043							classes = [];
27044							if ((options.minDateTime !== false && options.minDateTime > optionDateTime) || (options.maxTime !== false && _xdsoft_datetime.strtotime(options.maxTime).getTime() < now.getTime()) || (options.minTime !== false && _xdsoft_datetime.strtotime(options.minTime).getTime() > now.getTime())) {
27045								classes.push('xdsoft_disabled');
27046							}
27047							if ((options.minDateTime !== false && options.minDateTime > optionDateTime) || ((options.disabledMinTime !== false && now.getTime() > _xdsoft_datetime.strtotime(options.disabledMinTime).getTime()) && (options.disabledMaxTime !== false && now.getTime() < _xdsoft_datetime.strtotime(options.disabledMaxTime).getTime()))) {
27048								classes.push('xdsoft_disabled');
27049							}
27050
27051							current_time = new Date(_xdsoft_datetime.currentTime);
27052							current_time.setHours(parseInt(_xdsoft_datetime.currentTime.getHours(), 10));
27053							current_time.setMinutes(Math[options.roundTime](_xdsoft_datetime.currentTime.getMinutes() / options.step) * options.step);
27054
27055							if ((options.initTime || options.defaultSelect || datetimepicker.data('changed')) && current_time.getHours() === parseInt(h, 10) && (options.step > 59 || current_time.getMinutes() === parseInt(m, 10))) {
27056								if (options.defaultSelect || datetimepicker.data('changed')) {
27057									classes.push('xdsoft_current');
27058								} else if (options.initTime) {
27059									classes.push('xdsoft_init_time');
27060								}
27061							}
27062							if (parseInt(today.getHours(), 10) === parseInt(h, 10) && parseInt(today.getMinutes(), 10) === parseInt(m, 10)) {
27063								classes.push('xdsoft_today');
27064							}
27065							time += '<div class="xdsoft_time ' + classes.join(' ') + '" data-hour="' + h + '" data-minute="' + m + '">' + now.dateFormat(options.formatTime) + '</div>';
27066						};
27067
27068						if (!options.allowTimes || !$.isArray(options.allowTimes) || !options.allowTimes.length) {
27069							for (i = 0, j = 0; i < (options.hours12 ? 12 : 24); i += 1) {
27070								for (j = 0; j < 60; j += options.step) {
27071									h = (i < 10 ? '0' : '') + i;
27072									m = (j < 10 ? '0' : '') + j;
27073									line_time(h, m);
27074								}
27075							}
27076						} else {
27077							for (i = 0; i < options.allowTimes.length; i += 1) {
27078								h = _xdsoft_datetime.strtotime(options.allowTimes[i]).getHours();
27079								m = _xdsoft_datetime.strtotime(options.allowTimes[i]).getMinutes();
27080								line_time(h, m);
27081							}
27082						}
27083
27084						timebox.html(time);
27085
27086						opt = '';
27087						i = 0;
27088
27089						for (i = parseInt(options.yearStart, 10) + options.yearOffset; i <= parseInt(options.yearEnd, 10) + options.yearOffset; i += 1) {
27090							opt += '<div class="xdsoft_option ' + (_xdsoft_datetime.currentTime.getFullYear() === i ? 'xdsoft_current' : '') + '" data-value="' + i + '">' + i + '</div>';
27091						}
27092						yearselect.children().eq(0)
27093												.html(opt);
27094
27095						for (i = parseInt(options.monthStart, 10), opt = ''; i <= parseInt(options.monthEnd, 10); i += 1) {
27096							opt += '<div class="xdsoft_option ' + (_xdsoft_datetime.currentTime.getMonth() === i ? 'xdsoft_current' : '') + '" data-value="' + i + '">' + options.i18n[options.lang].months[i] + '</div>';
27097						}
27098						monthselect.children().eq(0).html(opt);
27099						$(datetimepicker)
27100							.trigger('generate.xdsoft');
27101					}, 10);
27102					event.stopPropagation();
27103				})
27104				.on('afterOpen.xdsoft', function () {
27105					if (options.timepicker) {
27106						var classType, pheight, height, top;
27107						if (timebox.find('.xdsoft_current').length) {
27108							classType = '.xdsoft_current';
27109						} else if (timebox.find('.xdsoft_init_time').length) {
27110							classType = '.xdsoft_init_time';
27111						}
27112						if (classType) {
vendor: 1,383 bytes, lines 27113-27151
27113							pheight = timeboxparent[0].clientHeight;
27114							height = timebox[0].offsetHeight;
27115							top = timebox.find(classType).index() * options.timeHeightInTimePicker + 1;
27116							if ((height - pheight) < top) {
27117								top = height - pheight;
27118							}
27119							timeboxparent.trigger('scroll_element.xdsoft_scroller', [parseInt(top, 10) / (height - pheight)]);
27120						} else {
27121							timeboxparent.trigger('scroll_element.xdsoft_scroller', [0]);
27122						}
27123					}
27124				});
27125
27126			timerclick = 0;
27127			calendar
27128				.on('click.xdsoft', 'td', function (xdevent) {
27129					xdevent.stopPropagation();  // Prevents closing of Pop-ups, Modals and Flyouts in Bootstrap
27130					timerclick += 1;
27131					var $this = $(this),
27132						currentTime = _xdsoft_datetime.currentTime;
27133
27134					if (currentTime === undefined || currentTime === null) {
27135						_xdsoft_datetime.currentTime = _xdsoft_datetime.now();
27136						currentTime = _xdsoft_datetime.currentTime;
27137					}
27138
27139					if ($this.hasClass('xdsoft_disabled')) {
27140						return false;
27141					}
27142
27143					currentTime.setDate(1);
27144					currentTime.setFullYear($this.data('year'));
27145					currentTime.setMonth($this.data('month'));
27146					currentTime.setDate($this.data('date'));
27147
27148					datetimepicker.trigger('select.xdsoft', [currentTime]);
27149
27150					input.val(_xdsoft_datetime.str());
27151					if ((timerclick > 1 || (options.closeOnDateSelect === true || (options.closeOnDateSelect === false && !
27151options.timepicker))) && !options.inline) {
27152						datetimepicker.trigger('close.xdsoft');
27153					}
27154
27155					if (options.onSelectDate &&	$.isFunction(options.onSelectDate)) {
27156						options.onSelectDate.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'), xdevent);
27157					}
27158
27159					datetimepicker.data('changed', true);
27160					datetimepicker.trigger('xchange.xdsoft');
27161					datetimepicker.trigger('changedatetime.xdsoft');
27162					setTimeout(function () {
27163						timerclick = 0;
27164					}, 200);
27165				});
27166
27167			timebox
27168				.on('click.xdsoft', 'div', function (xdevent) {
27169					xdevent.stopPropagation();
27170					var $this = $(this),
27171						currentTime = _xdsoft_datetime.currentTime;
27172
27173					if (currentTime === undefined || currentTime === null) {
27174						_xdsoft_datetime.currentTime = _xdsoft_datetime.now();
27175						currentTime = _xdsoft_datetime.currentTime;
27176					}
27177
27178					if ($this.hasClass('xdsoft_disabled')) {
27179						return false;
27180					}
27181					currentTime.setHours($this.data('hour'));
27182					currentTime.setMinutes($this.data('minute'));
27183					datetimepicker.trigger('select.xdsoft', [currentTime]);
27184
27185					datetimepicker.data('input').val(_xdsoft_datetime.str());
27186
27187                    if (options.inline !== true && options.closeOnTimeSelect === true) {
27188                        datetimepicker.trigger('close.xdsoft');
27189                    }
27190
27191					if (options.onSelectTime && $.isFunction(options.onSelectTime)) {
27192						options.onSelectTime.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'), xdevent);
27193					}
27194					datetimepicker.data('changed', true);
27195					datetimepicker.trigger('xchange.xdsoft');
27196					datetimepicker.trigger('changedatetime.xdsoft');
27197				});
27198
27199
27200			datepicker
27201				.on('mousewheel.xdsoft', function (event) {
27202					if (!options.scrollMonth) {
27203						return true;
27204					}
27205					if (event.deltaY < 0) {
27206						_xdsoft_datetime.nextMonth();
27207					} else {
27208						_xdsoft_datetime.prevMonth();
27209					}
27210					return false;
27211				});
27212
27213			input
27214				.on('mousewheel.xdsoft', function (event) {
27215					if (!options.scrollInput) {
27216						return true;
27217					}
27218					if (!options.datepicker && options.timepicker) {
27219						current_time_index = timebox.find('.xdsoft_current').length ? timebox.find('.xdsoft_current').eq(0).index() : 0;
27220						if (current_time_index + event.deltaY >= 0 && current_time_index + event.deltaY < timebox.children().length) {
27221							current_time_index += event.deltaY;
27222						}
27223						if (timebox.children().eq(current_time_index).length) {
27224							timebox.children().eq(current_time_index).trigger('mousedown');
27225						}
27226						return false;
27227					}
27228					if (options.datepicker && !options.timepicker) {
27229						datepicker.trigger(event, [event.deltaY, event.deltaX, event.deltaY]);
27230						if (input.val) {
27231							input.val(_xdsoft_datetime.str());
27232						}
27233						datetimepicker.trigger('changedatetime.xdsoft');
27234						return false;
27235					}
27236				});
27237
27238			datetimepicker
27239				.on('changedatetime.xdsoft', function (event) {
27240					if (options.onChangeDateTime && $.isFunction(options.onChangeDateTime)) {
27241						var $input = datetimepicker.data('input');
27242						options.onChangeDateTime.call(datetimepicker, _xdsoft_datetime.currentTime, $input, event);
27243						delete options.value;
27244						$input.trigger('change');
27245					}
27246				})
27247				.on('generate.xdsoft', function () {
27248					if (options.onGenerate && $.isFunction(options.onGenerate)) {
27249						options.onGenerate.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
27250					}
27251					if (triggerAfterOpen) {
27252						datetimepicker.trigger('afterOpen.xdsoft');
27253						triggerAfterOpen = false;
27254					}
27255				})
27256				.on('click.xdsoft', function (xdevent) {
27257					xdevent.stopPropagation();
27258				});
27259
27260			current_time_index = 0;
27261
27262			setPos = function () {
27263				var offset = datetimepicker.data('input').offset(), top = offset.top + datetimepicker.data('input')[0].offsetHeight - 1, left = offset.left, position = "absolute", node;
27264				if (options.fixed) {
27265					top -= $(window).scrollTop();
27266					left -= $(window).scrollLeft();
27267					position = "fixed";
27268				} else {
27269					if (top + datetimepicker[0].offsetHeight > $(window).height() + $(window).scrollTop()) {
27270						top = offset.top - datetimepicker[0].offsetHeight + 1;
27271					}
27272					if (top < 0) {
27273						top = 0;
27274					}
27275					if (left + datetimepicker[0].offsetWidth > $(window).width()) {
27276						left = $(window).width() - datetimepicker[0].offsetWidth;
27277					}
27278				}
27279
27280				node = datetimepicker[0];
27281				do {
27282					node = node.parentNode;
27283					if (window.getComputedStyle(node).getPropertyValue('position') === 'relative' && $(window).width() >= node.offsetWidth) {
27284						left = left - (($(window).width() - node.offsetWidth) / 2);
27285						break;
27286					}
27287				} while (node.nodeName !== 'HTML');
27288				datetimepicker.css({
27289					left: left,
27290					top: top,
27291					position: position
27292				});
27293			};
27294			datetimepicker
27295				.on('open.xdsoft', function (event) {
27296					var onShow = true;
27297					if (options.onShow && $.isFunction(options.onShow)) {
27298						onShow = options.onShow.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'), event);
27299					}
27300					if (onShow !== false) {
27301						datetimepicker.show();
27302						setPos();
27303						$(window)
27304							.off('resize.xdsoft', setPos)
27305							.on('resize.xdsoft', setPos);
27306
27307						if (options.closeOnWithoutClick) {
27308							$([document.body, window]).on('mousedown.xdsoft', function arguments_callee6() {
27309								datetimepicker.trigger('close.xdsoft');
27310								$([document.body, window]).off('mousedown.xdsoft', arguments_callee6);
27311							});
27312						}
27313					}
27314				})
27315				.on('close.xdsoft', function (event) {
27316					var onClose = true;
27317					mounth_picker
27318						.find('.xdsoft_month,.xdsoft_year')
27319							.find('.xdsoft_select')
27320								.hide();
27321					if (options.onClose && $.isFunction(options.onClose)) {
27322						onClose = options.onClose.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'), event);
27323					}
27324					if (onClose !== false && !options.opened && !options.inline) {
27325						datetimepicker.hide();
27326					}
27327					event.stopPropagation();
27328				})
27329				.on('toggle.xdsoft', function (event) {
27330					if (datetimepicker.is(':visible')) {
27331						datetimepicker.trigger('close.xdsoft');
27332					} else {
27333						datetimepicker.trigger('open.xdsoft');
27334					}
27335				})
27336				.data('input', input);
27337
27338			timer = 0;
27339			timer1 = 0;
27340
27341			datetimepicker.data('xdsoft_datetime', _xdsoft_datetime);
27342			datetimepicker.setOptions(options);
27343
27344			function getCurrentValue() {
27345				var ct = false, time;
27346
27347				if (options.startDate) {
27348					ct = _xdsoft_datetime.strToDate(options.startDate);
27349				} else {
27350					ct = options.value || ((input && input.val && input.val()) ? input.val() : '');
27351					if (ct) {
27352						ct = _xdsoft_datetime.strToDateTime(ct);
27353					} else if (options.defaultDate) {
27354						ct = _xdsoft_datetime.strToDateTime(options.defaultDate);
27355						if (options.defaultTime) {
27356							time = _xdsoft_datetime.strtotime(options.defaultTime);
27357							ct.setHours(time.getHours());
27358							ct.setMinutes(time.getMinutes());
27359						}
27360					}
27361				}
27362
27363				if (ct && _xdsoft_datetime.isValidDate(ct)) {
27364					datetimepicker.data('changed', true);
27365				} else {
27366					ct = '';
27367				}
27368
27369				return ct || 0;
27370			}
27371
27372			_xdsoft_datetime.setCurrentTime(getCurrentValue());
27373
27374			input
27375				.data('xdsoft_datetimepicker', datetimepicker)
27376				.on('open.xdsoft focusin.xdsoft mousedown.xdsoft', function (event) {
27377					if (input.is(':disabled') || (input.data('xdsoft_datetimepicker').is(':visible') && options.closeOnInputClick)) {
27378						return;
27379					}
27380					clearTimeout(timer);
27381					timer = setTimeout(function () {
27382						if (input.is(':disabled')) {
27383							return;
27384						}
27385
27386						triggerAfterOpen = true;
27387						_xdsoft_datetime.setCurrentTime(getCurrentValue());
27388
27389						datetimepicker.trigger('open.xdsoft');
27390					}, 100);
27391				})
27392				.on('keydown.xdsoft', function (event) {
27393					var val = this.value, elementSelector,
27394						key = event.which;
27395					if ([ENTER].indexOf(key) !== -1 && options.enterLikeTab) {
27396						elementSelector = $("input:visible,textarea:visible");
27397						datetimepicker.trigger('close.xdsoft');
27398						elementSelector.eq(elementSelector.index(this) + 1).focus();
27399						return false;
27400					}
27401					if ([TAB].indexOf(key) !== -1) {
27402						datetimepicker.trigger('close.xdsoft');
27403						return true;
27404					}
27405				});
27406		};
27407		destroyDateTimePicker = function (input) {
27408			var datetimepicker = input.data('xdsoft_datetimepicker');
27409			if (datetimepicker) {
27410				datetimepicker.data('xdsoft_datetime', null);
27411				datetimepicker.remove();
27412				input
27413					.data('xdsoft_datetimepicker', null)
27414					.off('.xdsoft');
27415				$(window).off('resize.xdsoft');
27416				$([window, document.body]).off('mousedown.xdsoft');
27417				if (input.unmousewheel) {
27418					input.unmousewheel();
27419				}
27420			}
27421		};
27422		$(document)
27423			.off('keydown.xdsoftctrl keyup.xdsoftctrl')
27424			.on('keydown.xdsoftctrl', function (e) {
27425				if (e.keyCode === CTRLKEY) {
27426					ctrlDown = true;
27427				}
27428			})
27429			.on('keyup.xdsoftctrl', function (e) {
27430				if (e.keyCode === CTRLKEY) {
27431					ctrlDown = false;
27432				}
27433			});
27434		return this.each(function () {
27435			var datetimepicker = $(this).data('xdsoft_datetimepicker'), $input;
27436			if (datetimepicker) {
27437				if ($.type(opt) === 'string') {
27438					switch (opt) {
27439					case 'show':
27440						$(this).select().focus();
27441						datetimepicker.trigger('open.xdsoft');
27442						break;
27443					case 'hide':
27444						datetimepicker.trigger('close.xdsoft');
27445						break;
27446					case 'toggle':
27447						datetimepicker.trigger('toggle.xdsoft');
27448						break;
27449					case 'destroy':
27450						destroyDateTimePicker($(this));
27451						break;
27452					case 'reset':
27453						this.value = this.defaultValue;
27454						if (!this.value || !datetimepicker.data('xdsoft_datetime').isValidDate(Date.parseDate(this.value, options.format))) {
27455							datetimepicker.data('changed', false);
27456						}
27457						datetimepicker.data('xdsoft_datetime').setCurrentTime(this.value);
27458						break;
27459					case 'validate':
27460						$input = datetimepicker.data('input');
27461						$input.trigger('blur.xdsoft');
27462						break;
27463					}
27464				} else {
27465					datetimepicker
27466						.setOptions(opt);
27467				}
27468				return 0;
27469			}
27470			if ($.type(opt) !== 'string') {
27471				if (!options.lazyInit || options.open || options.inline) {
27472					createDateTimePicker($(this));
27473				} else {
27474					lazyInit($(this));
27475				}
27476			}
27477		});
27478	};
27479	$.fn.datetimepicker.defaults = default_options;
27480}(jQuery));
27481
27482function HighlightedDate(date, desc, style) {
27483	"use strict";
27484	this.date = date;
27485	this.desc = desc;
27486	this.style = style;
27487}
27488
27489(function () {
27490
27491/*! Copyright (c) 2013 Brandon Aaron (http://brandon.aaron.sh)
27492 * Licensed under the MIT License (LICENSE.txt).
27493 *
27494 * Version: 3.1.12
27495 *
27496 * Requires: jQuery 1.2.2+
27497 */
27498!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1
vendor: 2,754 bytes, lines 27498-27506
27498),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});
27499
27500// Parse and Format Library
27501//http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
27502/*
27503 * Copyright (C) 2004 Baron Schwartz <baron at sequent dot org>
27504 *
27505 * This program is free software; you can redistribute it and/or modify it
27506 * under the terms of the GNU Lesser General Public License as published by the
27507 * Free Software Foundation, version 2.1.
27508 *
27509 * This program is distributed in the hope that it will be useful, but WITHOUT
27510 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
27511 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
27512 * details.
27513 */
27514Date.parseFunctions={count:0};Date.parseRegexes=[];Date.formatFunctions={count:0};Date.prototype.dateFormat=function(b){if(b=="unixtime"){return parseInt(this.getTime()/1000);}if(Date.formatFunctions[b]==null){Date.createNewFormat(b);}var a=Date.formatFunctions[b];return this[a]();};Date.createNewFormat=function(format){var funcName="format"+Date.formatFunctions.count++;Date.formatFunctions[format]=funcName;var codePrefix="Date.prototype."+funcName+" = function() {return ";var code="";var special=false;var ch="";for(var i=0;i<format.length;++i){ch=format.charAt(i);if(!special&&ch=="\\"){special=true;}else{if(special){special=false;code+="'"+String.escape(ch)+"' + ";}else{code+=Date.getFormatCode(ch);}}}if(code.length==0){code="\"\"";}else{code=code.substring(0,code.length-3);}eval(codePrefix+code+";}");};Date.getFormatCode=function(a){switch(a){case"d":return"String.leftPad(this.getDate(), 2, '0') + ";case"D":return"Date.dayNames[this.getDay()].substring(0, 3) + ";case"j":return"this.getDate() + ";case"l":return"Date.dayNames[this.getDay()] + ";case"S":return"this.getSuffix() + ";case"w":return"this.getDay() + ";case"z":return"this.getDayOfYear() + ";case"W":return"this.getWeekOfYear() + ";case"F":return"Date.monthNames[this.getMonth()] + ";case"m":return"String.leftPad(this.getMonth() + 1, 2, '0') + ";case"M":return"Date.monthNames[this.getMonth()].substring(0, 3) + ";case"n":return"(this.getMonth() + 1) + ";case"t":return"this.getDaysInMonth() + ";case"L":return"(this.isLeapYear() ? 1 : 0) + ";case"Y":return"this.getFullYear() + ";case"y":return"('' + this.getFullYear()).substring(2, 4) + ";case"a":return"(this.getHours() < 12 ? 'am' : 'pm') + ";case"A":return"(this.getHours() < 12 ? 'AM' : 'PM') + ";case"g":return"((this.getHours() %12) ? this.getHours() % 12 : 12) + ";case"G":return"this.getHours() + ";case"h":return"String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + ";case"H":return"String.leftPad(this.getHours(), 2, '0') + ";case"i":return"String.leftPad(this.getMinutes(), 2, '0') + ";case"s":return"String.leftPad(this.getSeconds(), 2, '0') + ";case"O":return"this.getGMTOffset() + ";case"T":return"this.getTimezone() + ";case"Z":return"(this.getTimezoneOffset() * -60) + ";default:return"'"+String.escape(a)+"' + ";}};Date.parseDate=function(a,c){if(c=="unixtime"){return new Date(!isNaN(parseInt(a))?parseInt(a)*1000:0);}if(Date.parseFunctions[c]==null){Date.createParser(c);}var b=Date.parseFunctions[c];return Date[b](a);};Date.createParser=function(format){var funcName="parse"+Date.parseFunctions.count++;var regexNum=Date.parseRegexes.length;var currentGroup=1;Date.parseFunctions[format]=funcName;var code="Date."+funcName+" = function(input) {\nvar y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, z = -1;\nvar d = new Date();\ny = d.getFullYear();\nm = d.getMonth();\nd = d.getDate();\nvar results = input.match(Date.parseRegexes["+regexNum+"]);\nif (results && results.length > 0) {";var regex="";var special=false;var ch="";for(var i=0;i<format.length;++i){ch=format.charAt(i);if(!special&&ch=="\\"){special=true;}else{if(special){special=false;regex+=String.escape(ch);}else{obj=Date.formatCodeToRegex(ch,currentGroup);currentGroup+=obj.g;regex+=obj.s;if(obj.g&&obj.c){code+=obj.c;}}}}code+="if (y > 0 && z > 0){\nvar doyDate = new Date(y,0);\ndoyDate.setDate(z);\nm = doyDate.getMonth();\nd = doyDate.getDate();\n}";code+="if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n{return new Date(y, m, d, h, i, s);}\nelse if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n{return new Date(y, m, d, h, i);}\nelse if (y > 0 && m >= 0 && d > 0 && h >= 0)\n{return new Date(y, m, d, h);}\nelse if (y > 0 && m >= 0 && d > 0)\n{return new Date(y, m, d);}\nelse if (y > 0 && m >= 0)\n{return new Date(y, m);}\nelse if (y > 0)\n{return new Date(y);}\n}return null;}";Date.parseRegexes[regexNum]=new RegExp("^"+regex+"$",'i');eval(code);};Date.formatCodeToRegex=function(b,a){switch(b){case"D":return{g:0,c:null,
27514s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};case"j":case"d":return{g:1,c:"d = parseInt(results["+a+"], 10);\n",s:"(\\d{1,2})"};case"l":return{g:0,c:null,s:"(?:"+Date.dayNames.join("|")+")"};case"S":return{g:0,c:null,s:"(?:st|nd|rd|th)"};case"w":return{g:0,c:null,s:"\\d"};case"z":return{g:1,c:"z = parseInt(results["+a+"], 10);\n",s:"(\\d{1,3})"};case"W":return{g:0,c:null,s:"(?:\\d{2})"};case"F":return{g:1,c:"m = parseInt(Date.monthNumbers[results["+a+"].substring(0, 3)], 10);\n",s:"("+Date.monthNames.join("|")+")"};case"M":return{g:1,c:"m = parseInt(Date.monthNumbers[results["+a+"]], 10);\n",s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};case"n":case"m":return{g:1,c:"m = parseInt(results["+a+"], 10) - 1;\n",s:"(\\d{1,2})"};case"t":return{g:0,c:null,s:"\\d{1,2}"};case"L":return{g:0,c:null,s:"(?:1|0)"};case"Y":return{g:1,c:"y = parseInt(results["+a+"], 10);\n",s:"(\\d{4})"};case"y":return{g:1,c:"var ty = parseInt(results["+a+"], 10);\ny = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",s:"(\\d{1,2})"};case"a":return{g:1,c:"if (results["+a+"] == 'am') {\nif (h == 12) { h = 0; }\n} else { if (h < 12) { h += 12; }}",s:"(am|pm)"};case"A":return{g:1,c:"if (results["+a+"] == 'AM') {\nif (h == 12) { h = 0; }\n} else { if (h < 12) { h += 12; }}",s:"(AM|PM)"};case"g":case"G":case"h":case"H":return{g:1,c:"h = parseInt(results["+a+"], 10);\n",s:"(\\d{1,2})"};case"i":return{g:1,c:"i = parseInt(results["+a+"], 10);\n",s:"(\\d{2})"};case"s":return{g:1,c:"s = parseInt(results["+a+"], 10);\n",s:"(\\d{2})"};case"O":return{g:0,c:null,s:"[+-]\\d{4}"};case"T":return{g:0,c:null,s:"[A-Z]{3}"};case"Z":return{g:0,c:null,s:"[+-]\\d{1,5}"};default:return{g:0,c:null,s:String.escape(b)};}};Date.prototype.getTimezone=function(){return this.toString().replace(/^.*? ([A-Z]{3}) [0-9]{4}.*$/,"$1").replace(/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/,"$1$2$3");};Date.prototype.getGMTOffset=function(){return(this.getTimezoneOffset()>0?"-":"+")+String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset())/60),2,"0")+String.leftPad(Math.abs(this.getTimezoneOffset())%60,2,"0");};Date.prototype.getDayOfYear=function(){var a=0;Date.daysInMonth[1]=this.isLeapYear()?29:28;for(var b=0;b<this.getMonth();++b){a+=Date.daysInMonth[b];}return a+this.getDate();};Date.prototype.getWeekOfYear=function(){var b=this.getDayOfYear()+(4-this.getDay());var a=new Date(this.getFullYear(),0,1);var c=(7-a.getDay()+4);return String.leftPad(Math.ceil((b-c)/7)+1,2,"0");};Date.prototype.isLeapYear=function(){var a=this.getFullYear();return((a&3)==0&&(a%100||(a%400==0&&a)));};Date.prototype.getFirstDayOfMonth=function(){var a=(this.getDay()-(this.getDate()-1))%7;return(a<0)?(a+7):a;};Date.prototype.getLastDayOfMonth=function(){var a=(this.getDay()+(Date.daysInMonth[this.getMonth()]-this.getDate()))%7;return(a<0)?(a+7):a;};Date.prototype.getDaysInMonth=function(){Date.daysInMonth[1]=this.isLeapYear()?29:28;return Date.daysInMonth[this.getMonth()];};Date.prototype.getSuffix=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};String.escape=function(a){return a.replace(/('|\\)/g,"\\$1");};String.leftPad=function(d,b,c){var a=new String(d);if(c==null){c=" ";}while(a.length<b){a=c+a;}return a;};Date.daysInMonth=[31,28,31,30,31,30,31,31,30,31,30,31];Date.monthNames=["January","February","March","April","May","June","July","August","September","October","November","December"];Date.dayNames=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];Date.y2kYear=50;Date.monthNumbers={Jan:0,Feb:1,Mar:2,Apr:3,May:4,Jun:5,Jul:6,Aug:7,Sep:8,Oct:9,Nov:10,Dec:11};Date.patterns={ISO8601LongPattern:"Y-m-d H:i:s",ISO8601ShortPattern:"Y-m-d",ShortDatePattern:"n/j/Y",LongDatePattern:"l, F d, Y",FullDateTimePattern:"l, F d, Y g:i:s A",MonthDayPattern:"F d",ShortTimePattern:"g:i A",LongTimePattern:"g:i:s A",SortableDateTimePattern:"Y-m-d\\TH:i:s",UniversalSortableDateTimePattern:"Y-m-d H:i:sO",YearMonthPattern:"F, Y"};
27515}());
27516
27517(function (root) {/*global exports, Intl*/
27518/**
27519 * This script gives you the zone info key representing your device's time zone setting.
27520 *
27521 * @name jsTimezoneDetect
27522 * @version 1.0.5
27523 * @author Jon Nylander
27524 * @license MIT License - https://bitbucket.org/pellepim/jstimezonedetect/src/default/LICENCE.txt
27525 *
27526 * For usage and examples, visit:
27527 * http://pellepim.bitbucket.org/jstz/
27528 *
27529 * Copyright (c) Jon Nylander
27530 */
27531
27532
27533/**
27534 * Namespace to hold all the code for timezone detection.
27535 */
27536var jstz = (function () {
27537    'use strict';
27538    var HEMISPHERE_SOUTH = 's',
27539
27540        consts = {
27541            DAY: 86400000,
27542            HOUR: 3600000,
27543            MINUTE: 60000,
27544            SECOND: 1000,
27545            BASELINE_YEAR: 2014,
27546            MAX_SCORE: 864000000, // 10 days
27547            AMBIGUITIES: {
27548                'America/Denver':       ['America/Mazatlan'],
27549                'America/Chicago':      ['America/Mexico_City'],
27550                'America/Santiago':     ['America/Asuncion', 'America/Campo_Grande'],
27551                'America/Montevideo':   ['America/Sao_Paulo'],
27552                // Europe/Minsk should not be in this list... but Windows.
27553                'Asia/Beirut':          ['Asia/Amman', 'Asia/Jerusalem', 'Europe/Helsinki', 'Asia/Damascus', 'Africa/Cairo', 'Asia/Gaza', 'Europe/Minsk'],
27554                'Pacific/Auckland':     ['Pacific/Fiji'],
27555                'America/Los_Angeles':  ['America/Santa_Isabel'],
vendor: 31,758 bytes, lines 27556-28566
27556                'America/New_York':     ['America/Havana'],
27557                'America/Halifax':      ['America/Goose_Bay'],
27558                'America/Godthab':      ['America/Miquelon'],
27559                'Asia/Dubai':           ['Asia/Yerevan'],
27560                'Asia/Jakarta':         ['Asia/Krasnoyarsk'],
27561                'Asia/Shanghai':        ['Asia/Irkutsk', 'Australia/Perth'],
27562                'Australia/Sydney':     ['Australia/Lord_Howe'],
27563                'Asia/Tokyo':           ['Asia/Yakutsk'],
27564                'Asia/Dhaka':           ['Asia/Omsk'],
27565                // In the real world Yerevan is not ambigous for Baku... but Windows.
27566                'Asia/Baku':            ['Asia/Yerevan'],
27567                'Australia/Brisbane':   ['Asia/Vladivostok'],
27568                'Pacific/Noumea':       ['Asia/Vladivostok'],
27569                'Pacific/Majuro':       ['Asia/Kamchatka', 'Pacific/Fiji'],
27570                'Pacific/Tongatapu':    ['Pacific/Apia'],
27571                'Asia/Baghdad':         ['Europe/Minsk', 'Europe/Moscow'],
27572                'Asia/Karachi':         ['Asia/Yekaterinburg'],
27573                'Africa/Johannesburg':  ['Asia/Gaza', 'Africa/Cairo']
27574            }
27575        },
27576
27577        /**
27578         * Gets the offset in minutes from UTC for a certain date.
27579         * @param {Date} date
27580         * @returns {Number}
27581         */
27582        get_date_offset = function get_date_offset(date) {
27583            var offset = -date.getTimezoneOffset();
27584            return (offset !== null ? offset : 0);
27585        },
27586
27587        /**
27588         * This function does some basic calculations to create information about
27589         * the user's timezone. It uses REFERENCE_YEAR as a solid year for which
27590         * the script has been tested rather than depend on the year set by the
27591         * client device.
27592         *
27593         * Returns a key that can be used to do lookups in jstz.olson.timezones.
27594         * eg: "720,1,2".
27595         *
27596         * @returns {String}
27597         */
27598        lookup_key = function lookup_key() {
27599            var january_offset = get_date_offset(new Date(consts.BASELINE_YEAR, 0, 2)),
27600                june_offset = get_date_offset(new Date(consts.BASELINE_YEAR, 5, 2)),
27601                diff = january_offset - june_offset;
27602
27603            if (diff < 0) {
27604                return january_offset + ",1";
27605            } else if (diff > 0) {
27606                return june_offset + ",1," + HEMISPHERE_SOUTH;
27607            }
27608
27609            return january_offset + ",0";
27610        },
27611
27612
27613        /**
27614         * Tries to get the time zone key directly from the operating system for those
27615         * environments that support the ECMAScript Internationalization API.
27616         */
27617        get_from_internationalization_api = function get_from_internationalization_api() {
27618            if (typeof Intl === "undefined" || typeof Intl.DateTimeFormat === "undefined") {
27619                return;
27620            }
27621            var format = Intl.DateTimeFormat();
27622            if (typeof format === "undefined" || typeof format.resolvedOptions === "undefined") {
27623                return;
27624            }
27625            return format.resolvedOptions().timeZone;
27626        },
27627
27628        /**
27629         * Starting point for getting all the DST rules for a specific year
27630         * for the current timezone (as described by the client system).
27631         *
27632         * Returns an object with start and end attributes, or false if no
27633         * DST rules were found for the year.
27634         *
27635         * @param year
27636         * @returns {Object} || {Boolean}
27637         */
27638        dst_dates = function dst_dates(year) {
27639            var yearstart = new Date(year, 0, 1, 0, 0, 1, 0).getTime();
27640            var yearend = new Date(year, 12, 31, 23, 59, 59).getTime();
27641            var current = yearstart;
27642            var offset = (new Date(current)).getTimezoneOffset();
27643            var dst_start = null;
27644            var dst_end = null;
27645
27646            while (current < yearend - 86400000) {
27647                var dateToCheck = new Date(current);
27648                var dateToCheckOffset = dateToCheck.getTimezoneOffset();
27649
27650                if (dateToCheckOffset !== offset) {
27651                    if (dateToCheckOffset < offset) {
27652                        dst_start = dateToCheck;
27653                    }
27654                    if (dateToCheckOffset > offset) {
27655                        dst_end = dateToCheck;
27656                    }
27657                    offset = dateToCheckOffset;
27658                }
27659
27660                current += 86400000;
27661            }
27662
27663            if (dst_start && dst_end) {
27664                return {
27665                    s: find_dst_fold(dst_start).getTime(),
27666                    e: find_dst_fold(dst_end).getTime()
27667                };
27668            }
27669
27670            return false;
27671        },
27672
27673        /**
27674         * Probably completely unnecessary function that recursively finds the
27675         * exact (to the second) time when a DST rule was changed.
27676         *
27677         * @param a_date - The candidate Date.
27678         * @param padding - integer specifying the padding to allow around the candidate
27679         *                  date for finding the fold.
27680         * @param iterator - integer specifying how many milliseconds to iterate while
27681         *                   searching for the fold.
27682         *
27683         * @returns {Date}
27684         */
27685        find_dst_fold = function find_dst_fold(a_date, padding, iterator) {
27686            if (typeof padding === 'undefined') {
27687                padding = consts.DAY;
27688                iterator = consts.HOUR;
27689            }
27690
27691            var date_start = new Date(a_date.getTime() - padding).getTime();
27692            var date_end = a_date.getTime() + padding;
27693            var offset = new Date(date_start).getTimezoneOffset();
27694
27695            var current = date_start;
27696
27697            var dst_change = null;
27698            while (current < date_end - iterator) {
27699                var dateToCheck = new Date(current);
27700                var dateToCheckOffset = dateToCheck.getTimezoneOffset();
27701
27702                if (dateToCheckOffset !== offset) {
27703                    dst_change = dateToCheck;
27704                    break;
27705                }
27706                current += iterator;
27707            }
27708
27709            if (padding === consts.DAY) {
27710                return find_dst_fold(dst_change, consts.HOUR, consts.MINUTE);
27711            }
27712
27713            if (padding === consts.HOUR) {
27714                return find_dst_fold(dst_change, consts.MINUTE, consts.SECOND);
27715            }
27716
27717            return dst_change;
27718        },
27719
27720        windows7_adaptations = function windows7_adaptions(rule_list, preliminary_timezone, score, sample) {
27721            if (score !== 'N/A') {
27722                return score;
27723            }
27724            if (preliminary_timezone === 'Asia/Beirut') {
27725                if (sample.name === 'Africa/Cairo') {
27726                    if (rule_list[6].s === 1398376800000 && rule_list[6].e === 1411678800000) {
27727                        return 0;
27728                    }
27729                }
27730                if (sample.name === 'Asia/Jerusalem') {
27731                    if (rule_list[6].s === 1395964800000 && rule_list[6].e === 1411858800000) {
27732                        return 0;
27733                }
27734            }
27735            } else if (preliminary_timezone === 'America/Santiago') {
27736                if (sample.name === 'America/Asuncion') {
27737                    if (rule_list[6].s === 1412481600000 && rule_list[6].e === 1397358000000) {
27738                        return 0;
27739                    }
27740                }
27741                if (sample.name === 'America/Campo_Grande') {
27742                    if (rule_list[6].s === 1413691200000 && rule_list[6].e === 1392519600000) {
27743                        return 0;
27744                    }
27745                }
27746            } else if (preliminary_timezone === 'America/Montevideo') {
27747                if (sample.name === 'America/Sao_Paulo') {
27748                    if (rule_list[6].s === 1413687600000 && rule_list[6].e === 1392516000000) {
27749                        return 0;
27750                    }
27751                }
27752            } else if (preliminary_timezone === 'Pacific/Auckland') {
27753                if (sample.name === 'Pacific/Fiji') {
27754                    if (rule_list[6].s === 1414245600000 && rule_list[6].e === 1396101600000) {
27755                        return 0;
27756                    }
27757                }
27758            }
27759
27760            return score;
27761        },
27762
27763        /**
27764         * Takes the DST rules for the current timezone, and proceeds to find matches
27765         * in the jstz.olson.dst_rules.zones array.
27766         *
27767         * Compares samples to the current timezone on a scoring basis.
27768         *
27769         * Candidates are ruled immediately if either the candidate or the current zone
27770         * has a DST rule where the other does not.
27771         *
27772         * Candidates are ruled out immediately if the current zone has a rule that is
27773         * outside the DST scope of the candidate.
27774         *
27775         * Candidates are included for scoring if the current zones rules fall within the
27776         * span of the samples rules.
27777         *
27778         * Low score is best, the score is calculated by summing up the differences in DST
27779         * rules and if the consts.MAX_SCORE is overreached the candidate is ruled out.
27780         *
27781         * Yah follow? :)
27782         *
27783         * @param rule_list
27784         * @param preliminary_timezone
27785         * @returns {*}
27786         */
27787        best_dst_match = function best_dst_match(rule_list, preliminary_timezone) {
27788            var score_sample = function score_sample(sample) {
27789                var score = 0;
27790
27791                for (var j = 0; j < rule_list.length; j++) {
27792
27793                    // Both sample and current time zone report DST during the year.
27794                    if (!!sample.rules[j] && !!rule_list[j]) {
27795
27796                        // The current time zone's DST rules are inside the sample's. Include.
27797                        if (rule_list[j].s >= sample.rules[j].s && rule_list[j].e <= sample.rules[j].e) {
27798                            score = 0;
27799                            score += Math.abs(rule_list[j].s - sample.rules[j].s);
27800                            score += Math.abs(sample.rules[j].e - rule_list[j].e);
27801
27802                        // The current time zone's DST rules are outside the sample's. Discard.
27803                        } else {
27804                            score = 'N/A';
27805                            break;
27806                        }
27807
27808                        // The max score has been reached. Discard.
27809                        if (score > consts.MAX_SCORE) {
27810                            score = 'N/A';
27811                            break;
27812                        }
27813                    }
27814                }
27815
27816                score = windows7_adaptations(rule_list, preliminary_timezone, score, sample);
27817
27818                return score;
27819            };
27820            var scoreboard = {};
27821            var dst_zones = jstz.olson.dst_rules.zones;
27822            var dst_zones_length = dst_zones.length;
27823            var ambiguities = consts.AMBIGUITIES[preliminary_timezone];
27824
27825            for (var i = 0; i < dst_zones_length; i++) {
27826                var sample = dst_zones[i];
27827                var score = score_sample(dst_zones[i]);
27828
27829                if (score !== 'N/A') {
27830                    scoreboard[sample.name] = score;
27831                }
27832            }
27833
27834            for (var tz in scoreboard) {
27835                if (scoreboard.hasOwnProperty(tz)) {
27836                    if (ambiguities.indexOf(tz) != -1) {
27837                        return tz;
27838                    }
27839                }
27840            }
27841
27842            return preliminary_timezone;
27843        },
27844
27845        /**
27846         * Takes the preliminary_timezone as detected by lookup_key().
27847         *
27848         * Builds up the current timezones DST rules for the years defined
27849         * in the jstz.olson.dst_rules.years array.
27850         *
27851         * If there are no DST occurences for those years, immediately returns
27852         * the preliminary timezone. Otherwise proceeds and tries to solve
27853         * ambiguities.
27854         *
27855         * @param preliminary_timezone
27856         * @returns {String} timezone_name
27857         */
27858        get_by_dst = function get_by_dst(preliminary_timezone) {
27859            var get_rules = function get_rules() {
27860                var rule_list = [];
27861                for (var i = 0; i < jstz.olson.dst_rules.years.length; i++) {
27862                    var year_rules = dst_dates(jstz.olson.dst_rules.years[i]);
27863                    rule_list.push(year_rules);
27864                }
27865                return rule_list;
27866            };
27867            var check_has_dst = function check_has_dst(rules) {
27868                for (var i = 0; i < rules.length; i++) {
27869                    if (rules[i] !== false) {
27870                        return true;
27871                    }
27872                }
27873                return false;
27874            };
27875            var rules = get_rules();
27876            var has_dst = check_has_dst(rules);
27877
27878            if (has_dst) {
27879                return best_dst_match(rules, preliminary_timezone);
27880            }
27881
27882            return preliminary_timezone;
27883        },
27884
27885        /**
27886         * Uses get_timezone_info() to formulate a key to use in the olson.timezones dictionary.
27887         *
27888         * Returns an object with one function ".name()"
27889         *
27890         * @returns Object
27891         */
27892        determine = function determine() {
27893            var preliminary_tz = get_from_internationalization_api();
27894
27895            if (!preliminary_tz) {
27896                preliminary_tz = jstz.olson.timezones[lookup_key()];
27897
27898                if (typeof consts.AMBIGUITIES[preliminary_tz] !== 'undefined') {
27899                    preliminary_tz = get_by_dst(preliminary_tz);
27900                }
27901            }
27902
27903            return {
27904                name: function () {
27905                    return preliminary_tz;
27906                }
27907            };
27908        };
27909
27910    return {
27911        determine: determine
27912    };
27913}());
27914
27915
27916jstz.olson = jstz.olson || {};
27917
27918/**
27919 * The keys in this dictionary are comma separated as such:
27920 *
27921 * First the offset compared to UTC time in minutes.
27922 *
27923 * Then a flag which is 0 if the timezone does not take daylight savings into account and 1 if it
27924 * does.
27925 *
27926 * Thirdly an optional 's' signifies that the timezone is in the southern hemisphere,
27927 * only interesting for timezones with DST.
27928 *
27929 * The mapped arrays is used for constructing the jstz.TimeZone object from within
27930 * jstz.determine();
27931 */
27932jstz.olson.timezones = {
27933    '-720,0': 'Etc/GMT+12',
27934    '-660,0': 'Pacific/Pago_Pago',
27935    '-660,1,s': 'Pacific/Apia', // Why? Because windows... cry!
27936    '-600,1': 'America/Adak',
27937    '-600,0': 'Pacific/Honolulu',
27938    '-570,0': 'Pacific/Marquesas',
27939    '-540,0': 'Pacific/Gambier',
27940    '-540,1': 'America/Anchorage',
27941    '-480,1': 'America/Los_Angeles',
27942    '-480,0': 'Pacific/Pitcairn',
27943    '-420,0': 'America/Phoenix',
27944    '-420,1': 'America/Denver',
27945    '-360,0': 'America/Guatemala',
27946    '-360,1': 'America/Chicago',
27947    '-360,1,s': 'Pacific/Easter',
27948    '-300,0': 'America/Bogota',
27949    '-300,1': 'America/New_York',
27950    '-270,0': 'America/Caracas',
27951    '-240,1': 'America/Halifax',
27952    '-240,0': 'America/Santo_Domingo',
27953    '-240,1,s': 'America/Santiago',
27954    '-210,1': 'America/St_Johns',
27955    '-180,1': 'America/Godthab',
27956    '-180,0': 'America/Argentina/Buenos_Aires',
27957    '-180,1,s': 'America/Montevideo',
27958    '-120,0': 'America/Noronha',
27959    '-120,1': 'America/Noronha',
27960    '-60,1': 'Atlantic/Azores',
27961    '-60,0': 'Atlantic/Cape_Verde',
27962    '0,0': 'UTC',
27963    '0,1': 'Europe/London',
27964    '60,1': 'Europe/Berlin',
27965    '60,0': 'Africa/Lagos',
27966    '60,1,s': 'Africa/Windhoek',
27967    '120,1': 'Asia/Beirut',
27968    '120,0': 'Africa/Johannesburg',
27969    '180,0': 'Asia/Baghdad',
27970    '180,1': 'Europe/Moscow',
27971    '210,1': 'Asia/Tehran',
27972    '240,0': 'Asia/Dubai',
27973    '240,1': 'Asia/Baku',
27974    '270,0': 'Asia/Kabul',
27975    '300,1': 'Asia/Yekaterinburg',
27976    '300,0': 'Asia/Karachi',
27977    '330,0': 'Asia/Kolkata',
27978    '345,0': 'Asia/Kathmandu',
27979    '360,0': 'Asia/Dhaka',
27980    '360,1': 'Asia/Omsk',
27981    '390,0': 'Asia/Rangoon',
27982    '420,1': 'Asia/Krasnoyarsk',
27983    '420,0': 'Asia/Jakarta',
27984    '480,0': 'Asia/Shanghai',
27985    '480,1': 'Asia/Irkutsk',
27986    '525,0': 'Australia/Eucla',
27987    '525,1,s': 'Australia/Eucla',
27988    '540,1': 'Asia/Yakutsk',
27989    '540,0': 'Asia/Tokyo',
27990    '570,0': 'Australia/Darwin',
27991    '570,1,s': 'Australia/Adelaide',
27992    '600,0': 'Australia/Brisbane',
27993    '600,1': 'Asia/Vladivostok',
27994    '600,1,s': 'Australia/Sydney',
27995    '630,1,s': 'Australia/Lord_Howe',
27996    '660,1': 'Asia/Kamchatka',
27997    '660,0': 'Pacific/Noumea',
27998    '690,0': 'Pacific/Norfolk',
27999    '720,1,s': 'Pacific/Auckland',
28000    '720,0': 'Pacific/Majuro',
28001    '765,1,s': 'Pacific/Chatham',
28002    '780,0': 'Pacific/Tongatapu',
28003    '780,1,s': 'Pacific/Apia',
28004    '840,0': 'Pacific/Kiritimati'
28005};
28006
28007/* Build time: 2014-11-28 11:10:50Z Build by invoking python utilities/dst.py generate */
28008jstz.olson.dst_rules = {
28009    "years": [
28010        2008,
28011        2009,
28012        2010,
28013        2011,
28014        2012,
28015        2013,
28016        2014
28017    ],
28018    "zones": [
28019        {
28020            "name": "Africa/Cairo",
28021            "rules": [
28022                {
28023                    "e": 1219957200000,
28024                    "s": 1209074400000
28025                },
28026                {
28027                    "e": 1250802000000,
28028                    "s": 1240524000000
28029                },
28030                {
28031                    "e": 1285880400000,
28032                    "s": 1284069600000
28033                },
28034                false,
28035                false,
28036                false,
28037                {
28038                    "e": 1411678800000,
28039                    "s": 1406844000000
28040                }
28041            ]
28042        },
28043        {
28044            "name": "America/Asuncion",
28045            "rules": [
28046                {
28047                    "e": 1205031600000,
28048                    "s": 1224388800000
28049                },
28050                {
28051                    "e": 1236481200000,
28052                    "s": 1255838400000
28053                },
28054                {
28055                    "e": 1270954800000,
28056                    "s": 1286078400000
28057                },
28058                {
28059                    "e": 1302404400000,
28060                    "s": 1317528000000
28061                },
28062                {
28063                    "e": 1333854000000,
28064                    "s": 1349582400000
28065                },
28066                {
28067                    "e": 1364094000000,
28068                    "s": 1381032000000
28069                },
28070                {
28071                    "e": 1395543600000,
28072                    "s": 1412481600000
28073                }
28074            ]
28075        },
28076        {
28077            "name": "America/Campo_Grande",
28078            "rules": [
28079                {
28080                    "e": 1203217200000,
28081                    "s": 1224388800000
28082                },
28083                {
28084                    "e": 1234666800000,
28085                    "s": 1255838400000
28086                },
28087                {
28088                    "e": 1266721200000,
28089                    "s": 1287288000000
28090                },
28091                {
28092                    "e": 1298170800000,
28093                    "s": 1318737600000
28094                },
28095                {
28096                    "e": 1330225200000,
28097                    "s": 1350792000000
28098                },
28099                {
28100                    "e": 1361070000000,
28101                    "s": 1382241600000
28102                },
28103                {
28104                    "e": 1392519600000,
28105                    "s": 1413691200000
28106                }
28107            ]
28108        },
28109        {
28110            "name": "America/Goose_Bay",
28111            "rules": [
28112                {
28113                    "e": 1225594860000,
28114                    "s": 1205035260000
28115                },
28116                {
28117                    "e": 1257044460000,
28118                    "s": 1236484860000
28119                },
28120                {
28121                    "e": 1289098860000,
28122                    "s": 1268539260000
28123                },
28124                {
28125                    "e": 1320555600000,
28126                    "s": 1299988860000
28127                },
28128                {
28129                    "e": 1352005200000,
28130                    "s": 1331445600000
28131                },
28132                {
28133                    "e": 1383454800000,
28134                    "s": 1362895200000
28135                },
28136                {
28137                    "e": 1414904400000,
28138                    "s": 1394344800000
28139                }
28140            ]
28141        },
28142        {
28143            "name": "America/Havana",
28144            "rules": [
28145                {
28146                    "e": 1224997200000,
28147                    "s": 1205643600000
28148                },
28149                {
28150                    "e": 1256446800000,
28151                    "s": 1236488400000
28152                },
28153                {
28154                    "e": 1288501200000,
28155                    "s": 1268542800000
28156                },
28157                {
28158                    "e": 1321160400000,
28159                    "s": 1300597200000
28160                },
28161                {
28162                    "e": 1352005200000,
28163                    "s": 1333256400000
28164                },
28165                {
28166                    "e": 1383454800000,
28167                    "s": 1362891600000
28168                },
28169                {
28170                    "e": 1414904400000,
28171                    "s": 1394341200000
28172                }
28173            ]
28174        },
28175        {
28176            "name": "America/Mazatlan",
28177            "rules": [
28178                {
28179                    "e": 1225008000000,
28180                    "s": 1207472400000
28181                },
28182                {
28183                    "e": 1256457600000,
28184                    "s": 1238922000000
28185                },
28186                {
28187                    "e": 1288512000000,
28188                    "s": 1270371600000
28189                },
28190                {
28191                    "e": 1319961600000,
28192                    "s": 1301821200000
28193                },
28194                {
28195                    "e": 1351411200000,
28196                    "s": 1333270800000
28197                },
28198                {
28199                    "e": 1382860800000,
28200                    "s": 1365325200000
28201                },
28202                {
28203                    "e": 1414310400000,
28204                    "s": 1396774800000
28205                }
28206            ]
28207        },
28208        {
28209            "name": "America/Mexico_City",
28210            "rules": [
28211                {
28212                    "e": 1225004400000,
28213                    "s": 1207468800000
28214                },
28215                {
28216                    "e": 1256454000000,
28217                    "s": 1238918400000
28218                },
28219                {
28220                    "e": 1288508400000,
28221                    "s": 1270368000000
28222                },
28223                {
28224                    "e": 1319958000000,
28225                    "s": 1301817600000
28226                },
28227                {
28228                    "e": 1351407600000,
28229                    "s": 1333267200000
28230                },
28231                {
28232                    "e": 1382857200000,
28233                    "s": 1365321600000
28234                },
28235                {
28236                    "e": 1414306800000,
28237                    "s": 1396771200000
28238                }
28239            ]
28240        },
28241        {
28242            "name": "America/Miquelon",
28243            "rules": [
28244                {
28245                    "e": 1225598400000,
28246                    "s": 1205038800000
28247                },
28248                {
28249                    "e": 1257048000000,
28250                    "s": 1236488400000
28251                },
28252                {
28253                    "e": 1289102400000,
28254                    "s": 1268542800000
28255                },
28256                {
28257                    "e": 1320552000000,
28258                    "s": 1299992400000
28259                },
28260                {
28261                    "e": 1352001600000,
28262                    "s": 1331442000000
28263                },
28264                {
28265                    "e": 1383451200000,
28266                    "s": 1362891600000
28267                },
28268                {
28269                    "e": 1414900800000,
28270                    "s": 1394341200000
28271                }
28272            ]
28273        },
28274        {
28275            "name": "America/Santa_Isabel",
28276            "rules": [
28277                {
28278                    "e": 1225011600000,
28279                    "s": 1207476000000
28280                },
28281                {
28282                    "e": 1256461200000,
28283                    "s": 1238925600000
28284                },
28285                {
28286                    "e": 1288515600000,
28287                    "s": 1270375200000
28288                },
28289                {
28290                    "e": 1319965200000,
28291                    "s": 1301824800000
28292                },
28293                {
28294                    "e": 1351414800000,
28295                    "s": 1333274400000
28296                },
28297                {
28298                    "e": 1382864400000,
28299                    "s": 1365328800000
28300                },
28301                {
28302                    "e": 1414314000000,
28303                    "s": 1396778400000
28304                }
28305            ]
28306        },
28307        {
28308            "name": "America/Sao_Paulo",
28309            "rules": [
28310                {
28311                    "e": 1203213600000,
28312                    "s": 1224385200000
28313                },
28314                {
28315                    "e": 1234663200000,
28316                    "s": 1255834800000
28317                },
28318                {
28319                    "e": 1266717600000,
28320                    "s": 1287284400000
28321                },
28322                {
28323                    "e": 1298167200000,
28324                    "s": 1318734000000
28325                },
28326                {
28327                    "e": 1330221600000,
28328                    "s": 1350788400000
28329                },
28330                {
28331                    "e": 1361066400000,
28332                    "s": 1382238000000
28333                },
28334                {
28335                    "e": 1392516000000,
28336                    "s": 1413687600000
28337                }
28338            ]
28339        },
28340        {
28341            "name": "Asia/Amman",
28342            "rules": [
28343                {
28344                    "e": 1225404000000,
28345                    "s": 1206655200000
28346                },
28347                {
28348                    "e": 1256853600000,
28349                    "s": 1238104800000
28350                },
28351                {
28352                    "e": 1288303200000,
28353                    "s": 1269554400000
28354                },
28355                {
28356                    "e": 1319752800000,
28357                    "s": 1301608800000
28358                },
28359                false,
28360                false,
28361                {
28362                    "e": 1414706400000,
28363                    "s": 1395957600000
28364                }
28365            ]
28366        },
28367        {
28368            "name": "Asia/Damascus",
28369            "rules": [
28370                {
28371                    "e": 1225486800000,
28372                    "s": 1207260000000
28373                },
28374                {
28375                    "e": 1256850000000,
28376                    "s": 1238104800000
28377                },
28378                {
28379                    "e": 1288299600000,
28380                    "s": 1270159200000
28381                },
28382                {
28383                    "e": 1319749200000,
28384                    "s": 1301608800000
28385                },
28386                {
28387                    "e": 1351198800000,
28388                    "s": 1333058400000
28389                },
28390                {
28391                    "e": 1382648400000,
28392                    "s": 1364508000000
28393                },
28394                {
28395                    "e": 1414702800000,
28396                    "s": 1395957600000
28397                }
28398            ]
28399        },
28400        {
28401            "name": "Asia/Dubai",
28402            "rules": [
28403                false,
28404                false,
28405                false,
28406                false,
28407                false,
28408                false,
28409                false
28410            ]
28411        },
28412        {
28413            "name": "Asia/Gaza",
28414            "rules": [
28415                {
28416                    "e": 1219957200000,
28417                    "s": 1206655200000
28418                },
28419                {
28420                    "e": 1252015200000,
28421                    "s": 1238104800000
28422                },
28423                {
28424                    "e": 1281474000000,
28425                    "s": 1269640860000
28426                },
28427                {
28428                    "e": 1312146000000,
28429                    "s": 1301608860000
28430                },
28431                {
28432                    "e": 1348178400000,
28433                    "s": 1333058400000
28434                },
28435                {
28436                    "e": 1380229200000,
28437                    "s": 1364508000000
28438                },
28439                {
28440                    "e": 1411678800000,
28441                    "s": 1395957600000
28442                }
28443            ]
28444        },
28445        {
28446            "name": "Asia/Irkutsk",
28447            "rules": [
28448                {
28449                    "e": 1224957600000,
28450                    "s": 1206813600000
28451                },
28452                {
28453                    "e": 1256407200000,
28454                    "s": 1238263200000
28455                },
28456                {
28457                    "e": 1288461600000,
28458                    "s": 1269712800000
28459                },
28460                false,
28461                false,
28462                false,
28463                false
28464            ]
28465        },
28466        {
28467            "name": "Asia/Jerusalem",
28468            "rules": [
28469                {
28470                    "e": 1223161200000,
28471                    "s": 1206662400000
28472                },
28473                {
28474                    "e": 1254006000000,
28475                    "s": 1238112000000
28476                },
28477                {
28478                    "e": 1284246000000,
28479                    "s": 1269561600000
28480                },
28481                {
28482                    "e": 1317510000000,
28483                    "s": 1301616000000
28484                },
28485                {
28486                    "e": 1348354800000,
28487                    "s": 1333065600000
28488                },
28489                {
28490                    "e": 1382828400000,
28491                    "s": 1364515200000
28492                },
28493                {
28494                    "e": 1414278000000,
28495                    "s": 1395964800000
28496                }
28497            ]
28498        },
28499        {
28500            "name": "Asia/Kamchatka",
28501            "rules": [
28502                {
28503                    "e": 1224943200000,
28504                    "s": 1206799200000
28505                },
28506                {
28507                    "e": 1256392800000,
28508                    "s": 1238248800000
28509                },
28510                {
28511                    "e": 1288450800000,
28512                    "s": 1269698400000
28513                },
28514                false,
28515                false,
28516                false,
28517                false
28518            ]
28519        },
28520        {
28521            "name": "Asia/Krasnoyarsk",
28522            "rules": [
28523                {
28524                    "e": 1224961200000,
28525                    "s": 1206817200000
28526                },
28527                {
28528                    "e": 1256410800000,
28529                    "s": 1238266800000
28530                },
28531                {
28532                    "e": 1288465200000,
28533                    "s": 1269716400000
28534                },
28535                false,
28536                false,
28537                false,
28538                false
28539            ]
28540        },
28541        {
28542            "name": "Asia/Omsk",
28543            "rules": [
28544                {
28545                    "e": 1224964800000,
28546                    "s": 1206820800000
28547                },
28548                {
28549                    "e": 1256414400000,
28550                    "s": 1238270400000
28551                },
28552                {
28553                    "e": 1288468800000,
28554                    "s": 1269720000000
28555                },
28556                false,
28557                false,
28558                false,
28559                false
28560            ]
28561        },
28562        {
28563            "name": "Asia/Vladivostok",
28564            "rules": [
28565                {
28566               
28566     "e": 1224950400000,
28567                    "s": 1206806400000
28568                },
28569                {
28570                    "e": 1256400000000,
28571                    "s": 1238256000000
28572                },
28573                {
28574                    "e": 1288454400000,
28575                    "s": 1269705600000
28576                },
28577                false,
28578                false,
28579                false,
28580                false
28581            ]
28582        },
28583        {
28584            "name": "Asia/Yakutsk",
28585            "rules": [
28586                {
28587                    "e": 1224954000000,
28588                    "s": 1206810000000
28589                },
28590                {
28591                    "e": 1256403600000,
28592                    "s": 1238259600000
28593                },
28594                {
28595                    "e": 1288458000000,
28596                    "s": 1269709200000
28597                },
28598                false,
28599                false,
28600                false,
28601                false
28602            ]
28603        },
28604        {
28605            "name": "Asia/Yekaterinburg",
28606            "rules": [
28607                {
28608                    "e": 1224968400000,
28609                    "s": 1206824400000
28610                },
28611                {
28612                    "e": 1256418000000,
28613                    "s": 1238274000000
28614                },
28615                {
28616                    "e": 1288472400000,
28617                    "s": 1269723600000
28618                },
28619                false,
28620                false,
28621                false,
28622                false
28623            ]
28624        },
28625        {
28626            "name": "Asia/Yerevan",
28627            "rules": [
28628                {
28629                    "e": 1224972000000,
28630                    "s": 1206828000000
28631                },
28632                {
28633                    "e": 1256421600000,
28634                    "s": 1238277600000
28635                },
28636                {
28637                    "e": 1288476000000,
28638                    "s": 1269727200000
28639                },
28640                {
28641                    "e": 1319925600000,
28642                    "s": 1301176800000
28643                },
28644                false,
28645                false,
28646                false
28647            ]
28648        },
28649        {
28650            "name": "Australia/Lord_Howe",
28651            "rules": [
28652                {
28653                    "e": 1207407600000,
28654                    "s": 1223134200000
28655                },
28656                {
28657                    "e": 1238857200000,
28658                    "s": 1254583800000
28659                },
28660                {
28661                    "e": 1270306800000,
28662                    "s": 1286033400000
28663                },
28664                {
28665                    "e": 1301756400000,
28666                    "s": 1317483000000
28667                },
28668                {
28669                    "e": 1333206000000,
28670                    "s": 1349537400000
28671                },
28672                {
28673                    "e": 1365260400000,
28674                    "s": 1380987000000
28675                },
28676                {
28677                    "e": 1396710000000,
28678                    "s": 1412436600000
28679                }
28680            ]
28681        },
28682        {
28683            "name": "Australia/Perth",
28684            "rules": [
28685                {
28686                    "e": 1206813600000,
28687                    "s": 1224957600000
28688                },
28689                false,
28690                false,
28691                false,
28692                false,
28693                false,
28694                false
28695            ]
28696        },
28697        {
28698            "name": "Europe/Helsinki",
28699            "rules": [
28700                {
28701                    "e": 1224982800000,
28702                    "s": 1206838800000
28703                },
28704                {
28705                    "e": 1256432400000,
28706                    "s": 1238288400000
28707                },
28708                {
28709                    "e": 1288486800000,
28710                    "s": 1269738000000
28711                },
28712                {
28713                    "e": 1319936400000,
28714                    "s": 1301187600000
28715                },
28716                {
28717                    "e": 1351386000000,
28718                    "s": 1332637200000
28719                },
28720                {
28721                    "e": 1382835600000,
28722                    "s": 1364691600000
28723                },
28724                {
28725                    "e": 1414285200000,
28726                    "s": 1396141200000
28727                }
28728            ]
28729        },
28730        {
28731            "name": "Europe/Minsk",
28732            "rules": [
28733                {
28734                    "e": 1224979200000,
28735                    "s": 1206835200000
28736                },
28737                {
28738                    "e": 1256428800000,
28739                    "s": 1238284800000
28740                },
28741                {
28742                    "e": 1288483200000,
28743                    "s": 1269734400000
28744                },
28745                false,
28746                false,
28747                false,
28748                false
28749            ]
28750        },
28751        {
28752            "name": "Europe/Moscow",
28753            "rules": [
28754                {
28755                    "e": 1224975600000,
28756                    "s": 1206831600000
28757                },
28758                {
28759                    "e": 1256425200000,
28760                    "s": 1238281200000
28761                },
28762                {
28763                    "e": 1288479600000,
28764                    "s": 1269730800000
28765                },
28766                false,
28767                false,
28768                false,
28769                false
28770            ]
28771        },
28772        {
28773            "name": "Pacific/Apia",
28774            "rules": [
28775                false,
28776                false,
28777                false,
28778                {
28779                    "e": 1301752800000,
28780                    "s": 1316872800000
28781                },
28782                {
28783                    "e": 1333202400000,
28784                    "s": 1348927200000
28785                },
28786                {
28787                    "e": 1365256800000,
28788                    "s": 1380376800000
28789                },
28790                {
28791                    "e": 1396706400000,
28792                    "s": 1411826400000
28793                }
28794            ]
28795        },
28796        {
28797            "name": "Pacific/Fiji",
28798            "rules": [
28799                false,
28800                false,
28801                {
28802                    "e": 1269698400000,
28803                    "s": 1287842400000
28804                },
28805                {
28806                    "e": 1327154400000,
28807                    "s": 1319292000000
28808                },
28809                {
28810                    "e": 1358604000000,
28811                    "s": 1350741600000
28812                },
28813                {
28814                    "e": 1390050000000,
28815                    "s": 1382796000000
28816                },
28817                {
28818                    "e": 1421503200000,
28819                    "s": 1414850400000
28820                }
28821            ]
28822        }
28823    ]
28824};    if (typeof exports !== 'undefined') {
28825        exports.jstz = jstz;
28826    } else {
28827        root.jstz = jstz;
28828    }
28829})(this);
28830
28831
28832/**
28833 * Initialize the DAVCal script, attaching some event handlers and triggering
28834 * the initial load of the fullcalendar JS
28835 */
28836jQuery(function() {
28837    // Redefine functions for using moment.js with datetimepicker
28838    
28839    Date.parseDate = function( input, format ){
28840      return moment(input,format).toDate();
28841    };
28842    Date.prototype.dateFormat = function( format ){
28843      return moment(this).format(format);
28844    };
28845    
28846    // Attach to event links
28847    var calendarpage = jQuery('#fullCalendar').data('calendarpage');
28848    if(!calendarpage) return;
28849    dw_davcal__modals.page = calendarpage;
28850    
28851    jQuery('div.fullCalendarSettings a').each(function() {
28852        var $link = jQuery(this);
28853        var href = $link.attr('href');
28854        if (!href) return;
28855
28856        $link.click(
28857            function(e) {
28858                dw_davcal__modals.showSettingsDialog();
28859                e.preventDefault();
28860                return '';
28861            }
28862        );
28863        }
28864    );
28865    
28866    // First, retrieve the current settings.
28867    // Upon success, initialize fullcalendar.
28868    var postArray = { };
28869    jQuery.post(
28870        DOKU_BASE + 'lib/exe/ajax.php',
28871        {
28872            call: 'plugin_davcal',
28873            id: dw_davcal__modals.page,
28874            page: dw_davcal__modals.page,
28875            action: 'getSettings',
28876            params: postArray,
28877            sectok: JSINFO.plugin.davcal['sectok']
28878        },
28879        function(data)
28880        {
28881            var result = data['result'];
28882            if(result === true)
28883            {
28884                dw_davcal__modals.settings = data['settings'];
28885                var tz = false;
28886                if(data['settings']['timezone'] !== '')
28887                    tz = data['settings']['timezone'];
28888                // Force-overwrite thhe timezone setting if requested
28889                if(data['settings']['meta']['forcetimezone'] !== 'no')
28890                    tz = data['settings']['meta']['forcetimezone'];
28891                var fcOptions = {
28892                    dayClick: function(date, jsEvent, view) {
28893                        dw_davcal__modals.showEditEventDialog(date, false);
28894                    },
28895                    eventClick: function(calEvent, jsEvent, view) {
28896                        dw_davcal__modals.showEditEventDialog(calEvent, true);
28897                    },
28898                    events: {
28899                        url: DOKU_BASE + 'lib/exe/ajax.php',
28900                        type: 'POST',
28901                        data: {
28902                            call: 'plugin_davcal',
28903                            action: 'getEvents',
28904                            id: dw_davcal__modals.page,
28905                            page: dw_davcal__modals.page,
28906                            sectok: JSINFO.plugin.davcal['sectok']
28907                        },
28908                        error: function() {
28909                            dw_davcal__modals.msg = LANG.plugins.davcal['error_retrieving_data'];
28910                            dw_davcal__modals.showDialog(false);
28911                        }
28912                    },
28913                    header: {
28914                        left: 'title',
28915                        center: 'today prev,next',
28916                        right: 'month,agendaWeek,agendaDay,listWeek'
28917                    },
28918                    locale: JSINFO.plugin.davcal['language'],
28919                    weekNumbers: (data['settings']['weeknumbers'] == 1) ? true : false,
28920                    timezone: tz,
28921                    weekends: (data['settings']['workweek'] == 1) ? false : true,
28922                    firstDay: (data['settings']['monday'] == 1) ? 1 : 0,
28923                    defaultView: data['settings']['meta']['view'],
28924                };
28925                var timeformat = data['settings']['timeformat'];
28926                // Force-overwrite the user's timezone setting if requested by the calendar
28927                if(data['settings']['meta']['forcetimeformat'] !== 'no')
28928                    timeformat = data['settings']['meta']['forcetimeformat'];
28929                if(timeformat !== 'lang')
28930                {
28931                    // If the time format is language-based, we don't need to pass
28932                    // the timeFormat option to fullCalendar
28933                    if(timeformat == '24h')
28934                    {
28935                        fcOptions.timeFormat = 'H:mm';
28936                    }
28937                    if(timeformat == '12h')
28938                    {
28939                        fcOptions.timeFormat = 'h:mmt';
28940                    }
28941                }
28942                for (var key in data['settings']['meta']['fcoptions'])
28943                {
28944                    if(!data['settings']['meta']['fcoptions'].hasOwnProperty(key)) continue;
28945                    
28946                    var val = data['settings']['meta']['fcoptions'][key];
28947                    fcOptions[key] = val;
28948                }
28949                var detectedTz = jstz.determine().name();
28950                dw_davcal__modals.detectedTz = detectedTz;
28951                // The current TZ value holds either the uers's selection or
28952                // the force timezone value
28953                dw_davcal__modals.currentTz = (tz === false) ? '' : tz;
28954                // Initialize the davcal popup
28955                var res = jQuery('#fullCalendar').fullCalendar(fcOptions);
28956            }
28957        }
28958    );    
28959});
28960
28961/**
28962 * This holds all modal windows that DAVCal uses.
28963 */
28964var dw_davcal__modals = {
28965    $editEventDialog: null,
28966    $dialog: null,
28967    $settingsDialog: null,
28968    $inputDialog: null,
28969    msg: null,
28970    completeCb: null,
28971    action: null,
28972    uid: null,
28973    settings: null,
28974    page: null,
28975    detectedTz: null,
28976    currentTz: null,
28977    
28978    /**
28979     * Show the settings dialog
28980     */
28981    // FIXME: Hide URLs for multi-calendar
28982    showSettingsDialog : function() {
28983        if(dw_davcal__modals.$settingsDialog)
28984            return;
28985
28986        // Dialog buttons are language-dependent and defined here.
28987        // Attach event handlers for save and cancel.
28988        var dialogButtons = {};
28989        if(!JSINFO.plugin.davcal['disable_settings'])
28990        {
28991            dialogButtons[LANG.plugins.davcal['save']] = function() {
28992                var postArray = { };
28993                jQuery("input[class=dw_davcal__settings], select[class=dw_davcal__settings]").each(function() {
28994                  if(jQuery(this).attr('type') == 'checkbox')
28995                  {
28996                      postArray[jQuery(this).prop('name')] = jQuery(this).prop('checked') ? 1 : 0;
28997                  }
28998                  else
28999                  {
29000                      postArray[jQuery(this).prop('name')] = jQuery(this).val();
29001                  }
29002                });
29003                jQuery('#dw_davcal__ajaxsettings').html('<img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="" width="16" height="16" />');
29004                jQuery.post(
29005                    DOKU_BASE + 'lib/exe/ajax.php',
29006                    {
29007                        call: 'plugin_davcal',
29008                        id: dw_davcal__modals.page,
29009                        page: dw_davcal__modals.page,
29010                        action: 'saveSettings',
29011                        params: postArray,
29012                        sectok: JSINFO.plugin.davcal['sectok']
29013                    },
29014                    function(data)
29015                    {
29016                        var result = data['result'];
29017                        var html = data['html'];
29018                        jQuery('#dw_davcal__ajaxsettings').html(html);
29019                        if(result === true)
29020                        {
29021                            location.reload();
29022                        }
29023                    }
29024                );
29025            };
29026        }
29027        dialogButtons[LANG.plugins.davcal['cancel']] = function () {
29028            dw_davcal__modals.hideSettingsDialog();
29029        };
29030        
29031        var settingsHtml = '<div><table>';
29032        
29033        if(JSINFO.plugin.davcal['disable_settings'] && JSINFO.plugin.davcal['disable_sync'] && JSINFO.plugin.davcal['disable_ics'])
29034        {
29035            settingsHtml += LANG.plugins.davcal['nothing_to_show'];
29036        }
29037        
29038        if(!JSINFO.plugin.davcal['disable_settings'])
29039        {
29040            settingsHtml += '<tr><td>' + LANG.plugins.davcal['timezone'] + '</td><td><select name="timezone" id="dw_davcal__settings_timezone" class="dw_davcal__settings"></select></td></tr>' +
29041            '<tr><td>' + LANG.plugins.davcal['timeformat'] + '</td><td><select name="timeformat" id="dw_davcal__settings_timeformat" class="dw_davcal__settings"></select></td></tr>' +
29042            '<tr><td>' + LANG.plugins.davcal['weeknumbers'] + '</td><td><input type="checkbox" name="weeknumbers" id="dw_davcal__settings_weeknumbers" class="dw_davcal__settings"></td></tr>' +
29043            '<tr><td>' + LANG.plugins.davcal['only_workweek'] + '</td><td><input type="checkbox" name="workweek" id="dw_davcal__settings_workweek" class="dw_davcal__settings"></td></tr>' +
29044            '<tr><td>' + LANG.plugins.davcal['start_monday'] + '</td><td><input type="checkbox" name="monday" id="dw_davcal__settings_monday" class="dw_davcal__settings"></td></tr>';
29045         }
29046         
29047         if(!JSINFO.plugin.davcal['disable_sync'])
29048         {
29049             settingsHtml += '<tr id="dw_davcal__settings_syncurl"><td>' + LANG.plugins.davcal['sync_url'] + '</td><td><input type="text" name="syncurl" readonly="readonly" id="dw_davcal__settings_syncurl_edit" class="dw_davcal__text" value="' + dw_davcal__modals.settings['syncurl'] + '"></td></tr>';
29050             settingsHtml += '<tr id="dw_davcal__settings_principalurl"><td>' + LANG.plugins.davcal['sync_ical'] + '</td><td><input type="text" name="principalurl" readonly="readonly" id="dw_davcal__settings_principalurl_edit" class="dw_davcal__text" value="' + dw_davcal__modals.settings['principalurl'] + '"></td></tr>';
29051         }
29052         
29053         if(!JSINFO.plugin.davcal['disable_ics'])
29054         {
29055             settingsHtml += '<tr id="dw_davcal__settings_privateurl"><td>' + LANG.plugins.davcal['private_url'] + '</td><td><input type="text" name="privateurl" readonly="readonly" id="dw_davcal__settings_privateurl_edit" class="dw_davcal__text" value="' + dw_davcal__modals.settings['privateurl'] + '"></td></tr>';
29056         }
29057         
29058         settingsHtml += '</table>' +
29059            '</div>' +
29060            '<div id="dw_davcal__ajaxsettings"></div>';
29061        
29062        dw_davcal__modals.$settingsDialog = jQuery(document.createElement('div'))
29063       .dialog({
29064           autoOpen: false,
29065           draggable: true,
29066           // fix for dragging: http://stackoverflow.com/questions/17247486/jquery-ui-dialog-dragging-issues
29067           drag: function(event, ui) {
29068               var fixPix = jQuery(document).scrollTop();
29069               iObj = ui.position;
29070               iObj.top = iObj.top - fixPix;
29071               jQuery(this).closest(".ui-dialog").css("top", iObj.top + "px");
29072           },
29073           title: LANG.plugins.davcal['settings'],
29074           resizable: true,         
29075           buttons: dialogButtons,
29076       })
29077       .html(
29078           settingsHtml
29079            )
29080       .parent()
29081       .attr('id','dw_davcal__settings')
29082       .show()
29083       .appendTo('.dokuwiki:first');
29084       
29085       jQuery('#dw_davcal__settings').position({
29086           my: "center",
29087           at: "center",
29088           of: window
29089       });
29090       
29091       // Initialize current settings
29092        
29093        if(!JSINFO.plugin.davcal['disable_settings'])
29094        {
29095            var $tzdropdown = jQuery('#dw_davcal__settings_timezone');
29096            jQuery('#fullCalendarTimezoneList option').each(function() {
29097                jQuery('<option />', {value: jQuery(this).val(), 
29098                        text: jQuery(this).text()}).appendTo($tzdropdown);
29099            });
29100            
29101            var $tfdropdown = jQuery('#dw_davcal__settings_timeformat');
29102            jQuery('<option />', {value: 'lang', text: LANG.plugins.davcal['language_specific']}).appendTo($tfdropdown);
29103            jQuery('<option />', {value: '24h', text: '24h'}).appendTo($tfdropdown);
29104            jQuery('<option />', {value: '12h', text: '12h'}).appendTo($tfdropdown);
29105            
29106            if(!JSINFO.plugin.davcal['disable_sync'])
29107            {
29108                jQuery('#dw_davcal__settings_syncurl_edit').on('click', function() {
29109                    jQuery(this).select();
29110                });
29111                jQuery('#dw_davcal__settings_principalurl_edit').on('click', function() {
29112                    jQuery(this).select();
29113                });
29114            }
29115            
29116            if(!JSINFO.plugin.davcal['disable_ics'])
29117            {
29118                jQuery('#dw_davcal__settings_privateurl_edit').on('click', function() {
29119                    jQuery(this).select(); 
29120                });
29121            }
29122            
29123            if(dw_davcal__modals.settings)
29124            {
29125                if(dw_davcal__modals.settings['timeformat'] !== '')
29126                    jQuery('#dw_davcal__settings_timeformat').val(dw_davcal__modals.settings['timeformat']);
29127                if(dw_davcal__modals.settings['timezone'] !== '')
29128                    jQuery('#dw_davcal__settings_timezone').val(dw_davcal__modals.settings['timezone']);
29129                if(dw_davcal__modals.settings['weeknumbers'] == 1)
29130                    jQuery('#dw_davcal__settings_weeknumbers').prop('checked', true);
29131                else
29132                    jQuery('#dw_davcal__settings_weeknumbers').prop('checked', false);
29133                    
29134                if(dw_davcal__modals.settings['workweek'] == 1)
29135                    jQuery('#dw_davcal__settings_workweek').prop('checked', true);
29136                else
29137                    jQuery('#dw_davcal__settings_workweek').prop('checked', false);
29138                    
29139                if(dw_davcal__modals.settings['monday'] == 1)
29140                    jQuery('#dw_davcal__settings_monday').prop('checked', true);
29141                else
29142                    jQuery('#dw_davcal__settings_monday').prop('checked', false);
29143                if(dw_davcal__modals.settings['meta']['forcetimezone'] !== 'no')
29144                    jQuery('#dw_davcal__settings_timezone').prop('disabled', true);
29145                if(dw_davcal__modals.settings['meta']['forcetimeformat'] !== 'no')
29146                    jQuery('#dw_davcal__settings_timeformat').prop('disabled', true);
29147            }
29148        }
29149
29150        // attach event handlers
29151        jQuery('#dw_davcal__settings .ui-dialog-titlebar-close').click(function(){
29152          dw_davcal__modals.hideSettingsDialog();
29153        });
29154    },
29155    
29156    /**
29157     * Sanity-check our events.
29158     * 
29159     * @return boolean false on failure, otherwise true
29160     */
29161    checkEvents : function() {
29162        // Retrieve dates
29163        var allDay = jQuery('#dw_davcal__allday_edit').prop('checked');
29164        var startDate = moment(jQuery('#dw_davcal__eventfrom_edit').val(), 'YYYY-MM-DD');
29165        var endDate = moment(jQuery('#dw_davcal__eventto_edit').val(), 'YYYY-MM-DD');
29166        
29167        // Do the checking
29168        if(!allDay)
29169        {
29170            var startTime = moment.duration(jQuery('#dw_davcal__eventfromtime_edit').val());
29171            var endTime = moment.duration(jQuery('#dw_davcal__eventtotime_edit').val());
29172            startDate.add(startTime);
29173            endDate.add(endTime);
29174        }
29175        if(!startDate.isValid())
29176        {
29177            dw_davcal__modals.msg = LANG.plugins.davcal['start_date_invalid'];
29178            dw_davcal__modals.showDialog(false);
29179            return false;
29180        }
29181        if(!endDate.isValid())
29182        {
29183            dw_davcal__modals.msg = LANG.plugins.davcal['end_date_invalid'];
29184            dw_davcal__modals.showDialog(false);
29185            return false;
29186        }
29187        if(endDate.isBefore(startDate))
29188        {
29189            dw_davcal__modals.msg = LANG.plugins.davcal['end_date_before_start_date'];
29190            dw_davcal__modals.showDialog(false);
29191            return false;
29192        }
29193        if(!allDay && endDate.isSame(startDate))
29194        {
29195            dw_davcal__modals.msg = LANG.plugins.davcal['end_date_is_same_as_start_date'];
29196            dw_davcal__modals.showDialog(false);
29197            return false;
29198        }
29199        return true;
29200    },
29201    
29202    /**
29203     * Show the edit event dialog, which is also used to create new events
29204     * @param {Object} event The event to create, that is the date or the calEvent
29205     * @param {Object} edit  Whether we edit (true) or create a new event (false)
29206     */
29207    showEditEventDialog : function(event, edit) {
29208        if(dw_davcal__modals.$editEventDialog)
29209            return;
29210        
29211        var readonly = true;
29212        for(var i=0; i<dw_davcal__modals.settings['calids'].length; i++)
29213        {
29214            if(edit)
29215            {
29216                // Use the specific calendar setting if we edit an event
29217                if(event.page == dw_davcal__modals.settings['calids'][i]['page'])
29218                  readonly = !dw_davcal__modals.settings['calids'][i]['write'];
29219            }
29220            else
29221            {
29222                // If there is at least one writable calendar,
29223                // we set readonly to false
29224                if(dw_davcal__modals.settings['calids'][i]['write'])
29225                  readonly = false;
29226            }
29227        }
29228
29229        var title = '';   
29230        var dialogButtons = {};
29231        var calEvent = [];
29232        var recurringWarning = '';
29233        // Buttons are dependent on edit or create
29234        // Several possibilities:
29235        //
29236        // 1) Somebody tries to edit, it is not recurring and not readonly -> show
29237        // 2) Somebody tries to edit, it is recurring and not readonly -> message
29238        // 3) Somebody tries to edit, it is readonly -> message
29239        // 4) Somebody tries to create and it is readonly -> message
29240        // 5) Somebody tries to create -> show
29241        if(edit && (event.recurring != true) && (readonly === false))
29242        {
29243            calEvent = event;
29244            title = LANG.plugins.davcal['edit_event'];
29245            dialogButtons[LANG.plugins.davcal['edit']] = function() {
29246                if(!dw_davcal__modals.checkEvents())
29247                  return;
29248                var postArray = { };
29249                var attachArr = new Array();
29250                var pageid = calEvent.page;
29251
29252                jQuery('.dw_davcal__editevent_attachment_link').each(function() {
29253                    var attachment = jQuery(this).attr('href');
29254                    if(attachment != undefined)
29255                    {
29256                        attachArr.push(attachment);
29257                    }
29258                });
29259                postArray['attachments'] = attachArr;
29260                jQuery("input.dw_davcal__editevent, textarea.dw_davcal__editevent").each(function() {
29261                  if(jQuery(this).attr('type') == 'checkbox')
29262                  {
29263                      postArray[jQuery(this).prop('name')] = jQuery(this).prop('checked') ? 1 : 0;
29264                  }
29265                  else
29266                  {
29267                      postArray[jQuery(this).prop('name')] = jQuery(this).val();
29268                  }
29269                });
29270                jQuery('#dw_davcal__ajaxedit').html('<img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="" width="16" height="16" />');
29271                jQuery.post(
29272                    DOKU_BASE + 'lib/exe/ajax.php',
29273                    {
29274                        call: 'plugin_davcal',
29275                        id: pageid,
29276                        page: dw_davcal__modals.page,
29277                        action: 'editEvent',
29278                        params: postArray,
29279                        sectok: JSINFO.plugin.davcal['sectok']
29280                    },
29281                    function(data)
29282                    {
29283                        var result = data['result'];
29284                        var html = data['html'];
29285                        jQuery('#dw_davcal__ajaxedit').html(html);
29286                        if(result === true)
29287                        {
29288                            jQuery('#fullCalendar').fullCalendar('refetchEvents');
29289                            dw_davcal__modals.hideEditEventDialog();
29290                        }
29291                    }
29292                );
29293            };
29294            dialogButtons[LANG.plugins.davcal['delete']] = function() {
29295                dw_davcal__modals.action = 'deleteEvent';
29296                dw_davcal__modals.msg = LANG.plugins.davcal['really_delete_this_event'];
29297                dw_davcal__modals.completeCb = function(data) {
29298                    var result = data['result'];
29299                    var html = data['html'];
29300                    jQuery('#dw_davcal__ajaxedit').html(html);                    
29301                    if(result === true)
29302                    {
29303                        jQuery('#fullCalendar').fullCalendar('refetchEvents');
29304                        dw_davcal__modals.hideEditEventDialog();
29305                    }
29306                };
29307                dw_davcal__modals.showDialog(true);
29308            };
29309        }
29310        else if(edit && (event.recurring == true) && (readonly === false))
29311        {
29312            calEvent = event;
29313            title = LANG.plugins.davcal['edit_event'];
29314            recurringWarning = LANG.plugins.davcal['recurring_cant_edit'];
29315        }
29316        else if(edit && (readonly === true))
29317        {
29318            calEvent = event;
29319            title = LANG.plugins.davcal['edit_event'];
29320            recurringWarning = LANG.plugins.davcal['no_permission'];
29321        }
29322        else if(readonly === true)
29323        {
29324            calEvent.start = event;
29325            calEvent.end = moment(event);
29326            calEvent.start.hour(12);
29327            calEvent.start.minute(0);
29328            calEvent.end.hour(13);
29329            calEvent.end.minute(0);
29330            calEvent.allDay = false;
29331            calEvent.recurring = false;
29332            calEvent.title = '';
29333            calEvent.description = '';
29334            calEvent.id = '0';
29335            calEvent.location = '';
29336            calEvent.page = dw_davcal__modals.page;
29337            title = LANG.plugins.davcal['create_new_event'];
29338            recurringWarning = LANG.plugins.davcal['no_permission'];
29339        }
29340        else
29341        {
29342            calEvent.start = event;
29343            calEvent.end = moment(event);
29344            calEvent.start.hour(12);
29345            calEvent.start.minute(0);
29346            calEvent.end.hour(13);
29347            calEvent.end.minute(0);
29348            calEvent.allDay = false;
29349            calEvent.recurring = false;
29350            calEvent.title = '';
29351            calEvent.description = '';
29352            calEvent.location = '';
29353            calEvent.id = '0';
29354            calEvent.page = dw_davcal__modals.settings['calids'][0]['page'];
29355            title = LANG.plugins.davcal['create_new_event'];
29356            dialogButtons[LANG.plugins.davcal['create']] = function() {
29357                if(!dw_davcal__modals.checkEvents())
29358                  return;
29359
29360                var postArray = { };
29361                var attachArr = new Array();
29362                var pageid = jQuery("#dw_davcal__editevent_calendar option:selected").val();
29363                jQuery("input.dw_davcal__editevent, textarea.dw_davcal__editevent").each(function() {
29364                  if(jQuery(this).attr('type') == 'checkbox')
29365                  {
29366                      postArray[jQuery(this).prop('name')] = jQuery(this).prop('checked') ? 1 : 0;
29367                  }
29368                  else
29369                  {
29370                      postArray[jQuery(this).prop('name')] = jQuery(this).val();
29371                  }
29372                });
29373                jQuery('.dw_davcal__editevent_attachment_link').each(function() {
29374                    var attachment = jQuery(this).attr('href');
29375                    if(attachment != undefined)
29376                    {
29377                        attachArr.push(attachment);
29378                    }
29379                });
29380                postArray['attachments'] = attachArr;
29381                jQuery('#dw_davcal__ajaxedit').html('<img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="" width="16" height="16" />');
29382                jQuery.post(
29383                    DOKU_BASE + 'lib/exe/ajax.php',
29384                    {
29385                        call: 'plugin_davcal',
29386                        id: pageid,
29387                        page: dw_davcal__modals.page,
29388                        action: 'newEvent',
29389                        params: postArray,
29390                        sectok: JSINFO.plugin.davcal['sectok']
29391                    },
29392                    function(data)
29393                    {
29394                        var result = data['result'];
29395                        var html = data['html'];
29396                        jQuery('#dw_davcal__ajaxedit').html(html);
29397                        if(result === true)
29398                        {
29399                            jQuery('#fullCalendar').fullCalendar('refetchEvents');
29400                            dw_davcal__modals.hideEditEventDialog();
29401                        }
29402                    }
29403                );
29404            };
29405        }
29406        dialogButtons[LANG.plugins.davcal['cancel']] = function() {
29407            dw_davcal__modals.hideEditEventDialog();
29408        };
29409        dw_davcal__modals.uid = calEvent.id;
29410        dw_davcal__modals.$editEventDialog = jQuery(document.createElement('div'))
29411       .dialog({
29412           autoOpen: false,
29413           draggable: true,
29414           // fix for dragging: http://stackoverflow.com/questions/17247486/jquery-ui-dialog-dragging-issues
29415           drag: function(event, ui) {
29416               var fixPix = jQuery(document).scrollTop();
29417               iObj = ui.position;
29418               iObj.top = iObj.top - fixPix;
29419               jQuery(this).closest(".ui-dialog").css("top", iObj.top + "px");
29420           },
29421           title: title,
29422           resizable: true,         
29423           buttons: dialogButtons,
29424       })
29425       .html(
29426            '<div><table>' + 
29427            '<tr><td>' + LANG.plugins.davcal['calendar'] + '</td><td><select id="dw_davcal__editevent_calendar"></select></td></tr>' +
29428            '<tr><td>' + LANG.plugins.davcal['title'] + '</td><td><input type="text" id="dw_davcal__eventname_edit" name="eventname" class="dw_davcal__editevent"></td></tr>' +
29429            '<tr><td>' + LANG.plugins.davcal['description'] + '</td><td><textarea name="eventdescription" id="dw_davcal__eventdescription_edit" class="dw_davcal__editevent dw_davcal__text"></textarea></td></tr>' +
29430            '<tr><td>' + LANG.plugins.davcal['location'] + '</td><td><input type="text" id="dw_davcal__eventlocation_edit" name="eventlocation" class="dw_davcal__editevent"></td></tr>' + 
29431            '<tr><td>' + LANG.plugins.davcal['from'] + '</td><td><input type="text" name="eventfrom" id="dw_davcal__eventfrom_edit" class="dw_davcal__editevent dw_davcal__date"><input type="text" name="eventfromtime" id="dw_davcal__eventfromtime_edit" class="dw_davcal__editevent dw_davcal__time"></td></tr>' +
29432            '<tr><td>' + LANG.plugins.davcal['to'] + '</td><td><input type="text" name="eventto" id="dw_davcal__eventto_edit" class="dw_davcal__editevent dw_davcal__date"><input type="text" name="eventtotime" id="dw_davcal__eventtotime_edit" class="dw_davcal__editevent dw_davcal__time"></td></tr>' +
29433            '<tr><td colspan="2"><input type="checkbox" name="allday" id="dw_davcal__allday_edit" class="dw_davcal__editevent">' + LANG.plugins.davcal['allday'] + '</td></tr>' +
29434            '<tr><td>' + LANG.plugins.davcal['attachments'] + '</td><td><table id="dw_davcal__editevent_attachments"><tbody><tr><td><input type="text" id="dw_davcal__editevent_attachment" value="http://"></td><td><a href="#" id="dw_davcal__editevent_attach">' + LANG.plugins.davcal['add_attachment'] + '</a></td></tr></tbody></table></td></tr>' +
29435            '</table>' +
29436            recurringWarning + 
29437            '<input type="hidden" name="uid" id="dw_davcal__uid_edit" class="dw_davcal__editevent">' +
29438            '<input type="hidden" name="detectedtz" id="dw_davcal__tz_edit" class="dw_davcal__editevent">' +
29439            '<input type="hidden" name="currenttz" id="dw_davcal__currenttz_edit" class="dw_davcal__editevent">' +
29440            '</div>' +
29441            '<div id="dw_davcal__ajaxedit"></div>'
29442            )
29443       .parent()
29444       .attr('id','dw_davcal__edit')
29445       .show()
29446       .appendTo('.dokuwiki:first');
29447       
29448       jQuery('#dw_davcal__edit').position({
29449           my: "center",
29450           at: "center",
29451           of: window
29452       });
29453       
29454       // Populate calendar dropdown
29455       var $dropdown = jQuery("#dw_davcal__editevent_calendar");
29456       for(var i=0; i<dw_davcal__modals.settings['calids'].length; i++)
29457       {
29458           var sel = '';
29459           // When creating an event, do not show read-only calendars
29460           if(!edit && (dw_davcal__modals.settings['calids'][i]['write'] === false))
29461             continue;
29462           if(calEvent.page == dw_davcal__modals.settings['calids'][i]['page'])
29463             sel = ' selected="selected"';
29464           $dropdown.append('<option value="' + dw_davcal__modals.settings['calids'][i]['page'] + '"' + sel + '>' + dw_davcal__modals.settings['calids'][i]['name'] + '</option>');
29465       }
29466       if(edit || (dw_davcal__modals.settings['calids'].length < 1))
29467       {
29468           $dropdown.prop('disabled', true);
29469       }
29470       
29471       // Set up existing/predefined values
29472       jQuery('#dw_davcal__tz_edit').val(dw_davcal__modals.detectedTz);
29473       jQuery('#dw_davcal__currenttz_edit').val(dw_davcal__modals.currentTz);
29474       jQuery('#dw_davcal__uid_edit').val(calEvent.id);
29475       jQuery('#dw_davcal__eventname_edit').val(calEvent.title);
29476       jQuery('#dw_davcal__eventlocation_edit').val(calEvent.location);
29477       jQuery('#dw_davcal__eventfrom_edit').val(calEvent.start.format('YYYY-MM-DD'));
29478       jQuery('#dw_davcal__eventfromtime_edit').val(calEvent.start.format('HH:mm'));
29479       jQuery('#dw_davcal__eventdescription_edit').val(calEvent.description);
29480       if(calEvent.attachments && (calEvent.attachments !== null))
29481       {
29482           for(var i=0; i<calEvent.attachments.length; i++)
29483           {
29484               var url = calEvent.attachments[i];
29485               var row = '<tr><td><a href="' + url + '" class="dw_davcal__editevent_attachment_link">' + url + '</a></td><td><a class="deleteLink" href="#">' + LANG.plugins.davcal['delete'] + '</a></td></tr>';
29486               jQuery('#dw_davcal__editevent_attachments > tbody:last').append(row);
29487
29488           }
29489       }
29490       dw_davcal__modals.attachAttachmentDeleteHandlers();
29491       jQuery('#dw_davcal__editevent_attach').on("click", function(e)
29492       {
29493           e.preventDefault();
29494           var url = jQuery('#dw_davcal__editevent_attachment').val();
29495           if(url == '')
29496             return false;
29497           jQuery('#dw_davcal__editevent_attachment').val('http://');
29498           var row = '<tr><td><a href="' + url + '" class="dw_davcal__editevent_attachment_link">' + url + '</a></td><td><a class="deleteLink" href="#">' + LANG.plugins.davcal['delete'] + '</a></td></tr>';
29499           jQuery('#dw_davcal__editevent_attachments > tbody:last').append(row);
29500           dw_davcal__modals.attachAttachmentDeleteHandlers();
29501           return false;
29502       });
29503       if(calEvent.allDay && (calEvent.end === null))
29504       {
29505           jQuery('#dw_davcal__eventto_edit').val(calEvent.start.format('YYYY-MM-DD'));
29506           jQuery('#dw_davcal__eventtotime_edit').val(calEvent.start.format('HH:mm'));
29507       }
29508       else if(calEvent.allDay)
29509       {
29510           endEvent = moment(calEvent.end);
29511           endEvent.subtract(1, 'days');
29512           jQuery('#dw_davcal__eventto_edit').val(endEvent.format('YYYY-MM-DD'));
29513           jQuery('#dw_davcal__eventotime_edit').val(endEvent.format('HH:mm'));
29514       }
29515       else
29516       {
29517           jQuery('#dw_davcal__eventto_edit').val(calEvent.end.format('YYYY-MM-DD'));
29518           jQuery('#dw_davcal__eventtotime_edit').val(calEvent.end.format('HH:mm'));
29519       }
29520       jQuery('#dw_davcal__allday_edit').prop('checked', calEvent.allDay);
29521       
29522        // attach event handlers
29523        jQuery('#dw_davcal__edit .ui-dialog-titlebar-close').click(function(){
29524          dw_davcal__modals.hideEditEventDialog();
29525        });
29526        jQuery('#dw_davcal__eventfrom_edit').datetimepicker({format:'YYYY-MM-DD',
29527                                                      formatDate:'YYYY-MM-DD',
29528                                                      datepicker: true,
29529                                                      timepicker: false,
29530                                                      lang: JSINFO.plugin.davcal['language'],
29531                                                      });
29532        jQuery('#dw_davcal__eventfromtime_edit').datetimepicker({format:'HH:mm',
29533                                                      formatTime:'HH:mm',
29534                                                      datepicker: false,
29535                                                      timepicker: true,
29536                                                      lang: JSINFO.plugin.davcal['language'],
29537                                                      step: 15});
29538        jQuery('#dw_davcal__eventto_edit').datetimepicker({format:'YYYY-MM-DD',
29539                                                      formatDate:'YYYY-MM-DD',
29540                                                      datepicker: true,
29541                                                      timepicker: false,
29542                                                      lang: JSINFO.plugin.davcal['language'],
29543                                                      });
29544        jQuery('#dw_davcal__eventtotime_edit').datetimepicker({format:'HH:mm',
29545                                                      formatTime:'HH:mm',
29546                                                      datepicker: false,
29547                                                      timepicker: true,
29548                                                      lang: JSINFO.plugin.davcal['language'],
29549                                                      step:15});
29550        jQuery('#dw_davcal__allday_edit').change(function() {
29551            if(jQuery(this).is(":checked"))
29552            {
29553                jQuery('#dw_davcal__eventfromtime_edit').prop('readonly', true);
29554                jQuery('#dw_davcal__eventtotime_edit').prop('readonly', true);
29555            }
29556            else
29557            {
29558                jQuery('#dw_davcal__eventfromtime_edit').prop('readonly', false);
29559                jQuery('#dw_davcal__eventtotime_edit').prop('readonly', false);
29560            }
29561        });
29562        jQuery('#dw_davcal__allday_edit').change();
29563    },
29564    
29565    /**
29566     * Attach handles to delete the attachments to all 'delete' links
29567     */
29568    attachAttachmentDeleteHandlers: function()
29569    {
29570       jQuery("#dw_davcal__editevent_attachments .deleteLink").on("click", function(e)
29571       {
29572            e.preventDefault();
29573            var tr = jQuery(this).closest('tr');
29574            tr.css("background-color", "#FF3700");
29575            tr.fadeOut(400, function()
29576            {
29577                tr.remove();
29578            });
29579            return false;
29580       });
29581    },
29582    
29583    /**
29584     * Show an info/confirmation dialog
29585     * @param {Object} confirm Whether a confirmation dialog (true) or an info dialog (false) is requested
29586     */
29587    showDialog : function(confirm)
29588    {
29589        if(dw_davcal__modals.$confirmDialog)
29590            return;
29591        var dialogButtons = {};
29592        var title = '';
29593        if(confirm)
29594        {
29595            title = LANG.plugins.davcal['confirmation'];
29596            var pageid = jQuery("#dw_davcal__editevent_calendar option:selected").val();
29597            dialogButtons[LANG.plugins.davcal['yes']] =  function() {
29598                            jQuery.post(
29599                                DOKU_BASE + 'lib/exe/ajax.php',
29600                                {
29601                                    call: 'plugin_davcal',
29602                                    id: pageid,
29603                                    page: dw_davcal__modals.page,
29604                                    action: dw_davcal__modals.action,
29605                                    params: {
29606                                        uid: dw_davcal__modals.uid
29607                                    },
29608                                    sectok: JSINFO.plugin.davcal['sectok']
29609                                },
29610                                function(data)
29611                                {
29612                                    dw_davcal__modals.completeCb(data);
29613                                }
29614                            );
29615                            dw_davcal__modals.hideDialog();
29616                    };
29617            dialogButtons[LANG.plugins.davcal['cancel']] = function() {
29618                            dw_davcal__modals.hideDialog();
29619                    };
29620        }
29621        else
29622        {
29623            title = LANG.plugins.davcal['info'];
29624            dialogButtons[LANG.plugins.davcal['ok']] = function() {
29625                 dw_davcal__modals.hideDialog();
29626            };
29627        }
29628        dw_davcal__modals.$dialog = jQuery(document.createElement('div'))
29629            .dialog({
29630                autoOpen: false,
29631                draggable: true,
29632                //fix for dragging: http://stackoverflow.com/questions/17247486/jquery-ui-dialog-dragging-issues
29633                drag: function(event, ui) {
29634                    var fixPix = jQuery(document).scrollTop();
29635                    iObj = ui.position;
29636                    iObj.top = iObj.top - fixPix;
29637                    jQuery(this).closest(".ui-dialog").css("top", iObj.top + "px");
29638                },
29639                title: title,
29640                resizable: true,
29641                buttons: dialogButtons,
29642            })
29643            .html(
29644                '<div>' + dw_davcal__modals.msg + '</div>'
29645            )
29646            .parent()
29647            .attr('id','dw_davcal__confirm')
29648            .show()
29649            .appendTo('.dokuwiki:first');
29650   
29651            jQuery('#dw_davcal__confirm').position({
29652                my: "center",
29653                at: "center",
29654                of: window
29655            });
29656                 // attach event handlers
29657            jQuery('#dw_davcal__confirm .ui-dialog-titlebar-close').click(function(){
29658                dw_davcal__modals.hideDialog();
29659            });
29660    },
29661    
29662    /**
29663     * Hide the edit event dialog
29664     */
29665    hideEditEventDialog : function() {
29666        dw_davcal__modals.$editEventDialog.empty();
29667        dw_davcal__modals.$editEventDialog.remove();
29668        dw_davcal__modals.$editEventDialog = null;
29669    },
29670    
29671    /**
29672     * Hide the confirm/info dialog
29673     */
29674    hideDialog: function() {
29675        dw_davcal__modals.$dialog.empty();
29676        dw_davcal__modals.$dialog.remove();
29677        dw_davcal__modals.$dialog = null;
29678    },
29679    
29680    /**
29681     * Hide the settings dialog
29682     */
29683    hideSettingsDialog: function() {
29684        dw_davcal__modals.$settingsDialog.empty();
29685        dw_davcal__modals.$settingsDialog.remove();
29686        dw_davcal__modals.$settingsDialog = null;
29687    }
29688};
29689
29690
29691
29692/* XXXXXXXXXX end of lib/plugins/davcal/script.js XXXXXXXXXX */
29693
29694
29695
29696/* XXXXXXXXXX begin of lib/plugins/extension/script.js XXXXXXXXXX */
29697
29698jQuery(function(){
29699
29700    var $extmgr = jQuery('#extension__manager');
29701
29702    /**
29703     * Confirm uninstalling
29704     */
29705    $extmgr.find('button.uninstall').on('click', function(e){
29706        if(!window.confirm(LANG.plugins.extension.reallydel)){
29707            e.preventDefault();
29708            return false;
29709        }
29710        return true;
29711    });
29712
29713    /**
29714     * very simple lightbox
29715     * @link http://webdesign.tutsplus.com/tutorials/htmlcss-tutorials/super-simple-lightbox-with-css-and-jquery/
29716     */
29717    $extmgr.find('a.extension_screenshot').on('click', function(e) {
29718        e.preventDefault();
29719
29720        //Get clicked link href
29721        var image_href = jQuery(this).attr("href");
29722
29723        // create lightbox if needed
29724        var $lightbox = jQuery('#plugin__extensionlightbox');
29725        if(!$lightbox.length){
29726            $lightbox = jQuery('<div id="plugin__extensionlightbox"><p>Click to close</p><div></div></div>')
29727                .appendTo(jQuery('body'))
29728                .hide()
29729                .on('click', function(){
29730                    $lightbox.hide();
29731                });
29732        }
29733
29734        // fill and show it
29735        $lightbox
29736            .show()
29737            .find('div').html('<img src="' + image_href + '" />');
29738
29739
29740        return false;
29741    });
29742
29743    /**
29744     * Enable/Disable extension via AJAX
29745     */
29746    $extmgr.find('button.disable, button.enable').on('click', function (e) {
29747        e.preventDefault();
29748        var $btn = jQuery(this);
29749
29750        // get current state
29751        var extension = $btn.attr('name').split('[')[2];
29752        extension = extension.substr(0, extension.length - 1);
29753        var act = ($btn.hasClass('disable')) ? 'disable' : 'enable';
29754
29755        // disable while we wait
29756        $btn.attr('disabled', 'disabled');
29757        $btn.css('cursor', 'wait');
29758
29759        // execute
29760        jQuery.get(
29761            DOKU_BASE + 'lib/exe/ajax.php',
29762            {
29763                call: 'plugin_extension',
29764                ext: extension,
29765                act: act,
29766                sectok: $btn.parents('form').find('input[name=sectok]').val()
29767            },
29768            function (data) {
29769                $btn.css('cursor', '')
29770                    .removeAttr('disabled')
29771                    .removeClass('disable')
29772                    .removeClass('enable')
29773                    .text(data.label)
29774                    .addClass(data.reverse)
29775                    .parents('li')
29776                    .removeClass('disabled')
29777                    .removeClass('enabled')
29778                    .addClass(data.state);
29779            }
29780        ).fail(function() {
29781            $btn.css('cursor', '')
29782                .removeAttr('disabled');
29783        });
29784    });
29785
29786    /**
29787     * AJAX detail infos
29788     */
29789    $extmgr.find('a.info').on('click', function(e){
29790        e.preventDefault();
29791
29792        var $link = jQuery(this);
29793        var $details = $link.parent().find('dl.details');
29794        if($details.length){
29795            $link.toggleClass('close');
29796            $details.toggle();
29797            return;
29798        }
29799
29800        $link.addClass('close');
29801        jQuery.get(
29802            DOKU_BASE + 'lib/exe/ajax.php',
29803            {
29804                call: 'plugin_extension',
29805                ext: $link.data('extid'),
29806                act: 'info'
29807            },
29808            function(data){
29809                $link.parent().append(data);
29810            }
29811        );
29812    });
29813
29814    /**
29815        Create section for enabling/disabling viewing options
29816     */
29817    if ( $extmgr.find('.plugins, .templates').hasClass('active') ) {
29818        var $extlist = jQuery('#extension__list');
29819        $extlist.addClass('hasDisplayOptions');
29820
29821        var $displayOpts = jQuery('<p>', { id: 'extension__viewoptions'} ).appendTo($extmgr.find( '.panelHeader' ));
29822        $displayOpts.append(LANG.plugins.extension.display_viewoptions);
29823
29824        var displayOptionsHandler = function(){
29825            $extlist.toggleClass( this.name );
29826            DokuCookie.setValue('ext_'+this.name, $extlist.hasClass(this.name) ? '1' : '0');
29827        };
29828
29829        jQuery(['enabled', 'disabled', 'updatable']).each(function(index, chkName){
29830            var $label = jQuery( '<label></label>' )
29831                .appendTo($displayOpts);
29832            var $input = jQuery( '<input />', { type: 'checkbox', name: chkName })
29833                .on('change', displayOptionsHandler)
29834                .appendTo($label);
29835
29836            var previous = DokuCookie.getValue('ext_'+chkName);
29837            if(typeof previous === "undefined" || previous == '1') {
29838                $input.trigger('click');
29839            }
29840
29841            jQuery( '<span/>' )
29842                .append(' '+LANG.plugins.extension['display_'+chkName])
29843                .appendTo($label);
29844        });
29845    }
29846});
29847
29848
29849
29850/* XXXXXXXXXX end of lib/plugins/extension/script.js XXXXXXXXXX */
29851
29852
29853
29854/* XXXXXXXXXX begin of lib/plugins/foldedlist/script.js XXXXXXXXXX */
29855
29856/*
29857 * For Folded Plugin
29858 *
29859 * @author Fabian van-de-l_Isle <webmaster [at] lajzar [dot] co [dot] uk>
29860 * @author Christopher Smith <chris [at] jalakai [dot] co [dot] uk>
29861 */
29862
29863/*
29864 * toggle the folded element via className change
29865 * also adjust the classname and title tooltip on the folding link
29866 */
29867function foldedlist_toggle(evt) {
29868  id = this.href.match(/#(.*)$/)[1];
29869  //e = jQuery(id);
29870  e = document.getElementById(id);
29871  if (!e) return;
29872
29873  if (e.className.match(/\bhidden\b/)) {
29874    e.className = e.className.replace(/\bhidden\b/g,'');
29875    e.className = e.className.replace(/  /g,' ');
29876    this.parentNode.className = 'open';
29877  } else {
29878    e.className += ' hidden';
29879    this.parentNode.className = 'closed';
29880  };
29881
29882  evt.preventDefault();
29883  return false;
29884}
29885
29886/*
29887 * run on document load, setup everything we need
29888 */
29889function foldedlist_setup() {
29890    // find all folder links, assign onclick handler and title tooltip for initial state
29891  //var folds = getElementsByClass('folder');
29892  var folds = jQuery('.folder')
29893
29894  for (var i=0; i<folds.length; i++) {    
29895    var t=folds[i];
29896    //addEvent(t, 'click', foldedlist_toggle);
29897    jQuery(t).click(foldedlist_toggle);
29898  }
29899}
29900
29901//addInitEvent(foldedlist_setup);
29902jQuery(foldedlist_setup);
29903
29904// support graceful js degradation, this hides the folded blocks from view before they are shown, 
29905// whilst still allowing non-js user to see any folded content.
29906document.write('<style type="text/css" media="screen"><!--/*--><![CDATA[/*><!--*/ .list.hidden { display: none; } .list { visibility: visible; } /*]]>*/--></style>');
29907
29908
29909
29910/* XXXXXXXXXX end of lib/plugins/foldedlist/script.js XXXXXXXXXX */
29911
29912
29913
29914/* XXXXXXXXXX begin of lib/plugins/goto/script.js XXXXXXXXXX */
29915
29916/*
29917 *@author    Myron Turner <[email protected]> 
29918*/
29919function goto_redirect(which,mode) { 
29920
29921     if(mode == 'extern') {
29922         location.href = which;
29923         return;
29924     }
29925	 var user = goto_getCookie("GOTO_LOGIN");      
29926      if(!user) {
29927          return;
29928      }   	 
29929      clearTimeout(goto_tm);
29930      if(mode == 'user')  {        
29931       which = which.replace(/user/, user);
29932      }
29933      location.href = which;
29934
29935      clearTimeout(goto_tm);
29936      setGotoCookie("GOTO_LOGIN", "") ;
29937}
29938function goto_getCookie(name) {
29939    var re = new RegExp(name + "=([^;]+)");
29940    var value = re.exec(document.cookie);
29941    return (value != null) ?decodeURIComponent(value[1]) : null;
29942}
29943
29944function setGotoCookie(cname, cvalue) {
29945    var d = new Date();  
29946    d.setTime(d.getTime() - (60*60*1000)); //60 minutes 
29947    var expires = "expires="+ d.toUTCString();
29948    document.cookie = cname + "=" + cvalue + ";" + expires + ";path="+DOKU_BASE;    
29949}
29950
29951jQuery( document ).ready(function() {
29952     if(JSINFO['update_version'] > 50) {
29953      var domval = window.document.getElementById("goto_go");
29954      if (domval && "innerHTML" in domval) {
29955        var ar = domval.innerHTML.split(';');
29956        if(ar) {
29957          var url = ar[0]; var delay = ar[1];
29958          setTimeout(function(){ location.href = url; }, delay,url);
29959          return;
29960        }
29961      }
29962      }
29963	  var which = goto_getCookie("GOTO_LOGIN");      
29964  
29965      if(!which) {
29966          return;
29967      }   
29968	   location.href = DOKU_BASE + 'doku.php?id=' + decodeURIComponent(which) ;
29969	   setGotoCookie("GOTO_LOGIN", "") ;
29970});
29971
29972
29973
29974/* XXXXXXXXXX end of lib/plugins/goto/script.js XXXXXXXXXX */
29975
29976
29977
29978/* XXXXXXXXXX begin of lib/plugins/highlight/script.js XXXXXXXXXX */
29979
29980/* JavaScript function to create highlight toolbar in DokuwKki */
29981/* see http://www.dokuwiki.org/plugin:highlight for more info */
29982
29983hl_icobase = "../../plugins/highlight/images/";
29984
29985if(window.toolbar != undefined) {
29986  toolbar[toolbar.length] = {
29987    "type":"picker",
29988    "title":"Highlight Text",
29989    "icon":hl_icobase+"toolbar_icon.png",
29990    "list":[{
29991      "type":"format",
29992      "title":"Gray Highlighted Text",
29993      "icon":hl_icobase+"picker_light_gray.png",
29994      "open":"<hi #c3c3c3>",
29995      "close":"</hi>"
29996    }, {
29997      "type":"format",
29998      "title":"Rose Highlighted Text",
29999      "icon":hl_icobase+"picker_rose.png",
30000      "open":"<hi #ffaec9>",
30001      "close":"</hi>"
30002    }, {
30003      "type":"format",
30004      "title":"Red Highlighted Text",
30005      "icon":hl_icobase+"picker_red.png",
30006      "open":"<hi #ed1c24>",
30007      "close":"</hi>"
30008    }, {
30009      "type":"format",
30010      "title":"Orange Highlighted Text",
30011      "icon":hl_icobase+"picker_orange.png",
30012      "open":"<hi #ff7f27>",
30013      "close":"</hi>"
30014    }, {
30015      "type":"format",
30016      "title":"Gold Highlighted Text",
30017      "icon":hl_icobase+"picker_gold.png",
30018      "open":"<hi #ffc90e>",
30019      "close":"</hi>"
30020    }, {
30021      "type":"format",
30022      "title":"Yellow Highlighted Text",
30023      "icon":hl_icobase+"picker_yellow.png",
30024      "open":"<hi #fff200>",
30025      "close":"</hi>"
30026    }, {
30027      "type":"format",
30028      "title":"Light Yellow Highlighted Text",
30029      "icon":hl_icobase+"picker_light_yellow.png",
30030      "open":"<hi #efe4B0>",
30031      "close":"</hi>"
30032    }, {
30033      "type":"format",
30034      "title":"Green Highlighted Text",
30035      "icon":hl_icobase+"picker_green.png",
30036      "open":"<hi #22b14c>",
30037      "close":"</hi>"
30038    }, {
30039      "type":"format",
30040      "title":"Lime Highlighted Text",
30041      "icon":hl_icobase+"picker_lime.png",
30042      "open":"<hi #b5e61d>",
30043      "close":"</hi>"
30044    }, {
30045      "type":"format",
30046      "title":"Turquoise Highlighted Text",
30047      "icon":hl_icobase+"picker_turquoise.png",
30048      "open":"<hi #00a2e8>",
30049      "close":"</hi>"
30050    }, {
30051      "type":"format",
30052      "title":"Light Turquoise Highlighted Text",
30053      "icon":hl_icobase+"picker_light_turquoise.png",
30054      "open":"<hi #99d9ea>",
30055      "close":"</hi>"
30056    }, {
30057    //  "type":"format",
30058    //  "title":"Indigo Highlighted Text",
30059    //  "icon":hl_icobase+"picker_indigo.png",
30060    //  "open":"<hi #3f48cc>",
30061    //  "close":"</hi>"
30062    //}, {
30063      "type":"format",
30064      "title":"Blue-Gray Highlighted Text",
30065      "icon":hl_icobase+"picker_blue_gray.png",
30066      "open":"<hi #7092be>",
30067      "close":"</hi>"
30068    }, {
30069      "type":"format",
30070      "title":"Lavender Highlighted Text",
30071      "icon":hl_icobase+"picker_lavender.png",
30072      "open":"<hi #c8bfe7>",
30073      "close":"</hi>"
30074    }]
30075  }; 
30076}
30077
30078//Setup VIM: ex: et ts=2 sw=2 enc=utf-8 :
30079
30080
30081
30082/* XXXXXXXXXX end of lib/plugins/highlight/script.js XXXXXXXXXX */
30083
30084
30085
30086/* XXXXXXXXXX begin of lib/plugins/logviewer/script.js XXXXXXXXXX */
30087
30088/**
30089 * Scroll to the end of the log on load
30090 */
30091jQuery(function () {
30092    var $dl = jQuery('#plugin__logviewer').find('dl');
30093    if (!$dl.length) return;
30094    $dl.animate({scrollTop: $dl.prop("scrollHeight")}, 500);
30095
30096
30097    var $filter = jQuery('<input>');
30098    $filter.on('keyup', function (e) {
30099        var re = new RegExp($filter.val(), 'i');
30100
30101        $dl.find('dt').each(function (idx, elem) {
30102            if (elem.innerText.match(re)) {
30103                jQuery(elem).removeClass('hidden');
30104            } else {
30105                jQuery(elem).addClass('hidden');
30106            }
30107        });
30108    });
30109    $dl.before($filter);
30110    $filter.wrap('<label></label>');
30111    $filter.before(LANG.plugins.logviewer.filter + ' ');
30112});
30113
30114
30115
30116/* XXXXXXXXXX end of lib/plugins/logviewer/script.js XXXXXXXXXX */
30117
30118
30119
30120/* XXXXXXXXXX begin of lib/plugins/overlay/script.js XXXXXXXXXX */
30121
30122if(JSINFO && !JSINFO['overlay']) {  
30123    jQuery( document ).ready(function() {   
30124      jQuery('#overlay').toggle();     
30125      jQuery('#widget').draggable();
30126   });   
30127}
30128 var theUserposition= {'x':0,'y':0,'position':'absolute'};  
30129jQuery( document ).ready(function() {   
30130    jQuery( "#overlay" ).draggable({
30131        drag: function(event,ui){
30132        var position = jQuery(this).position();
30133        theUserposition.y = position.top;
30134         theUserposition.x =position.left;
30135        }, 
30136        stop: function(){
30137        var position = jQuery(this).position();
30138        theUserposition.y = position.top;
30139         theUserposition.x =position.left;
30140         jQuery(this).css('left',position.left);
30141         jQuery(this).css('top',position.top);
30142        },
30143    });
30144    
30145    if (jQuery.fn.resizable) {
30146        jQuery( "#overlay" ).draggable().resizable({
30147            helper: "ui-resizable-helper",	
30148            handles: {
30149                    'nw': '#nwgrip',
30150                    'ne': '#negrip',
30151                    'sw': '#swgrip',
30152                    'se': '#segrip',
30153                    'n': '#ngrip',
30154                    'e': '#egrip', 
30155                    'w': '#wgrip'
30156                }        
30157          }
30158       ); 
30159    }
30160  
30161OverlaySetSize();
30162
30163 jQuery( "a.ovl_fix_toggle" ).on('click', function() {
30164    var which = jQuery("#overlay").css('position');    
30165    var button_text, title_text;
30166     
30167    if(which == 'fixed') {
30168        which = "absolute";  
30169        button_text = LANG.plugins.overlay.absolute;
30170        title_text = LANG.plugins.overlay.unfix_title;
30171      }
30172    else if(which == "absolute") {
30173        which = 'fixed';
30174        button_text = LANG.plugins.overlay.fixed;
30175        theUserposition.x = 0;
30176        theUserposition.y = 0;
30177        title_text = LANG.plugins.overlay.fix_title;
30178        jQuery("#overlay" ).css({top:  theUserposition.y, left:  theUserposition.x, position:which}); 
30179    }  
30180    else {
30181        button_text =  jQuery(this).html();
30182        title_text = jQuery(this).attr('title');
30183    }   
30184       var y = jQuery("#overlay").css('top');    
30185       var x = jQuery("#overlay").css('left');   
30186       jQuery(this).html(button_text);
30187       jQuery(this).attr('title', title_text);   
30188       var pos = x.toString() + '#' + y.toString() + '#' + which;       
30189       theUserposition.x = x;
30190       theUserposition.y = y;
30191       setOverlayCookie('OverlayUserposition', pos) ;
30192       jQuery("#overlay").css('position',which);    
30193       
30194 });
30195 
30196 jQuery(window).on('beforeunload', function(){ 
30197   var which = jQuery("#overlay").css('position');    
30198   var y = jQuery("#overlay").css('top');    
30199   var x = jQuery("#overlay").css('left');    
30200   var width = parseInt(jQuery("#overlay").css('width'));
30201   if(width < 200) width = 200;
30202   var height = parseInt(jQuery("#overlay").css('height'));   
30203   if(height < 200) height = 200;   
30204    var pos = x.toString() + '#' + y.toString() + '#' + which;
30205    setOverlayCookie('OverlayUserposition', pos) ;
30206    
30207    var dim = height.toString() + '#' + width.toString();    
30208    setOverlayCookie('OverlayUserDim',dim) ;
30209      
30210});
30211});
30212
30213jQuery(window).on("load", function(){                    
30214            var pos  = overlay_getCookie('OverlayUserposition') ;
30215            var  pos_ar, ptop=0, pleft=0;
30216            var ptype;       
30217        
30218            if(pos) {
30219                pos_ar = pos.split('#');
30220                pleft = parseInt(pos_ar[0]);
30221                ptop = parseInt(pos_ar[1]);                
30222                ptype=pos_ar[2];
30223            }
30224            else if(JSINFO['ol_left']) {                 
30225                pleft = JSINFO['ol_left'];
30226                ptop = JSINFO['ol_top'] ;               
30227                ptype=JSINFO['position'] ;
30228            }
30229            else ptype='absolute';
30230            
30231           if(ptype == 'fixed') {        
30232                button_text = LANG.plugins.overlay.fixed;
30233              }
30234            else if(ptype == "absolute")
30235            {        
30236                button_text = LANG.plugins.overlay.absolute;
30237              }  
30238           else  {              
30239               button_text = LANG.plugins.overlay.fixed;
30240               ptop = 0;
30241               pleft = 0;
30242               ptype = 'fixed';   
30243            }
30244  
30245           jQuery( "a.ovl_fix_toggle" ).html(button_text);      
30246            jQuery("#overlay" ).css({top: ptop, left: pleft, position:ptype});     
30247           
30248           OverlaySetSize();
30249});
30250
30251function OverlaySetSize() {
30252     var dim = overlay_getCookie('OverlayUserDim') ;
30253    if(JSINFO  && ! dim) {
30254       if(JSINFO['ol_width']) {
30255           jQuery( "#overlay" ).css('width',JSINFO['ol_width']); 
30256       }    
30257       if(JSINFO['ol_height']) {
30258           jQuery( "#overlay" ).css('height',JSINFO['ol_height']);            
30259        }
30260   }
30261   else if(dim) {
30262        var dim_ar = dim.split('#');
30263        var h = parseInt(dim_ar[0]);
30264        var w = parseInt(dim_ar[1]);
30265        if(w < 200) w = 200;
30266        jQuery("#overlay" ).css({'width': w, 'height': h});      
30267   }
30268
30269}
30270
30271function setOverlayCookie(cname, cvalue) {
30272    var d = new Date();  
30273    d.setTime(d.getTime() + (60*60*1000)); //60 minutes
30274    var expires = "expires="+ d.toUTCString();
30275    document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";    
30276}
30277
30278 function overlay_getCookie(cname) {
30279    var name = cname + "=";
30280    var ca = document.cookie.split(';');
30281    for(var i = 0; i <ca.length; i++) {
30282        var c = ca[i];
30283        while (c.charAt(0)==' ') {
30284            c = c.substring(1);
30285        }
30286        if (c.indexOf(name) == 0) {
30287            return c.substring(name.length,c.length);
30288        }
30289    }
30290    return "";
30291 }
30292 
30293
30294
30295
30296/* XXXXXXXXXX end of lib/plugins/overlay/script.js XXXXXXXXXX */
30297
30298
30299
30300/* XXXXXXXXXX begin of lib/plugins/sidebox/script.js XXXXXXXXXX */
30301
30302/*
30303 * For Folded Plugin
30304 *
30305 * @author Fabian van-de-l_Isle <webmaster [at] lajzar [dot] co [dot] uk>
30306 * @author Christopher Smith <chris [at] jalakai [dot] co [dot] uk>
30307 */
30308
30309function DW_getCurid() {
30310  var pageid;
30311  var metas = document.getElementsByTagName('meta');
30312  for (var i=0; i<metas.length; i++) {    
30313    var meta = metas[i];
30314    if (meta.name.match(/keywords/)) { 
30315	pageid = meta.content.replace(/,/g,':');
30316	break; 
30317    };
30318  };
30319  return pageid;
30320}
30321
30322function sidebox_toggle(evt) {                                                                                                                                      
30323  id = this.href.match(/#(.*)$/)[1];                                                                                                                                   
30324  //e = jQuery(id);                                                                                                                                                           
30325  e = document.getElementById(id);                                                                                                                                                           
30326  if (!e) return;                                                                                                                                                      
30327                                                                                                                                                                       
30328  if (e.className.match(/\bhidden\b/)) {                                                                                                                               
30329    e.className = e.className.replace(/\bhidden\b/g,'');                                                                                                               
30330    e.className = e.className.replace(/  /g,' ');                                                                                                                      
30331    e.previousSibling.className = e.previousSibling.className.replace(/\bhidden\b/g,'');                                                                                                               
30332    e.previousSibling.className = e.previousSibling.className.replace(/  /g,' ');                                                                                                                      
30333//    this.parentNode.className = 'open';                                                                                                                                
30334  } else {                                                                                                                                                             
30335    e.className += ' hidden';                                                                                                                                          
30336    e.previousSibling.className += ' hidden';                                                                                                                                          
30337//    this.parentNode.className = 'closed';                                                                                                                              
30338  };                                                                                                                                                                   
30339                                                                                                                                                                       
30340  evt.preventDefault();                                                                                                                                                
30341  return false;                                                                                                                                                        
30342}
30343
30344function sidebox_setup() {
30345  //var titles = getElementsByClass('sidebox_title'); 
30346  var titles = jQuery('.sidebox_title'); 
30347  for (var i=0; i<titles.length; i++) {    
30348    var title = titles[i];
30349    //addEvent(title, 'click', sidebox_toggle);
30350    jQuery(title).click(sidebox_toggle);
30351  };
30352}
30353
30354/*
30355 * run on document load, setup everything we need
30356 */
30357function navigation_sidebox_setup() {    
30358  //var lis = getElementsByClass('wikilink1'); 
30359  var lis = jQuery('.wikilink1'); 
30360  for (var i=0; i<lis.length; i++) {    
30361    var a = lis[i];
30362    var li = a.parentNode;
30363    var ul = li.parentNode;
30364    var pageid = DW_getCurid();
30365    
30366    tt = eval("/^" + pageid + "$/");
30367    if (a.title.match(tt)) {
30368/*
30369	if (li.className.match(/^closed/)) {
30370	    // we encountered a link as a foldername
30371	    li.className = li.className.replace(/^closed/,'open');
30372//	    ul = li.nextSibling;
30373	};    
30374*/    
30375        // check if the curid link is in a foldedlist
30376	if (ul.className.match(/\blist\b/)) { 
30377	    // highlight the link to the current page...
30378	    li.className += ' current';
30379
30380    	    // for each parent open the list to expose the link to the current page
30381	    while (ul.className.match(/\blist\b/)) {
30382    		ul.className = ul.className.replace(/\bhidden\b/g,'');
30383    	        ul.className = ul.className.replace(/  /g,' ');
30384		ul.className += ' open';
30385		li = ul.parentNode;
30386		li.className.replace(/^closed/,'open');
30387    		ul = li.parentNode;
30388	    };
30389	};
30390    };
30391  };
30392};
30393
30394//addInitEvent(navigation_sidebox_setup);
30395//addInitEvent(sidebox_setup);
30396
30397jQuery(navigation_sidebox_setup);
30398jQuery(sidebox_setup);
30399
30400
30401
30402/* XXXXXXXXXX end of lib/plugins/sidebox/script.js XXXXXXXXXX */
30403
30404
30405
30406/* XXXXXXXXXX begin of lib/plugins/styling/script.js XXXXXXXXXX */
30407
30408jQuery(function () {
30409
30410    /**
30411     * Function to reload the preview styles in the main window
30412     *
30413     * @param {Window} target the main window
30414     */
30415    function applyPreview(target) {
30416        // remove style
30417        var $style = target.jQuery('link[rel=stylesheet][href*="lib/exe/css.php"]');
30418        $style.attr('href', '');
30419
30420        // append the loader screen
30421        var $loader = target.jQuery('#plugin__styling_loader');
30422        if (!$loader.length) {
30423            $loader = target.jQuery('<div id="plugin__styling_loader">' + LANG.plugins.styling.loader + '</div>');
30424            $loader.css({
30425                'position':         'absolute',
30426                'width':            '100%',
30427                'height':           '100%',
30428                'top':              0,
30429                'left':             0,
30430                'z-index':          5000,
30431                'background-color': '#fff',
30432                'opacity':          '0.7',
30433                'color':            '#000',
30434                'font-size':        '2.5em',
30435                'text-align':       'center',
30436                'line-height':      1.5,
30437                'padding-top':      '2em'
30438            });
30439            target.jQuery('body').append($loader);
30440        }
30441
30442        // load preview in main window (timeout works around chrome updating CSS weirdness)
30443        setTimeout(function () {
30444            var now = new Date().getTime();
30445            $style.attr('href', DOKU_BASE + 'lib/exe/css.php?preview=1&tseed=' + now);
30446        }, 500);
30447    }
30448
30449    var doreload = 1;
30450    var $styling_plugin = jQuery('#plugin__styling');
30451
30452    // if we are not on the plugin page (either main or popup)
30453    if (!$styling_plugin.length) {
30454        // handle the preview cookie
30455        if(DokuCookie.getValue('styling_plugin') == 1) {
30456            applyPreview(window);
30457        }
30458        return; // nothing more to do here
30459    }
30460
30461    /* ---- from here on we're in the popup or admin page ---- */
30462
30463    // add button on main page
30464    if (!$styling_plugin.hasClass('ispopup')) {
30465        var $form = $styling_plugin.find('form.styling').first();
30466        var $btn = jQuery('<button>' + LANG.plugins.styling.popup + '</button>');
30467        $form.prepend($btn);
30468
30469        $btn.on('click', function (e) {
30470            var windowFeatures = "menubar=no,location=no,resizable=yes,scrollbars=yes,status=false,width=500,height=500";
30471            window.open(DOKU_BASE + 'lib/plugins/styling/popup.php', 'styling_popup', windowFeatures);
30472            e.preventDefault();
30473            e.stopPropagation();
30474        }).wrap('<p></p>');
30475        return; // we exit here if this is not the popup
30476    }
30477
30478    /* ---- from here on we're in the popup only ---- */
30479
30480    // reload the main page on close
30481    window.onunload = function(e) {
30482        if(doreload) {
30483            DokuCookie.setValue('styling_plugin', 0);
30484            if(window.opener) window.opener.document.location.reload();
30485        }
30486        return null;
30487    };
30488
30489    // don't reload on our own buttons
30490    jQuery(':button').click(function(e){
30491        doreload = false;
30492    });
30493
30494    // on first load apply preview
30495    if(window.opener) applyPreview(window.opener);
30496
30497    // enable the preview cookie
30498    DokuCookie.setValue('styling_plugin', 1);
30499});
30500
30501
30502
30503/* XXXXXXXXXX end of lib/plugins/styling/script.js XXXXXXXXXX */
30504
30505
30506
30507/* XXXXXXXXXX begin of lib/plugins/usermanager/script.js XXXXXXXXXX */
30508
30509/**
30510 * Add JavaScript confirmation to the User Delete button
30511 */
30512jQuery(function(){
30513    jQuery('#usrmgr__del').on('click', function(){
30514        return confirm(LANG.del_confirm);
30515    });
30516});
30517
30518
30519
30520/* XXXXXXXXXX end of lib/plugins/usermanager/script.js XXXXXXXXXX */
30521
30522jQuery(function(){ dw_locktimer.init(840,1); });
30523

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.