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, '&') 11093 .replace(/</g, '<') 11094 .replace(/>/g, '>') 11095 .replace(/'/g, ''') 11096 .replace(/"/g, '"') 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') + '"> </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') + '"> </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 || '') || ' ') + // 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> </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:"<Zurück",nextText:"Vor>",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:"<ÐÑед",nextText:"След>",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.