PageSourceSearch

https://dobrota.ru/metronic/default/assets/vendors/base/vendors.bundle.js

js dobrota.ru collected 2026-09-25 12:19:34 UTC 3,548,137 bytes, 92,685 lines download raw bytes

vendor: 4,678 bytes, lines 1-158
1/**!
2 * @fileOverview Kickass library to create and place poppers near their reference elements.
3 * @version 1.14.7
4 * @license
5 * Copyright (c) 2016 Federico Zivolo and contributors
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25(function (global, factory) {
26	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
27	typeof define === 'function' && define.amd ? define(factory) :
28	(global.Popper = factory());
29}(this, (function () { 'use strict';
30
31var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
32
33var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
34var timeoutDuration = 0;
35for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
36  if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
37    timeoutDuration = 1;
38    break;
39  }
40}
41
42function microtaskDebounce(fn) {
43  var called = false;
44  return function () {
45    if (called) {
46      return;
47    }
48    called = true;
49    window.Promise.resolve().then(function () {
50      called = false;
51      fn();
52    });
53  };
54}
55
56function taskDebounce(fn) {
57  var scheduled = false;
58  return function () {
59    if (!scheduled) {
60      scheduled = true;
61      setTimeout(function () {
62        scheduled = false;
63        fn();
64      }, timeoutDuration);
65    }
66  };
67}
68
69var supportsMicroTasks = isBrowser && window.Promise;
70
71/**
72* Create a debounced version of a method, that's asynchronously deferred
73* but called in the minimum time possible.
74*
75* @method
76* @memberof Popper.Utils
77* @argument {Function} fn
78* @returns {Function}
79*/
80var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;
81
82/**
83 * Check if the given variable is a function
84 * @method
85 * @memberof Popper.Utils
86 * @argument {Any} functionToCheck - variable to check
87 * @returns {Boolean} answer to: is a function?
88 */
89function isFunction(functionToCheck) {
90  var getType = {};
91  return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
92}
93
94/**
95 * Get CSS computed property of the given element
96 * @method
97 * @memberof Popper.Utils
98 * @argument {Eement} element
99 * @argument {String} property
100 */
101function getStyleComputedProperty(element, property) {
102  if (element.nodeType !== 1) {
103    return [];
104  }
105  // NOTE: 1 DOM access here
106  var window = element.ownerDocument.defaultView;
107  var css = window.getComputedStyle(element, null);
108  return property ? css[property] : css;
109}
110
111/**
112 * Returns the parentNode or the host of the element
113 * @method
114 * @memberof Popper.Utils
115 * @argument {Element} element
116 * @returns {Element} parent
117 */
118function getParentNode(element) {
119  if (element.nodeName === 'HTML') {
120    return element;
121  }
122  return element.parentNode || element.host;
123}
124
125/**
126 * Returns the scrolling parent of the given element
127 * @method
128 * @memberof Popper.Utils
129 * @argument {Element} element
130 * @returns {Element} scroll parent
131 */
132function getScrollParent(element) {
133  // Return body, `getScroll` will take care to get the correct `scrollTop` from it
134  if (!element) {
135    return document.body;
136  }
137
138  switch (element.nodeName) {
139    case 'HTML':
140    case 'BODY':
141      return element.ownerDocument.body;
142    case '#document':
143      return element.body;
144  }
145
146  // Firefox want us to check `-x` and `-y` variations as well
147
148  var _getStyleComputedProp = getStyleComputedProperty(element),
149      overflow = _getStyleComputedProp.overflow,
150      overflowX = _getStyleComputedProp.overflowX,
151      overflowY = _getStyleComputedProp.overflowY;
152
153  if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {
154    return element;
155  }
156
157  return getScrollParent(getParentNode(element));
158}
vendor: 5,677 bytes, lines 158-343
158
159
160var isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);
161var isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);
162
163/**
164 * Determines if the browser is Internet Explorer
165 * @method
166 * @memberof Popper.Utils
167 * @param {Number} version to check
168 * @returns {Boolean} isIE
169 */
170function isIE(version) {
171  if (version === 11) {
172    return isIE11;
173  }
174  if (version === 10) {
175    return isIE10;
176  }
177  return isIE11 || isIE10;
178}
179
180/**
181 * Returns the offset parent of the given element
182 * @method
183 * @memberof Popper.Utils
184 * @argument {Element} element
185 * @returns {Element} offset parent
186 */
187function getOffsetParent(element) {
188  if (!element) {
189    return document.documentElement;
190  }
191
192  var noOffsetParent = isIE(10) ? document.body : null;
193
194  // NOTE: 1 DOM access here
195  var offsetParent = element.offsetParent || null;
196  // Skip hidden elements which don't have an offsetParent
197  while (offsetParent === noOffsetParent && element.nextElementSibling) {
198    offsetParent = (element = element.nextElementSibling).offsetParent;
199  }
200
201  var nodeName = offsetParent && offsetParent.nodeName;
202
203  if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
204    return element ? element.ownerDocument.documentElement : document.documentElement;
205  }
206
207  // .offsetParent will return the closest TH, TD or TABLE in case
208  // no offsetParent is present, I hate this job...
209  if (['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {
210    return getOffsetParent(offsetParent);
211  }
212
213  return offsetParent;
214}
215
216function isOffsetContainer(element) {
217  var nodeName = element.nodeName;
218
219  if (nodeName === 'BODY') {
220    return false;
221  }
222  return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;
223}
224
225/**
226 * Finds the root node (document, shadowDOM root) of the given element
227 * @method
228 * @memberof Popper.Utils
229 * @argument {Element} node
230 * @returns {Element} root node
231 */
232function getRoot(node) {
233  if (node.parentNode !== null) {
234    return getRoot(node.parentNode);
235  }
236
237  return node;
238}
239
240/**
241 * Finds the offset parent common to the two provided nodes
242 * @method
243 * @memberof Popper.Utils
244 * @argument {Element} element1
245 * @argument {Element} element2
246 * @returns {Element} common offset parent
247 */
248function findCommonOffsetParent(element1, element2) {
249  // This check is needed to avoid errors in case one of the elements isn't defined for any reason
250  if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
251    return document.documentElement;
252  }
253
254  // Here we make sure to give as "start" the element that comes first in the DOM
255  var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;
256  var start = order ? element1 : element2;
257  var end = order ? element2 : element1;
258
259  // Get common ancestor container
260  var range = document.createRange();
261  range.setStart(start, 0);
262  range.setEnd(end, 0);
263  var commonAncestorContainer = range.commonAncestorContainer;
264
265  // Both nodes are inside #document
266
267  if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {
268    if (isOffsetContainer(commonAncestorContainer)) {
269      return commonAncestorContainer;
270    }
271
272    return getOffsetParent(commonAncestorContainer);
273  }
274
275  // one of the nodes is inside shadowDOM, find which one
276  var element1root = getRoot(element1);
277  if (element1root.host) {
278    return findCommonOffsetParent(element1root.host, element2);
279  } else {
280    return findCommonOffsetParent(element1, getRoot(element2).host);
281  }
282}
283
284/**
285 * Gets the scroll value of the given element in the given side (top and left)
286 * @method
287 * @memberof Popper.Utils
288 * @argument {Element} element
289 * @argument {String} side `top` or `left`
290 * @returns {number} amount of scrolled pixels
291 */
292function getScroll(element) {
293  var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';
294
295  var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
296  var nodeName = element.nodeName;
297
298  if (nodeName === 'BODY' || nodeName === 'HTML') {
299    var html = element.ownerDocument.documentElement;
300    var scrollingElement = element.ownerDocument.scrollingElement || html;
301    return scrollingElement[upperSide];
302  }
303
304  return element[upperSide];
305}
306
307/*
308 * Sum or subtract the element scroll values (left and top) from a given rect object
309 * @method
310 * @memberof Popper.Utils
311 * @param {Object} rect - Rect object you want to change
312 * @param {HTMLElement} element - The element from the function reads the scroll values
313 * @param {Boolean} subtract - set to true if you want to subtract the scroll values
314 * @return {Object} rect - The modifier rect object
315 */
316function includeScroll(rect, element) {
317  var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
318
319  var scrollTop = getScroll(element, 'top');
320  var scrollLeft = getScroll(element, 'left');
321  var modifier = subtract ? -1 : 1;
322  rect.top += scrollTop * modifier;
323  rect.bottom += scrollTop * modifier;
324  rect.left += scrollLeft * modifier;
325  rect.right += scrollLeft * modifier;
326  return rect;
327}
328
329/*
330 * Helper to detect borders of a given element
331 * @method
332 * @memberof Popper.Utils
333 * @param {CSSStyleDeclaration} styles
334 * Result of `getStyleComputedProperty` on the given element
335 * @param {String} axis - `x` or `y`
336 * @return {number} borders - The borders size of the given axis
337 */
338
339function getBordersSize(styles, axis) {
340  var sideA = axis === 'x' ? 'Left' : 'Top';
341  var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
342
343  return parseFloat(styles['border' + sideA + 'Width']
vendor: 42,752 bytes, lines 343-1612
343, 10) + parseFloat(styles['border' + sideB + 'Width'], 10);
344}
345
346function getSize(axis, body, html, computedStyle) {
347  return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? parseInt(html['offset' + axis]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')]) : 0);
348}
349
350function getWindowSizes(document) {
351  var body = document.body;
352  var html = document.documentElement;
353  var computedStyle = isIE(10) && getComputedStyle(html);
354
355  return {
356    height: getSize('Height', body, html, computedStyle),
357    width: getSize('Width', body, html, computedStyle)
358  };
359}
360
361var classCallCheck = function (instance, Constructor) {
362  if (!(instance instanceof Constructor)) {
363    throw new TypeError("Cannot call a class as a function");
364  }
365};
366
367var createClass = function () {
368  function defineProperties(target, props) {
369    for (var i = 0; i < props.length; i++) {
370      var descriptor = props[i];
371      descriptor.enumerable = descriptor.enumerable || false;
372      descriptor.configurable = true;
373      if ("value" in descriptor) descriptor.writable = true;
374      Object.defineProperty(target, descriptor.key, descriptor);
375    }
376  }
377
378  return function (Constructor, protoProps, staticProps) {
379    if (protoProps) defineProperties(Constructor.prototype, protoProps);
380    if (staticProps) defineProperties(Constructor, staticProps);
381    return Constructor;
382  };
383}();
384
385
386
387
388
389var defineProperty = function (obj, key, value) {
390  if (key in obj) {
391    Object.defineProperty(obj, key, {
392      value: value,
393      enumerable: true,
394      configurable: true,
395      writable: true
396    });
397  } else {
398    obj[key] = value;
399  }
400
401  return obj;
402};
403
404var _extends = Object.assign || function (target) {
405  for (var i = 1; i < arguments.length; i++) {
406    var source = arguments[i];
407
408    for (var key in source) {
409      if (Object.prototype.hasOwnProperty.call(source, key)) {
410        target[key] = source[key];
411      }
412    }
413  }
414
415  return target;
416};
417
418/**
419 * Given element offsets, generate an output similar to getBoundingClientRect
420 * @method
421 * @memberof Popper.Utils
422 * @argument {Object} offsets
423 * @returns {Object} ClientRect like output
424 */
425function getClientRect(offsets) {
426  return _extends({}, offsets, {
427    right: offsets.left + offsets.width,
428    bottom: offsets.top + offsets.height
429  });
430}
431
432/**
433 * Get bounding client rect of given element
434 * @method
435 * @memberof Popper.Utils
436 * @param {HTMLElement} element
437 * @return {Object} client rect
438 */
439function getBoundingClientRect(element) {
440  var rect = {};
441
442  // IE10 10 FIX: Please, don't ask, the element isn't
443  // considered in DOM in some circumstances...
444  // This isn't reproducible in IE10 compatibility mode of IE11
445  try {
446    if (isIE(10)) {
447      rect = element.getBoundingClientRect();
448      var scrollTop = getScroll(element, 'top');
449      var scrollLeft = getScroll(element, 'left');
450      rect.top += scrollTop;
451      rect.left += scrollLeft;
452      rect.bottom += scrollTop;
453      rect.right += scrollLeft;
454    } else {
455      rect = element.getBoundingClientRect();
456    }
457  } catch (e) {}
458
459  var result = {
460    left: rect.left,
461    top: rect.top,
462    width: rect.right - rect.left,
463    height: rect.bottom - rect.top
464  };
465
466  // subtract scrollbar size from sizes
467  var sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : {};
468  var width = sizes.width || element.clientWidth || result.right - result.left;
469  var height = sizes.height || element.clientHeight || result.bottom - result.top;
470
471  var horizScrollbar = element.offsetWidth - width;
472  var vertScrollbar = element.offsetHeight - height;
473
474  // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
475  // we make this check conditional for performance reasons
476  if (horizScrollbar || vertScrollbar) {
477    var styles = getStyleComputedProperty(element);
478    horizScrollbar -= getBordersSize(styles, 'x');
479    vertScrollbar -= getBordersSize(styles, 'y');
480
481    result.width -= horizScrollbar;
482    result.height -= vertScrollbar;
483  }
484
485  return getClientRect(result);
486}
487
488function getOffsetRectRelativeToArbitraryNode(children, parent) {
489  var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
490
491  var isIE10 = isIE(10);
492  var isHTML = parent.nodeName === 'HTML';
493  var childrenRect = getBoundingClientRect(children);
494  var parentRect = getBoundingClientRect(parent);
495  var scrollParent = getScrollParent(children);
496
497  var styles = getStyleComputedProperty(parent);
498  var borderTopWidth = parseFloat(styles.borderTopWidth, 10);
499  var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
500
501  // In cases where the parent is fixed, we must ignore negative scroll in offset calc
502  if (fixedPosition && isHTML) {
503    parentRect.top = Math.max(parentRect.top, 0);
504    parentRect.left = Math.max(parentRect.left, 0);
505  }
506  var offsets = getClientRect({
507    top: childrenRect.top - parentRect.top - borderTopWidth,
508    left: childrenRect.left - parentRect.left - borderLeftWidth,
509    width: childrenRect.width,
510    height: childrenRect.height
511  });
512  offsets.marginTop = 0;
513  offsets.marginLeft = 0;
514
515  // Subtract margins of documentElement in case it's being used as parent
516  // we do this only on HTML because it's the only element that behaves
517  // differently when margins are applied to it. The margins are included in
518  // the box of the documentElement, in the other cases not.
519  if (!isIE10 && isHTML) {
520    var marginTop = parseFloat(styles.marginTop, 10);
521    var marginLeft = parseFloat(styles.marginLeft, 10);
522
523    offsets.top -= borderTopWidth - marginTop;
524    offsets.bottom -= borderTopWidth - marginTop;
525    offsets.left -= borderLeftWidth - marginLeft;
526    offsets.right -= borderLeftWidth - marginLeft;
527
528    // Attach marginTop and marginLeft because in some circumstances we may need them
529    offsets.marginTop = marginTop;
530    offsets.marginLeft = marginLeft;
531  }
532
533  if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {
534    offsets = includeScroll(offsets, parent);
535  }
536
537  return offsets;
538}
539
540function getViewportOffsetRectRelativeToArtbitraryNode(element) {
541  var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
542
543  var html = element.ownerDocument.documentElement;
544  var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);
545  var width = Math.max(html.clientWidth, window.innerWidth || 0);
546  var height = Math.max(html.clientHeight, window.innerHeight || 0);
547
548  var scrollTop = !excludeScroll ? getScroll(html) : 0;
549  var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;
550
551  var offset = {
552    top: scrollTop - relativeOffset.top + relativeOffset.marginTop,
553    left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,
554    width: width,
555    height: height
556  };
557
558  return getClientRect(offset);
559}
560
561/**
562 * Check if the given element is fixed or is inside a fixed parent
563 * @method
564 * @memberof Popper.Utils
565 * @argument {Element} element
566 * @argument {Element} customContainer
567 * @returns {Boolean} answer to "isFixed?"
568 */
569function isFixed(element) {
570  var nodeName = element.nodeName;
571  if (nodeName === 'BODY' || nodeName === 'HTML') {
572    return false;
573  }
574  if (getStyleComputedProperty(element, 'position') === 'fixed') {
575    return true;
576  }
577  var parentNode = getParentNode(element);
578  if (!parentNode) {
579    return false;
580  }
581  return isFixed(parentNode);
582}
583
584/**
585 * Finds the first parent of an element that has a transformed property defined
586 * @method
587 * @memberof Popper.Utils
588 * @argument {Element} element
589 * @returns {Element} first transformed parent or documentElement
590 */
591
592function getFixedPositionOffsetParent(element) {
593  // This check is needed to avoid errors in case one of the elements isn't defined for any reason
594  if (!element || !element.parentElement || isIE()) {
595    return document.documentElement;
596  }
597  var el = element.parentElement;
598  while (el && getStyleComputedProperty(el, 'transform') === 'none') {
599    el = el.parentElement;
600  }
601  return el || document.documentElement;
602}
603
604/**
605 * Computed the boundaries limits and return them
606 * @method
607 * @memberof Popper.Utils
608 * @param {HTMLElement} popper
609 * @param {HTMLElement} reference
610 * @param {number} padding
611 * @param {HTMLElement} boundariesElement - Element used to define the boundaries
612 * @param {Boolean} fixedPosition - Is in fixed position mode
613 * @returns {Object} Coordinates of the boundaries
614 */
615function getBoundaries(popper, reference, padding, boundariesElement) {
616  var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
617
618  // NOTE: 1 DOM access here
619
620  var boundaries = { top: 0, left: 0 };
621  var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);
622
623  // Handle viewport case
624  if (boundariesElement === 'viewport') {
625    boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);
626  } else {
627    // Handle other cases based on DOM element used as boundaries
628    var boundariesNode = void 0;
629    if (boundariesElement === 'scrollParent') {
630      boundariesNode = getScrollParent(getParentNode(reference));
631      if (boundariesNode.nodeName === 'BODY') {
632        boundariesNode = popper.ownerDocument.documentElement;
633      }
634    } else if (boundariesElement === 'window') {
635      boundariesNode = popper.ownerDocument.documentElement;
636    } else {
637      boundariesNode = boundariesElement;
638    }
639
640    var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition);
641
642    // In case of HTML, we need a different computation
643    if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {
644      var _getWindowSizes = getWindowSizes(popper.ownerDocument),
645          height = _getWindowSizes.height,
646          width = _getWindowSizes.width;
647
648      boundaries.top += offsets.top - offsets.marginTop;
649      boundaries.bottom = height + offsets.top;
650      boundaries.left += offsets.left - offsets.marginLeft;
651      boundaries.right = width + offsets.left;
652    } else {
653      // for all the other DOM elements, this one is good
654      boundaries = offsets;
655    }
656  }
657
658  // Add paddings
659  padding = padding || 0;
660  var isPaddingNumber = typeof padding === 'number';
661  boundaries.left += isPaddingNumber ? padding : padding.left || 0;
662  boundaries.top += isPaddingNumber ? padding : padding.top || 0;
663  boundaries.right -= isPaddingNumber ? padding : padding.right || 0;
664  boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0;
665
666  return boundaries;
667}
668
669function getArea(_ref) {
670  var width = _ref.width,
671      height = _ref.height;
672
673  return width * height;
674}
675
676/**
677 * Utility used to transform the `auto` placement to the placement with more
678 * available space.
679 * @method
680 * @memberof Popper.Utils
681 * @argument {Object} data - The data object generated by update method
682 * @argument {Object} options - Modifiers configuration and options
683 * @returns {Object} The data object, properly modified
684 */
685function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {
686  var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
687
688  if (placement.indexOf('auto') === -1) {
689    return placement;
690  }
691
692  var boundaries = getBoundaries(popper, reference, padding, boundariesElement);
693
694  var rects = {
695    top: {
696      width: boundaries.width,
697      height: refRect.top - boundaries.top
698    },
699    right: {
700      width: boundaries.right - refRect.right,
701      height: boundaries.height
702    },
703    bottom: {
704      width: boundaries.width,
705      height: boundaries.bottom - refRect.bottom
706    },
707    left: {
708      width: refRect.left - boundaries.left,
709      height: boundaries.height
710    }
711  };
712
713  var sortedAreas = Object.keys(rects).map(function (key) {
714    return _extends({
715      key: key
716    }, rects[key], {
717      area: getArea(rects[key])
718    });
719  }).sort(function (a, b) {
720    return b.area - a.area;
721  });
722
723  var filteredAreas = sortedAreas.filter(function (_ref2) {
724    var width = _ref2.width,
725        height = _ref2.height;
726    return width >= popper.clientWidth && height >= popper.clientHeight;
727  });
728
729  var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;
730
731  var variation = placement.split('-')[1];
732
733  return computedPlacement + (variation ? '-' + variation : '');
734}
735
736/**
737 * Get offsets to the reference element
738 * @method
739 * @memberof Popper.Utils
740 * @param {Object} state
741 * @param {Element} popper - the popper element
742 * @param {Element} reference - the reference element (the popper will be relative to this)
743 * @param {Element} fixedPosition - is in fixed position mode
744 * @returns {Object} An object containing the offsets which will be applied to the popper
745 */
746function getReferenceOffsets(state, popper, reference) {
747  var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
748
749  var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);
750  return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);
751}
752
753/**
754 * Get the outer sizes of the given element (offset size + margins)
755 * @method
756 * @memberof Popper.Utils
757 * @argument {Element} element
758 * @returns {Object} object containing width and height properties
759 */
760function getOuterSizes(element) {
761  var window = element.ownerDocument.defaultView;
762  var styles = window.getComputedStyle(element);
763  var x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0);
764  var y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0);
765  var result = {
766    width: element.offsetWidth + y,
767    height: element.offsetHeight + x
768  };
769  return result;
770}
771
772/**
773 * Get the opposite placement of the given one
774 * @method
775 * @memberof Popper.Utils
776 * @argument {String} placement
777 * @returns {String} flipped placement
778 */
779function getOppositePlacement(placement) {
780  var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };
781  return placement.replace(/left|right|bottom|top/g, function (matched) {
782    return hash[matched];
783  });
784}
785
786/**
787 * Get offsets to the popper
788 * @method
789 * @memberof Popper.Utils
790 * @param {Object} position - CSS position the Popper will get applied
791 * @param {HTMLElement} popper - the popper element
792 * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)
793 * @param {String} placement - one of the valid placement options
794 * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper
795 */
796function getPopperOffsets(popper, referenceOffsets, placement) {
797  placement = placement.split('-')[0];
798
799  // Get popper node sizes
800  var popperRect = getOuterSizes(popper);
801
802  // Add position, width and height to our offsets object
803  var popperOffsets = {
804    width: popperRect.width,
805    height: popperRect.height
806  };
807
808  // depending by the popper placement we have to compute its offsets slightly differently
809  var isHoriz = ['right', 'left'].indexOf(placement) !== -1;
810  var mainSide = isHoriz ? 'top' : 'left';
811  var secondarySide = isHoriz ? 'left' : 'top';
812  var measurement = isHoriz ? 'height' : 'width';
813  var secondaryMeasurement = !isHoriz ? 'height' : 'width';
814
815  popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;
816  if (placement === secondarySide) {
817    popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];
818  } else {
819    popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];
820  }
821
822  return popperOffsets;
823}
824
825/**
826 * Mimics the `find` method of Array
827 * @method
828 * @memberof Popper.Utils
829 * @argument {Array} arr
830 * @argument prop
831 * @argument value
832 * @returns index or -1
833 */
834function find(arr, check) {
835  // use native find if supported
836  if (Array.prototype.find) {
837    return arr.find(check);
838  }
839
840  // use `filter` to obtain the same behavior of `find`
841  return arr.filter(check)[0];
842}
843
844/**
845 * Return the index of the matching object
846 * @method
847 * @memberof Popper.Utils
848 * @argument {Array} arr
849 * @argument prop
850 * @argument value
851 * @returns index or -1
852 */
853function findIndex(arr, prop, value) {
854  // use native findIndex if supported
855  if (Array.prototype.findIndex) {
856    return arr.findIndex(function (cur) {
857      return cur[prop] === value;
858    });
859  }
860
861  // use `find` + `indexOf` if `findIndex` isn't supported
862  var match = find(arr, function (obj) {
863    return obj[prop] === value;
864  });
865  return arr.indexOf(match);
866}
867
868/**
869 * Loop trough the list of modifiers and run them in order,
870 * each of them will then edit the data object.
871 * @method
872 * @memberof Popper.Utils
873 * @param {dataObject} data
874 * @param {Array} modifiers
875 * @param {String} ends - Optional modifier name used as stopper
876 * @returns {dataObject}
877 */
878function runModifiers(modifiers, data, ends) {
879  var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
880
881  modifiersToRun.forEach(function (modifier) {
882    if (modifier['function']) {
883      // eslint-disable-line dot-notation
884      console.warn('`modifier.function` is deprecated, use `modifier.fn`!');
885    }
886    var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation
887    if (modifier.enabled && isFunction(fn)) {
888      // Add properties to offsets to make them a complete clientRect object
889      // we do this before each modifier to make sure the previous one doesn't
890      // mess with these values
891      data.offsets.popper = getClientRect(data.offsets.popper);
892      data.offsets.reference = getClientRect(data.offsets.reference);
893
894      data = fn(data, modifier);
895    }
896  });
897
898  return data;
899}
900
901/**
902 * Updates the position of the popper, computing the new offsets and applying
903 * the new style.<br />
904 * Prefer `scheduleUpdate` over `update` because of performance reasons.
905 * @method
906 * @memberof Popper
907 */
908function update() {
909  // if popper is destroyed, don't perform any further update
910  if (this.state.isDestroyed) {
911    return;
912  }
913
914  var data = {
915    instance: this,
916    styles: {},
917    arrowStyles: {},
918    attributes: {},
919    flipped: false,
920    offsets: {}
921  };
922
923  // compute reference element offsets
924  data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed);
925
926  // compute auto placement, store placement inside the data object,
927  // modifiers will be able to edit `placement` if needed
928  // and refer to originalPlacement to know the original value
929  data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);
930
931  // store the computed placement inside `originalPlacement`
932  data.originalPlacement = data.placement;
933
934  data.positionFixed = this.options.positionFixed;
935
936  // compute the popper offsets
937  data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);
938
939  data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute';
940
941  // run the modifiers
942  data = runModifiers(this.modifiers, data);
943
944  // the first `update` will call `onCreate` callback
945  // the other ones will call `onUpdate` callback
946  if (!this.state.isCreated) {
947    this.state.isCreated = true;
948    this.options.onCreate(data);
949  } else {
950    this.options.onUpdate(data);
951  }
952}
953
954/**
955 * Helper used to know if the given modifier is enabled.
956 * @method
957 * @memberof Popper.Utils
958 * @returns {Boolean}
959 */
960function isModifierEnabled(modifiers, modifierName) {
961  return modifiers.some(function (_ref) {
962    var name = _ref.name,
963        enabled = _ref.enabled;
964    return enabled && name === modifierName;
965  });
966}
967
968/**
969 * Get the prefixed supported property name
970 * @method
971 * @memberof Popper.Utils
972 * @argument {String} property (camelCase)
973 * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)
974 */
975function getSupportedPropertyName(property) {
976  var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];
977  var upperProp = property.charAt(0).toUpperCase() + property.slice(1);
978
979  for (var i = 0; i < prefixes.length; i++) {
980    var prefix = prefixes[i];
981    var toCheck = prefix ? '' + prefix + upperProp : property;
982    if (typeof document.body.style[toCheck] !== 'undefined') {
983      return toCheck;
984    }
985  }
986  return null;
987}
988
989/**
990 * Destroys the popper.
991 * @method
992 * @memberof Popper
993 */
994function destroy() {
995  this.state.isDestroyed = true;
996
997  // touch DOM only if `applyStyle` modifier is enabled
998  if (isModifierEnabled(this.modifiers, 'applyStyle')) {
999    this.popper.removeAttribute('x-placement');
1000    this.popper.style.position = '';
1001    this.popper.style.top = '';
1002    this.popper.style.left = '';
1003    this.popper.style.right = '';
1004    this.popper.style.bottom = '';
1005    this.popper.style.willChange = '';
1006    this.popper.style[getSupportedPropertyName('transform')] = '';
1007  }
1008
1009  this.disableEventListeners();
1010
1011  // remove the popper if user explicity asked for the deletion on destroy
1012  // do not use `remove` because IE11 doesn't support it
1013  if (this.options.removeOnDestroy) {
1014    this.popper.parentNode.removeChild(this.popper);
1015  }
1016  return this;
1017}
1018
1019/**
1020 * Get the window associated with the element
1021 * @argument {Element} element
1022 * @returns {Window}
1023 */
1024function getWindow(element) {
1025  var ownerDocument = element.ownerDocument;
1026  return ownerDocument ? ownerDocument.defaultView : window;
1027}
1028
1029function attachToScrollParents(scrollParent, event, callback, scrollParents) {
1030  var isBody = scrollParent.nodeName === 'BODY';
1031  var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;
1032  target.addEventListener(event, callback, { passive: true });
1033
1034  if (!isBody) {
1035    attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);
1036  }
1037  scrollParents.push(target);
1038}
1039
1040/**
1041 * Setup needed event listeners used to update the popper position
1042 * @method
1043 * @memberof Popper.Utils
1044 * @private
1045 */
1046function setupEventListeners(reference, options, state, updateBound) {
1047  // Resize event listener on window
1048  state.updateBound = updateBound;
1049  getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });
1050
1051  // Scroll event listener on scroll parents
1052  var scrollElement = getScrollParent(reference);
1053  attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);
1054  state.scrollElement = scrollElement;
1055  state.eventsEnabled = true;
1056
1057  return state;
1058}
1059
1060/**
1061 * It will add resize/scroll events and start recalculating
1062 * position of the popper element when they are triggered.
1063 * @method
1064 * @memberof Popper
1065 */
1066function enableEventListeners() {
1067  if (!this.state.eventsEnabled) {
1068    this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);
1069  }
1070}
1071
1072/**
1073 * Remove event listeners used to update the popper position
1074 * @method
1075 * @memberof Popper.Utils
1076 * @private
1077 */
1078function removeEventListeners(reference, state) {
1079  // Remove resize event listener on window
1080  getWindow(reference).removeEventListener('resize', state.updateBound);
1081
1082  // Remove scroll event listener on scroll parents
1083  state.scrollParents.forEach(function (target) {
1084    target.removeEventListener('scroll', state.updateBound);
1085  });
1086
1087  // Reset state
1088  state.updateBound = null;
1089  state.scrollParents = [];
1090  state.scrollElement = null;
1091  state.eventsEnabled = false;
1092  return state;
1093}
1094
1095/**
1096 * It will remove resize/scroll events and won't recalculate popper position
1097 * when they are triggered. It also won't trigger `onUpdate` callback anymore,
1098 * unless you call `update` method manually.
1099 * @method
1100 * @memberof Popper
1101 */
1102function disableEventListeners() {
1103  if (this.state.eventsEnabled) {
1104    cancelAnimationFrame(this.scheduleUpdate);
1105    this.state = removeEventListeners(this.reference, this.state);
1106  }
1107}
1108
1109/**
1110 * Tells if a given input is a number
1111 * @method
1112 * @memberof Popper.Utils
1113 * @param {*} input to check
1114 * @return {Boolean}
1115 */
1116function isNumeric(n) {
1117  return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
1118}
1119
1120/**
1121 * Set the style to the given popper
1122 * @method
1123 * @memberof Popper.Utils
1124 * @argument {Element} element - Element to apply the style to
1125 * @argument {Object} styles
1126 * Object with a list of properties and values which will be applied to the element
1127 */
1128function setStyles(element, styles) {
1129  Object.keys(styles).forEach(function (prop) {
1130    var unit = '';
1131    // add unit if the value is numeric and is one of the following
1132    if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
1133      unit = 'px';
1134    }
1135    element.style[prop] = styles[prop] + unit;
1136  });
1137}
1138
1139/**
1140 * Set the attributes to the given popper
1141 * @method
1142 * @memberof Popper.Utils
1143 * @argument {Element} element - Element to apply the attributes to
1144 * @argument {Object} styles
1145 * Object with a list of properties and values which will be applied to the element
1146 */
1147function setAttributes(element, attributes) {
1148  Object.keys(attributes).forEach(function (prop) {
1149    var value = attributes[prop];
1150    if (value !== false) {
1151      element.setAttribute(prop, attributes[prop]);
1152    } else {
1153      element.removeAttribute(prop);
1154    }
1155  });
1156}
1157
1158/**
1159 * @function
1160 * @memberof Modifiers
1161 * @argument {Object} data - The data object generated by `update` method
1162 * @argument {Object} data.styles - List of style properties - values to apply to popper element
1163 * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element
1164 * @argument {Object} options - Modifiers configuration and options
1165 * @returns {Object} The same data object
1166 */
1167function applyStyle(data) {
1168  // any property present in `data.styles` will be applied to the popper,
1169  // in this way we can make the 3rd party modifiers add custom styles to it
1170  // Be aware, modifiers could override the properties defined in the previous
1171  // lines of this modifier!
1172  setStyles(data.instance.popper, data.styles);
1173
1174  // any property present in `data.attributes` will be applied to the popper,
1175  // they will be set as HTML attributes of the element
1176  setAttributes(data.instance.popper, data.attributes);
1177
1178  // if arrowElement is defined and arrowStyles has some properties
1179  if (data.arrowElement && Object.keys(data.arrowStyles).length) {
1180    setStyles(data.arrowElement, data.arrowStyles);
1181  }
1182
1183  return data;
1184}
1185
1186/**
1187 * Set the x-placement attribute before everything else because it could be used
1188 * to add margins to the popper margins needs to be calculated to get the
1189 * correct popper offsets.
1190 * @method
1191 * @memberof Popper.modifiers
1192 * @param {HTMLElement} reference - The reference element used to position the popper
1193 * @param {HTMLElement} popper - The HTML element used as popper
1194 * @param {Object} options - Popper.js options
1195 */
1196function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {
1197  // compute reference element offsets
1198  var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed);
1199
1200  // compute auto placement, store placement inside the data object,
1201  // modifiers will be able to edit `placement` if needed
1202  // and refer to originalPlacement to know the original value
1203  var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);
1204
1205  popper.setAttribute('x-placement', placement);
1206
1207  // Apply `position` to popper before anything else because
1208  // without the position applied we can't guarantee correct computations
1209  setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' });
1210
1211  return options;
1212}
1213
1214/**
1215 * @function
1216 * @memberof Popper.Utils
1217 * @argument {Object} data - The data object generated by `update` method
1218 * @argument {Boolean} shouldRound - If the offsets should be rounded at all
1219 * @returns {Object} The popper's position offsets rounded
1220 *
1221 * The tale of pixel-perfect positioning. It's still not 100% perfect, but as
1222 * good as it can be within reason.
1223 * Discussion here: https://github.com/FezVrasta/popper.js/pull/715
1224 *
1225 * Low DPI screens cause a popper to be blurry if not using full pixels (Safari
1226 * as well on High DPI screens).
1227 *
1228 * Firefox prefers no rounding for positioning and does not have blurriness on
1229 * high DPI screens.
1230 *
1231 * Only horizontal placement and left/right values need to be considered.
1232 */
1233function getRoundedOffsets(data, shouldRound) {
1234  var _data$offsets = data.offsets,
1235      popper = _data$offsets.popper,
1236      reference = _data$offsets.reference;
1237  var round = Math.round,
1238      floor = Math.floor;
1239
1240  var noRound = function noRound(v) {
1241    return v;
1242  };
1243
1244  var referenceWidth = round(reference.width);
1245  var popperWidth = round(popper.width);
1246
1247  var isVertical = ['left', 'right'].indexOf(data.placement) !== -1;
1248  var isVariation = data.placement.indexOf('-') !== -1;
1249  var sameWidthParity = referenceWidth % 2 === popperWidth % 2;
1250  var bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1;
1251
1252  var horizontalToInteger = !shouldRound ? noRound : isVertical || isVariation || sameWidthParity ? round : floor;
1253  var verticalToInteger = !shouldRound ? noRound : round;
1254
1255  return {
1256    left: horizontalToInteger(bothOddWidth && !isVariation && shouldRound ? popper.left - 1 : popper.left),
1257    top: verticalToInteger(popper.top),
1258    bottom: verticalToInteger(popper.bottom),
1259    right: horizontalToInteger(popper.right)
1260  };
1261}
1262
1263var isFirefox = isBrowser && /Firefox/i.test(navigator.userAgent);
1264
1265/**
1266 * @function
1267 * @memberof Modifiers
1268 * @argument {Object} data - The data object generated by `update` method
1269 * @argument {Object} options - Modifiers configuration and options
1270 * @returns {Object} The data object, properly modified
1271 */
1272function computeStyle(data, options) {
1273  var x = options.x,
1274      y = options.y;
1275  var popper = data.offsets.popper;
1276
1277  // Remove this legacy support in Popper.js v2
1278
1279  var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {
1280    return modifier.name === 'applyStyle';
1281  }).gpuAcceleration;
1282  if (legacyGpuAccelerationOption !== undefined) {
1283    console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');
1284  }
1285  var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;
1286
1287  var offsetParent = getOffsetParent(data.instance.popper);
1288  var offsetParentRect = getBoundingClientRect(offsetParent);
1289
1290  // Styles
1291  var styles = {
1292    position: popper.position
1293  };
1294
1295  var offsets = getRoundedOffsets(data, window.devicePixelRatio < 2 || !isFirefox);
1296
1297  var sideA = x === 'bottom' ? 'top' : 'bottom';
1298  var sideB = y === 'right' ? 'left' : 'right';
1299
1300  // if gpuAcceleration is set to `true` and transform is supported,
1301  //  we use `translate3d` to apply the position to the popper we
1302  // automatically use the supported prefixed version if needed
1303  var prefixedProperty = getSupportedPropertyName('transform');
1304
1305  // now, let's make a step back and look at this code closely (wtf?)
1306  // If the content of the popper grows once it's been positioned, it
1307  // may happen that the popper gets misplaced because of the new content
1308  // overflowing its reference element
1309  // To avoid this problem, we provide two options (x and y), which allow
1310  // the consumer to define the offset origin.
1311  // If we position a popper on top of a reference element, we can set
1312  // `x` to `top` to make the popper grow towards its top instead of
1313  // its bottom.
1314  var left = void 0,
1315      top = void 0;
1316  if (sideA === 'bottom') {
1317    // when offsetParent is <html> the positioning is relative to the bottom of the screen (excluding the scrollbar)
1318    // and not the bottom of the html element
1319    if (offsetParent.nodeName === 'HTML') {
1320      top = -offsetParent.clientHeight + offsets.bottom;
1321    } else {
1322      top = -offsetParentRect.height + offsets.bottom;
1323    }
1324  } else {
1325    top = offsets.top;
1326  }
1327  if (sideB === 'right') {
1328    if (offsetParent.nodeName === 'HTML') {
1329      left = -offsetParent.clientWidth + offsets.right;
1330    } else {
1331      left = -offsetParentRect.width + offsets.right;
1332    }
1333  } else {
1334    left = offsets.left;
1335  }
1336  if (gpuAcceleration && prefixedProperty) {
1337    styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
1338    styles[sideA] = 0;
1339    styles[sideB] = 0;
1340    styles.willChange = 'transform';
1341  } else {
1342    // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties
1343    var invertTop = sideA === 'bottom' ? -1 : 1;
1344    var invertLeft = sideB === 'right' ? -1 : 1;
1345    styles[sideA] = top * invertTop;
1346    styles[sideB] = left * invertLeft;
1347    styles.willChange = sideA + ', ' + sideB;
1348  }
1349
1350  // Attributes
1351  var attributes = {
1352    'x-placement': data.placement
1353  };
1354
1355  // Update `data` attributes, styles and arrowStyles
1356  data.attributes = _extends({}, attributes, data.attributes);
1357  data.styles = _extends({}, styles, data.styles);
1358  data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);
1359
1360  return data;
1361}
1362
1363/**
1364 * Helper used to know if the given modifier depends from another one.<br />
1365 * It checks if the needed modifier is listed and enabled.
1366 * @method
1367 * @memberof Popper.Utils
1368 * @param {Array} modifiers - list of modifiers
1369 * @param {String} requestingName - name of requesting modifier
1370 * @param {String} requestedName - name of requested modifier
1371 * @returns {Boolean}
1372 */
1373function isModifierRequired(modifiers, requestingName, requestedName) {
1374  var requesting = find(modifiers, function (_ref) {
1375    var name = _ref.name;
1376    return name === requestingName;
1377  });
1378
1379  var isRequired = !!requesting && modifiers.some(function (modifier) {
1380    return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;
1381  });
1382
1383  if (!isRequired) {
1384    var _requesting = '`' + requestingName + '`';
1385    var requested = '`' + requestedName + '`';
1386    console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');
1387  }
1388  return isRequired;
1389}
1390
1391/**
1392 * @function
1393 * @memberof Modifiers
1394 * @argument {Object} data - The data object generated by update method
1395 * @argument {Object} options - Modifiers configuration and options
1396 * @returns {Object} The data object, properly modified
1397 */
1398function arrow(data, options) {
1399  var _data$offsets$arrow;
1400
1401  // arrow depends on keepTogether in order to work
1402  if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
1403    return data;
1404  }
1405
1406  var arrowElement = options.element;
1407
1408  // if arrowElement is a string, suppose it's a CSS selector
1409  if (typeof arrowElement === 'string') {
1410    arrowElement = data.instance.popper.querySelector(arrowElement);
1411
1412    // if arrowElement is not found, don't run the modifier
1413    if (!arrowElement) {
1414      return data;
1415    }
1416  } else {
1417    // if the arrowElement isn't a query selector we must check that the
1418    // provided DOM node is child of its popper node
1419    if (!data.instance.popper.contains(arrowElement)) {
1420      console.warn('WARNING: `arrow.element` must be child of its popper element!');
1421      return data;
1422    }
1423  }
1424
1425  var placement = data.placement.split('-')[0];
1426  var _data$offsets = data.offsets,
1427      popper = _data$offsets.popper,
1428      reference = _data$offsets.reference;
1429
1430  var isVertical = ['left', 'right'].indexOf(placement) !== -1;
1431
1432  var len = isVertical ? 'height' : 'width';
1433  var sideCapitalized = isVertical ? 'Top' : 'Left';
1434  var side = sideCapitalized.toLowerCase();
1435  var altSide = isVertical ? 'left' : 'top';
1436  var opSide = isVertical ? 'bottom' : 'right';
1437  var arrowElementSize = getOuterSizes(arrowElement)[len];
1438
1439  //
1440  // extends keepTogether behavior making sure the popper and its
1441  // reference have enough pixels in conjunction
1442  //
1443
1444  // top/left side
1445  if (reference[opSide] - arrowElementSize < popper[side]) {
1446    data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
1447  }
1448  // bottom/right side
1449  if (reference[side] + arrowElementSize > popper[opSide]) {
1450    data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
1451  }
1452  data.offsets.popper = getClientRect(data.offsets.popper);
1453
1454  // compute center of the popper
1455  var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
1456
1457  // Compute the sideValue using the updated popper offsets
1458  // take popper margin in account because we don't have this info available
1459  var css = getStyleComputedProperty(data.instance.popper);
1460  var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10);
1461  var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10);
1462  var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
1463
1464  // prevent arrowElement from being placed not contiguously to its popper
1465  sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
1466
1467  data.arrowElement = arrowElement;
1468  data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);
1469
1470  return data;
1471}
1472
1473/**
1474 * Get the opposite placement variation of the given one
1475 * @method
1476 * @memberof Popper.Utils
1477 * @argument {String} placement variation
1478 * @returns {String} flipped placement variation
1479 */
1480function getOppositeVariation(variation) {
1481  if (variation === 'end') {
1482    return 'start';
1483  } else if (variation === 'start') {
1484    return 'end';
1485  }
1486  return variation;
1487}
1488
1489/**
1490 * List of accepted placements to use as values of the `placement` option.<br />
1491 * Valid placements are:
1492 * - `auto`
1493 * - `top`
1494 * - `right`
1495 * - `bottom`
1496 * - `left`
1497 *
1498 * Each placement can have a variation from this list:
1499 * - `-start`
1500 * - `-end`
1501 *
1502 * Variations are interpreted easily if you think of them as the left to right
1503 * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`
1504 * is right.<br />
1505 * Vertically (`left` and `right`), `start` is top and `end` is bottom.
1506 *
1507 * Some valid examples are:
1508 * - `top-end` (on top of reference, right aligned)
1509 * - `right-start` (on right of reference, top aligned)
1510 * - `bottom` (on bottom, centered)
1511 * - `auto-end` (on the side with more space available, alignment depends by placement)
1512 *
1513 * @static
1514 * @type {Array}
1515 * @enum {String}
1516 * @readonly
1517 * @method placements
1518 * @memberof Popper
1519 */
1520var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'];
1521
1522// Get rid of `auto` `auto-start` and `auto-end`
1523var validPlacements = placements.slice(3);
1524
1525/**
1526 * Given an initial placement, returns all the subsequent placements
1527 * clockwise (or counter-clockwise).
1528 *
1529 * @method
1530 * @memberof Popper.Utils
1531 * @argument {String} placement - A valid placement (it accepts variations)
1532 * @argument {Boolean} counter - Set to true to walk the placements counterclockwise
1533 * @returns {Array} placements including their variations
1534 */
1535function clockwise(placement) {
1536  var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
1537
1538  var index = validPlacements.indexOf(placement);
1539  var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));
1540  return counter ? arr.reverse() : arr;
1541}
1542
1543var BEHAVIORS = {
1544  FLIP: 'flip',
1545  CLOCKWISE: 'clockwise',
1546  COUNTERCLOCKWISE: 'counterclockwise'
1547};
1548
1549/**
1550 * @function
1551 * @memberof Modifiers
1552 * @argument {Object} data - The data object generated by update method
1553 * @argument {Object} options - Modifiers configuration and options
1554 * @returns {Object} The data object, properly modified
1555 */
1556function flip(data, options) {
1557  // if `inner` modifier is enabled, we can't use the `flip` modifier
1558  if (isModifierEnabled(data.instance.modifiers, 'inner')) {
1559    return data;
1560  }
1561
1562  if (data.flipped && data.placement === data.originalPlacement) {
1563    // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
1564    return data;
1565  }
1566
1567  var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);
1568
1569  var placement = data.placement.split('-')[0];
1570  var placementOpposite = getOppositePlacement(placement);
1571  var variation = data.placement.split('-')[1] || '';
1572
1573  var flipOrder = [];
1574
1575  switch (options.behavior) {
1576    case BEHAVIORS.FLIP:
1577      flipOrder = [placement, placementOpposite];
1578      break;
1579    case BEHAVIORS.CLOCKWISE:
1580      flipOrder = clockwise(placement);
1581      break;
1582    case BEHAVIORS.COUNTERCLOCKWISE:
1583      flipOrder = clockwise(placement, true);
1584      break;
1585    default:
1586      flipOrder = options.behavior;
1587  }
1588
1589  flipOrder.forEach(function (step, index) {
1590    if (placement !== step || flipOrder.length === index + 1) {
1591      return data;
1592    }
1593
1594    placement = data.placement.split('-')[0];
1595    placementOpposite = getOppositePlacement(placement);
1596
1597    var popperOffsets = data.offsets.popper;
1598    var refOffsets = data.offsets.reference;
1599
1600    // using floor because the reference offsets may contain decimals we are not going to consider here
1601    var floor = Math.floor;
1602    var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);
1603
1604    var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);
1605    var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);
1606    var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);
1607    var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);
1608
1609    var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;
1610
1611    // flip the variation if required
1612    var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
1613    var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom)
vendor: 21,083 bytes, lines 1613-2220
1613;
1614
1615    if (overlapsRef || overflowsBoundaries || flippedVariation) {
1616      // this boolean to detect any flip loop
1617      data.flipped = true;
1618
1619      if (overlapsRef || overflowsBoundaries) {
1620        placement = flipOrder[index + 1];
1621      }
1622
1623      if (flippedVariation) {
1624        variation = getOppositeVariation(variation);
1625      }
1626
1627      data.placement = placement + (variation ? '-' + variation : '');
1628
1629      // this object contains `position`, we want to preserve it along with
1630      // any additional property we may add in the future
1631      data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));
1632
1633      data = runModifiers(data.instance.modifiers, data, 'flip');
1634    }
1635  });
1636  return data;
1637}
1638
1639/**
1640 * @function
1641 * @memberof Modifiers
1642 * @argument {Object} data - The data object generated by update method
1643 * @argument {Object} options - Modifiers configuration and options
1644 * @returns {Object} The data object, properly modified
1645 */
1646function keepTogether(data) {
1647  var _data$offsets = data.offsets,
1648      popper = _data$offsets.popper,
1649      reference = _data$offsets.reference;
1650
1651  var placement = data.placement.split('-')[0];
1652  var floor = Math.floor;
1653  var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
1654  var side = isVertical ? 'right' : 'bottom';
1655  var opSide = isVertical ? 'left' : 'top';
1656  var measurement = isVertical ? 'width' : 'height';
1657
1658  if (popper[side] < floor(reference[opSide])) {
1659    data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];
1660  }
1661  if (popper[opSide] > floor(reference[side])) {
1662    data.offsets.popper[opSide] = floor(reference[side]);
1663  }
1664
1665  return data;
1666}
1667
1668/**
1669 * Converts a string containing value + unit into a px value number
1670 * @function
1671 * @memberof {modifiers~offset}
1672 * @private
1673 * @argument {String} str - Value + unit string
1674 * @argument {String} measurement - `height` or `width`
1675 * @argument {Object} popperOffsets
1676 * @argument {Object} referenceOffsets
1677 * @returns {Number|String}
1678 * Value in pixels, or original string if no values were extracted
1679 */
1680function toValue(str, measurement, popperOffsets, referenceOffsets) {
1681  // separate value from unit
1682  var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/);
1683  var value = +split[1];
1684  var unit = split[2];
1685
1686  // If it's not a number it's an operator, I guess
1687  if (!value) {
1688    return str;
1689  }
1690
1691  if (unit.indexOf('%') === 0) {
1692    var element = void 0;
1693    switch (unit) {
1694      case '%p':
1695        element = popperOffsets;
1696        break;
1697      case '%':
1698      case '%r':
1699      default:
1700        element = referenceOffsets;
1701    }
1702
1703    var rect = getClientRect(element);
1704    return rect[measurement] / 100 * value;
1705  } else if (unit === 'vh' || unit === 'vw') {
1706    // if is a vh or vw, we calculate the size based on the viewport
1707    var size = void 0;
1708    if (unit === 'vh') {
1709      size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
1710    } else {
1711      size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
1712    }
1713    return size / 100 * value;
1714  } else {
1715    // if is an explicit pixel unit, we get rid of the unit and keep the value
1716    // if is an implicit unit, it's px, and we return just the value
1717    return value;
1718  }
1719}
1720
1721/**
1722 * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.
1723 * @function
1724 * @memberof {modifiers~offset}
1725 * @private
1726 * @argument {String} offset
1727 * @argument {Object} popperOffsets
1728 * @argument {Object} referenceOffsets
1729 * @argument {String} basePlacement
1730 * @returns {Array} a two cells array with x and y offsets in numbers
1731 */
1732function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {
1733  var offsets = [0, 0];
1734
1735  // Use height if placement is left or right and index is 0 otherwise use width
1736  // in this way the first offset will use an axis and the second one
1737  // will use the other one
1738  var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;
1739
1740  // Split the offset string to obtain a list of values and operands
1741  // The regex addresses values with the plus or minus sign in front (+10, -20, etc)
1742  var fragments = offset.split(/(\+|\-)/).map(function (frag) {
1743    return frag.trim();
1744  });
1745
1746  // Detect if the offset string contains a pair of values or a single one
1747  // they could be separated by comma or space
1748  var divider = fragments.indexOf(find(fragments, function (frag) {
1749    return frag.search(/,|\s/) !== -1;
1750  }));
1751
1752  if (fragments[divider] && fragments[divider].indexOf(',') === -1) {
1753    console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');
1754  }
1755
1756  // If divider is found, we divide the list of values and operands to divide
1757  // them by ofset X and Y.
1758  var splitRegex = /\s*,\s*|\s+/;
1759  var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];
1760
1761  // Convert the values with units to absolute pixels to allow our computations
1762  ops = ops.map(function (op, index) {
1763    // Most of the units rely on the orientation of the popper
1764    var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';
1765    var mergeWithPrevious = false;
1766    return op
1767    // This aggregates any `+` or `-` sign that aren't considered operators
1768    // e.g.: 10 + +5 => [10, +, +5]
1769    .reduce(function (a, b) {
1770      if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {
1771        a[a.length - 1] = b;
1772        mergeWithPrevious = true;
1773        return a;
1774      } else if (mergeWithPrevious) {
1775        a[a.length - 1] += b;
1776        mergeWithPrevious = false;
1777        return a;
1778      } else {
1779        return a.concat(b);
1780      }
1781    }, [])
1782    // Here we convert the string values into number values (in px)
1783    .map(function (str) {
1784      return toValue(str, measurement, popperOffsets, referenceOffsets);
1785    });
1786  });
1787
1788  // Loop trough the offsets arrays and execute the operations
1789  ops.forEach(function (op, index) {
1790    op.forEach(function (frag, index2) {
1791      if (isNumeric(frag)) {
1792        offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);
1793      }
1794    });
1795  });
1796  return offsets;
1797}
1798
1799/**
1800 * @function
1801 * @memberof Modifiers
1802 * @argument {Object} data - The data object generated by update method
1803 * @argument {Object} options - Modifiers configuration and options
1804 * @argument {Number|String} options.offset=0
1805 * The offset value as described in the modifier description
1806 * @returns {Object} The data object, properly modified
1807 */
1808function offset(data, _ref) {
1809  var offset = _ref.offset;
1810  var placement = data.placement,
1811      _data$offsets = data.offsets,
1812      popper = _data$offsets.popper,
1813      reference = _data$offsets.reference;
1814
1815  var basePlacement = placement.split('-')[0];
1816
1817  var offsets = void 0;
1818  if (isNumeric(+offset)) {
1819    offsets = [+offset, 0];
1820  } else {
1821    offsets = parseOffset(offset, popper, reference, basePlacement);
1822  }
1823
1824  if (basePlacement === 'left') {
1825    popper.top += offsets[0];
1826    popper.left -= offsets[1];
1827  } else if (basePlacement === 'right') {
1828    popper.top += offsets[0];
1829    popper.left += offsets[1];
1830  } else if (basePlacement === 'top') {
1831    popper.left += offsets[0];
1832    popper.top -= offsets[1];
1833  } else if (basePlacement === 'bottom') {
1834    popper.left += offsets[0];
1835    popper.top += offsets[1];
1836  }
1837
1838  data.popper = popper;
1839  return data;
1840}
1841
1842/**
1843 * @function
1844 * @memberof Modifiers
1845 * @argument {Object} data - The data object generated by `update` method
1846 * @argument {Object} options - Modifiers configuration and options
1847 * @returns {Object} The data object, properly modified
1848 */
1849function preventOverflow(data, options) {
1850  var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);
1851
1852  // If offsetParent is the reference element, we really want to
1853  // go one step up and use the next offsetParent as reference to
1854  // avoid to make this modifier completely useless and look like broken
1855  if (data.instance.reference === boundariesElement) {
1856    boundariesElement = getOffsetParent(boundariesElement);
1857  }
1858
1859  // NOTE: DOM access here
1860  // resets the popper's position so that the document size can be calculated excluding
1861  // the size of the popper element itself
1862  var transformProp = getSupportedPropertyName('transform');
1863  var popperStyles = data.instance.popper.style; // assignment to help minification
1864  var top = popperStyles.top,
1865      left = popperStyles.left,
1866      transform = popperStyles[transformProp];
1867
1868  popperStyles.top = '';
1869  popperStyles.left = '';
1870  popperStyles[transformProp] = '';
1871
1872  var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed);
1873
1874  // NOTE: DOM access here
1875  // restores the original style properties after the offsets have been computed
1876  popperStyles.top = top;
1877  popperStyles.left = left;
1878  popperStyles[transformProp] = transform;
1879
1880  options.boundaries = boundaries;
1881
1882  var order = options.priority;
1883  var popper = data.offsets.popper;
1884
1885  var check = {
1886    primary: function primary(placement) {
1887      var value = popper[placement];
1888      if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {
1889        value = Math.max(popper[placement], boundaries[placement]);
1890      }
1891      return defineProperty({}, placement, value);
1892    },
1893    secondary: function secondary(placement) {
1894      var mainSide = placement === 'right' ? 'left' : 'top';
1895      var value = popper[mainSide];
1896      if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {
1897        value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));
1898      }
1899      return defineProperty({}, mainSide, value);
1900    }
1901  };
1902
1903  order.forEach(function (placement) {
1904    var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
1905    popper = _extends({}, popper, check[side](placement));
1906  });
1907
1908  data.offsets.popper = popper;
1909
1910  return data;
1911}
1912
1913/**
1914 * @function
1915 * @memberof Modifiers
1916 * @argument {Object} data - The data object generated by `update` method
1917 * @argument {Object} options - Modifiers configuration and options
1918 * @returns {Object} The data object, properly modified
1919 */
1920function shift(data) {
1921  var placement = data.placement;
1922  var basePlacement = placement.split('-')[0];
1923  var shiftvariation = placement.split('-')[1];
1924
1925  // if shift shiftvariation is specified, run the modifier
1926  if (shiftvariation) {
1927    var _data$offsets = data.offsets,
1928        reference = _data$offsets.reference,
1929        popper = _data$offsets.popper;
1930
1931    var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;
1932    var side = isVertical ? 'left' : 'top';
1933    var measurement = isVertical ? 'width' : 'height';
1934
1935    var shiftOffsets = {
1936      start: defineProperty({}, side, reference[side]),
1937      end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])
1938    };
1939
1940    data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);
1941  }
1942
1943  return data;
1944}
1945
1946/**
1947 * @function
1948 * @memberof Modifiers
1949 * @argument {Object} data - The data object generated by update method
1950 * @argument {Object} options - Modifiers configuration and options
1951 * @returns {Object} The data object, properly modified
1952 */
1953function hide(data) {
1954  if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {
1955    return data;
1956  }
1957
1958  var refRect = data.offsets.reference;
1959  var bound = find(data.instance.modifiers, function (modifier) {
1960    return modifier.name === 'preventOverflow';
1961  }).boundaries;
1962
1963  if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
1964    // Avoid unnecessary DOM access if visibility hasn't changed
1965    if (data.hide === true) {
1966      return data;
1967    }
1968
1969    data.hide = true;
1970    data.attributes['x-out-of-boundaries'] = '';
1971  } else {
1972    // Avoid unnecessary DOM access if visibility hasn't changed
1973    if (data.hide === false) {
1974      return data;
1975    }
1976
1977    data.hide = false;
1978    data.attributes['x-out-of-boundaries'] = false;
1979  }
1980
1981  return data;
1982}
1983
1984/**
1985 * @function
1986 * @memberof Modifiers
1987 * @argument {Object} data - The data object generated by `update` method
1988 * @argument {Object} options - Modifiers configuration and options
1989 * @returns {Object} The data object, properly modified
1990 */
1991function inner(data) {
1992  var placement = data.placement;
1993  var basePlacement = placement.split('-')[0];
1994  var _data$offsets = data.offsets,
1995      popper = _data$offsets.popper,
1996      reference = _data$offsets.reference;
1997
1998  var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;
1999
2000  var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;
2001
2002  popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);
2003
2004  data.placement = getOppositePlacement(placement);
2005  data.offsets.popper = getClientRect(popper);
2006
2007  return data;
2008}
2009
2010/**
2011 * Modifier function, each modifier can have a function of this type assigned
2012 * to its `fn` property.<br />
2013 * These functions will be called on each update, this means that you must
2014 * make sure they are performant enough to avoid performance bottlenecks.
2015 *
2016 * @function ModifierFn
2017 * @argument {dataObject} data - The data object generated by `update` method
2018 * @argument {Object} options - Modifiers configuration and options
2019 * @returns {dataObject} The data object, properly modified
2020 */
2021
2022/**
2023 * Modifiers are plugins used to alter the behavior of your poppers.<br />
2024 * Popper.js uses a set of 9 modifiers to provide all the basic functionalities
2025 * needed by the library.
2026 *
2027 * Usually you don't want to override the `order`, `fn` and `onLoad` props.
2028 * All the other properties are configurations that could be tweaked.
2029 * @namespace modifiers
2030 */
2031var modifiers = {
2032  /**
2033   * Modifier used to shift the popper on the start or end of its reference
2034   * element.<br />
2035   * It will read the variation of the `placement` property.<br />
2036   * It can be one either `-end` or `-start`.
2037   * @memberof modifiers
2038   * @inner
2039   */
2040  shift: {
2041    /** @prop {number} order=100 - Index used to define the order of execution */
2042    order: 100,
2043    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2044    enabled: true,
2045    /** @prop {ModifierFn} */
2046    fn: shift
2047  },
2048
2049  /**
2050   * The `offset` modifier can shift your popper on both its axis.
2051   *
2052   * It accepts the following units:
2053   * - `px` or unit-less, interpreted as pixels
2054   * - `%` or `%r`, percentage relative to the length of the reference element
2055   * - `%p`, percentage relative to the length of the popper element
2056   * - `vw`, CSS viewport width unit
2057   * - `vh`, CSS viewport height unit
2058   *
2059   * For length is intended the main axis relative to the placement of the popper.<br />
2060   * This means that if the placement is `top` or `bottom`, the length will be the
2061   * `width`. In case of `left` or `right`, it will be the `height`.
2062   *
2063   * You can provide a single value (as `Number` or `String`), or a pair of values
2064   * as `String` divided by a comma or one (or more) white spaces.<br />
2065   * The latter is a deprecated method because it leads to confusion and will be
2066   * removed in v2.<br />
2067   * Additionally, it accepts additions and subtractions between different units.
2068   * Note that multiplications and divisions aren't supported.
2069   *
2070   * Valid examples are:
2071   * ```
2072   * 10
2073   * '10%'
2074   * '10, 10'
2075   * '10%, 10'
2076   * '10 + 10%'
2077   * '10 - 5vh + 3%'
2078   * '-10px + 5vh, 5px - 6%'
2079   * ```
2080   * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap
2081   * > with their reference element, unfortunately, you will have to disable the `flip` modifier.
2082   * > You can read more on this at this [issue](https://github.com/FezVrasta/popper.js/issues/373).
2083   *
2084   * @memberof modifiers
2085   * @inner
2086   */
2087  offset: {
2088    /** @prop {number} order=200 - Index used to define the order of execution */
2089    order: 200,
2090    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2091    enabled: true,
2092    /** @prop {ModifierFn} */
2093    fn: offset,
2094    /** @prop {Number|String} offset=0
2095     * The offset value as described in the modifier description
2096     */
2097    offset: 0
2098  },
2099
2100  /**
2101   * Modifier used to prevent the popper from being positioned outside the boundary.
2102   *
2103   * A scenario exists where the reference itself is not within the boundaries.<br />
2104   * We can say it has "escaped the boundaries" — or just "escaped".<br />
2105   * In this case we need to decide whether the popper should either:
2106   *
2107   * - detach from the reference and remain "trapped" in the boundaries, or
2108   * - if it should ignore the boundary and "escape with its reference"
2109   *
2110   * When `escapeWithReference` is set to`true` and reference is completely
2111   * outside its boundaries, the popper will overflow (or completely leave)
2112   * the boundaries in order to remain attached to the edge of the reference.
2113   *
2114   * @memberof modifiers
2115   * @inner
2116   */
2117  preventOverflow: {
2118    /** @prop {number} order=300 - Index used to define the order of execution */
2119    order: 300,
2120    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2121    enabled: true,
2122    /** @prop {ModifierFn} */
2123    fn: preventOverflow,
2124    /**
2125     * @prop {Array} [priority=['left','right','top','bottom']]
2126     * Popper will try to prevent overflow following these priorities by default,
2127     * then, it could overflow on the left and on top of the `boundariesElement`
2128     */
2129    priority: ['left', 'right', 'top', 'bottom'],
2130    /**
2131     * @prop {number} padding=5
2132     * Amount of pixel used to define a minimum distance between the boundaries
2133     * and the popper. This makes sure the popper always has a little padding
2134     * between the edges of its container
2135     */
2136    padding: 5,
2137    /**
2138     * @prop {String|HTMLElement} boundariesElement='scrollParent'
2139     * Boundaries used by the modifier. Can be `scrollParent`, `window`,
2140     * `viewport` or any DOM element.
2141     */
2142    boundariesElement: 'scrollParent'
2143  },
2144
2145  /**
2146   * Modifier used to make sure the reference and its popper stay near each other
2147   * without leaving any gap between the two. Especially useful when the arrow is
2148   * enabled and you want to ensure that it points to its reference element.
2149   * It cares only about the first axis. You can still have poppers with margin
2150   * between the popper and its reference element.
2151   * @memberof modifiers
2152   * @inner
2153   */
2154  keepTogether: {
2155    /** @prop {number} order=400 - Index used to define the order of execution */
2156    order: 400,
2157    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2158    enabled: true,
2159    /** @prop {ModifierFn} */
2160    fn: keepTogether
2161  },
2162
2163  /**
2164   * This modifier is used to move the `arrowElement` of the popper to make
2165   * sure it is positioned between the reference element and its popper element.
2166   * It will read the outer size of the `arrowElement` node to detect how many
2167   * pixels of conjunction are needed.
2168   *
2169   * It has no effect if no `arrowElement` is provided.
2170   * @memberof modifiers
2171   * @inner
2172   */
2173  arrow: {
2174    /** @prop {number} order=500 - Index used to define the order of execution */
2175    order: 500,
2176    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2177    enabled: true,
2178    /** @prop {ModifierFn} */
2179    fn: arrow,
2180    /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */
2181    element: '[x-arrow]'
2182  },
2183
2184  /**
2185   * Modifier used to flip the popper's placement when it starts to overlap its
2186   * reference element.
2187   *
2188   * Requires the `preventOverflow` modifier before it in order to work.
2189   *
2190   * **NOTE:** this modifier will interrupt the current update cycle and will
2191   * restart it if it detects the need to flip the placement.
2192   * @memberof modifiers
2193   * @inner
2194   */
2195  flip: {
2196    /** @prop {number} order=600 - Index used to define the order of execution */
2197    order: 600,
2198    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2199    enabled: true,
2200    /** @prop {ModifierFn} */
2201    fn: flip,
2202    /**
2203     * @prop {String|Array} behavior='flip'
2204     * The behavior used to change the popper's placement. It can be one of
2205     * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid
2206     * placements (with optional variations)
2207     */
2208    behavior: 'flip',
2209    /**
2210     * @prop {number} padding=5
2211     * The popper will flip if it hits the edges of the `boundariesElement`
2212     */
2213    padding: 5,
2214    /**
2215     * @prop {String|HTMLElement} boundariesElement='viewport'
2216     * The element which will define the boundaries of the popper position.
2217     * The popper will never be placed outside of the defined boundaries
2218     * (except if `keepTogether` is enabled)
2219     */
2220    boundariesElement: 'viewport'
2220
2221  },
2222
2223  /**
2224   * Modifier used to make the popper flow toward the inner of the reference element.
2225   * By default, when this modifier is disabled, the popper will be placed outside
2226   * the reference element.
2227   * @memberof modifiers
2228   * @inner
2229   */
2230  inner: {
2231    /** @prop {number} order=700 - Index used to define the order of execution */
2232    order: 700,
2233    /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */
2234    enabled: false,
2235    /** @prop {ModifierFn} */
2236    fn: inner
2237  },
2238
2239  /**
2240   * Modifier used to hide the popper when its reference element is outside of the
2241   * popper boundaries. It will set a `x-out-of-boundaries` attribute which can
2242   * be used to hide with a CSS selector the popper when its reference is
2243   * out of boundaries.
2244   *
2245   * Requires the `preventOverflow` modifier before it in order to work.
2246   * @memberof modifiers
2247   * @inner
2248   */
2249  hide: {
2250    /** @prop {number} order=800 - Index used to define the order of execution */
2251    order: 800,
2252    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2253    enabled: true,
2254    /** @prop {ModifierFn} */
2255    fn: hide
2256  },
2257
2258  /**
2259   * Computes the style that will be applied to the popper element to gets
2260   * properly positioned.
2261   *
2262   * Note that this modifier will not touch the DOM, it just prepares the styles
2263   * so that `applyStyle` modifier can apply it. This separation is useful
2264   * in case you need to replace `applyStyle` with a custom implementation.
2265   *
2266   * This modifier has `850` as `order` value to maintain backward compatibility
2267   * with previous versions of Popper.js. Expect the modifiers ordering method
2268   * to change in future major versions of the library.
2269   *
2270   * @memberof modifiers
2271   * @inner
2272   */
2273  computeStyle: {
2274    /** @prop {number} order=850 - Index used to define the order of execution */
2275    order: 850,
2276    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2277    enabled: true,
2278    /** @prop {ModifierFn} */
2279    fn: computeStyle,
2280    /**
2281     * @prop {Boolean} gpuAcceleration=true
2282     * If true, it uses the CSS 3D transformation to position the popper.
2283     * Otherwise, it will use the `top` and `left` properties
2284     */
2285    gpuAcceleration: true,
2286    /**
2287     * @prop {string} [x='bottom']
2288     * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.
2289     * Change this if your popper should grow in a direction different from `bottom`
2290     */
2291    x: 'bottom',
2292    /**
2293     * @prop {string} [x='left']
2294     * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.
2295     * Change this if your popper should grow in a direction different from `right`
2296     */
2297    y: 'right'
2298  },
2299
2300  /**
2301   * Applies the computed styles to the popper element.
2302   *
2303   * All the DOM manipulations are limited to this modifier. This is useful in case
2304   * you want to integrate Popper.js inside a framework or view library and you
2305   * want to delegate all the DOM manipulations to it.
2306   *
2307   * Note that if you disable this modifier, you must make sure the popper element
2308   * has its position set to `absolute` before Popper.js can do its work!
2309   *
2310   * Just disable this modifier and define your own to achieve the desired effect.
2311   *
2312   * @memberof modifiers
2313   * @inner
2314   */
2315  applyStyle: {
2316    /** @prop {number} order=900 - Index used to define the order of execution */
2317    order: 900,
2318    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2319    enabled: true,
2320    /** @prop {ModifierFn} */
vendor: 4,830 bytes, lines 2321-2459
2321    fn: applyStyle,
2322    /** @prop {Function} */
2323    onLoad: applyStyleOnLoad,
2324    /**
2325     * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier
2326     * @prop {Boolean} gpuAcceleration=true
2327     * If true, it uses the CSS 3D transformation to position the popper.
2328     * Otherwise, it will use the `top` and `left` properties
2329     */
2330    gpuAcceleration: undefined
2331  }
2332};
2333
2334/**
2335 * The `dataObject` is an object containing all the information used by Popper.js.
2336 * This object is passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
2337 * @name dataObject
2338 * @property {Object} data.instance The Popper.js instance
2339 * @property {String} data.placement Placement applied to popper
2340 * @property {String} data.originalPlacement Placement originally defined on init
2341 * @property {Boolean} data.flipped True if popper has been flipped by flip modifier
2342 * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper
2343 * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
2344 * @property {Object} data.styles Any CSS property defined here will be applied to the popper. It expects the JavaScript nomenclature (eg. `marginBottom`)
2345 * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow. It expects the JavaScript nomenclature (eg. `marginBottom`)
2346 * @property {Object} data.boundaries Offsets of the popper boundaries
2347 * @property {Object} data.offsets The measurements of popper, reference and arrow elements
2348 * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
2349 * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
2350 * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0
2351 */
2352
2353/**
2354 * Default options provided to Popper.js constructor.<br />
2355 * These can be overridden using the `options` argument of Popper.js.<br />
2356 * To override an option, simply pass an object with the same
2357 * structure of the `options` object, as the 3rd argument. For example:
2358 * ```
2359 * new Popper(ref, pop, {
2360 *   modifiers: {
2361 *     preventOverflow: { enabled: false }
2362 *   }
2363 * })
2364 * ```
2365 * @type {Object}
2366 * @static
2367 * @memberof Popper
2368 */
2369var Defaults = {
2370  /**
2371   * Popper's placement.
2372   * @prop {Popper.placements} placement='bottom'
2373   */
2374  placement: 'bottom',
2375
2376  /**
2377   * Set this to true if you want popper to position it self in 'fixed' mode
2378   * @prop {Boolean} positionFixed=false
2379   */
2380  positionFixed: false,
2381
2382  /**
2383   * Whether events (resize, scroll) are initially enabled.
2384   * @prop {Boolean} eventsEnabled=true
2385   */
2386  eventsEnabled: true,
2387
2388  /**
2389   * Set to true if you want to automatically remove the popper when
2390   * you call the `destroy` method.
2391   * @prop {Boolean} removeOnDestroy=false
2392   */
2393  removeOnDestroy: false,
2394
2395  /**
2396   * Callback called when the popper is created.<br />
2397   * By default, it is set to no-op.<br />
2398   * Access Popper.js instance with `data.instance`.
2399   * @prop {onCreate}
2400   */
2401  onCreate: function onCreate() {},
2402
2403  /**
2404   * Callback called when the popper is updated. This callback is not called
2405   * on the initialization/creation of the popper, but only on subsequent
2406   * updates.<br />
2407   * By default, it is set to no-op.<br />
2408   * Access Popper.js instance with `data.instance`.
2409   * @prop {onUpdate}
2410   */
2411  onUpdate: function onUpdate() {},
2412
2413  /**
2414   * List of modifiers used to modify the offsets before they are applied to the popper.
2415   * They provide most of the functionalities of Popper.js.
2416   * @prop {modifiers}
2417   */
2418  modifiers: modifiers
2419};
2420
2421/**
2422 * @callback onCreate
2423 * @param {dataObject} data
2424 */
2425
2426/**
2427 * @callback onUpdate
2428 * @param {dataObject} data
2429 */
2430
2431// Utils
2432// Methods
2433var Popper = function () {
2434  /**
2435   * Creates a new Popper.js instance.
2436   * @class Popper
2437   * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper
2438   * @param {HTMLElement} popper - The HTML element used as the popper
2439   * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)
2440   * @return {Object} instance - The generated Popper.js instance
2441   */
2442  function Popper(reference, popper) {
2443    var _this = this;
2444
2445    var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
2446    classCallCheck(this, Popper);
2447
2448    this.scheduleUpdate = function () {
2449      return requestAnimationFrame(_this.update);
2450    };
2451
2452    // make update() debounced, so that it only runs at most once-per-tick
2453    this.update = debounce(this.update.bind(this));
2454
2455    // with {} we create a new object with the options inside it
2456    this.options = _extends({}, Popper.Defaults, options);
2457
2458    // init state
2459    this.state = {
2460      isDestroyed: false,
2461      isCreated: false,
2462      scrollParents: []
2463    };
2464
2465    // get reference and popper elements (allow jQuery wrappers)
2466    this.reference = reference && reference.jquery ? reference[0] : reference;
2467    this.popper = popper && popper.jquery ? popper[0] : popper;
2468
2469    // Deep merge modifiers options
2470    this.options.modifiers = {};
2471    Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {
2472      _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});
2473    });
2474
2475    // Refactoring modifiers' list (Object => Array)
2476    this.modifiers = Object.keys(this.options.modifiers).map(function (name) {
2477      return _extends({
2478        name: name
2479      }, _this.options.modifiers[name]);
2480    })
2481    // sort the modifiers by order
2482    .sort(function (a, b) {
2483      return a.order - b.order;
2484    });
2485
2486    // modifiers have the ability to execute arbitrary code when Popper.js get inited
2487    // such code is executed in the same order of its modifier
2488    // they could add new properties to their options configuration
2489    // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!
2490    this.modifiers.forEach(function (modifierOptions) {
2491      if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {
2492        modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);
2493      }
2494    });
2495
2496    // fire the first update to position the popper in the right place
2497    this.update();
2498
2499    var eventsEnabled = this.options.eventsEnabled;
2500    if (eventsEnabled) {
2501      // setup event listeners, they will take care of update the position in specific situations
2502      this.enableEventListeners();
2503    }
2504
2505    this.state.eventsEnabled = eventsEnabled;
2506  }
2507
2508  // We can't use class properties because they don't get listed in the
2509  // class prototype and break stuff like Sinon stubs
2510
2511
2512  createClass(Popper, [{
2513    key: 'update',
2514    value: function update$$1() {
2515      return update.call(this);
2516    }
2517  }, {
2518    key: 'destroy',
2519    value: function destroy$$1() {
2520      return destroy.call(this);
2521    }
2522  }, {
2523    key: 'enableEventListeners',
2524    value: function enableEventListeners$$1() {
2525      return enableEventListeners.call(this);
2526    }
2527  }, {
2528    key: 'disableEventListeners',
2529    value: function disableEventListeners$$1() {
2530      return disableEventListeners.call(this);
2531    }
2532
2533    /**
2534     * Schedules an update. It will run on the next UI update available.
2535     * @method scheduleUpdate
2536     * @memberof Popper
2537     */
2538
2539
2540    /**
2541     * Collection of utilities useful when writing custom modifiers.
2542     * Starting from version 1.7, this method is available only if you
2543     * include `popper-utils.js` before `popper.js`.
2544     *
2545     * **DEPRECATION**: This way to access PopperUtils is deprecated
2546     * and will be removed in v2! Use the PopperUtils module directly instead.
2547     * Due to the high instability of the methods contained in Utils, we can't
2548     * guarantee them to follow semver. Use them at your own risk!
2549     * @static
2550     * @private
2551     * @type {Object}
2552     * @deprecated since version 1.8
2553     * @member Utils
2554     * @memberof Popper
2555     */
2556
2557  }]);
2558  return Popper;
2559}();
2560
2561/**
2562 * The `referenceObject` is an object that provides an interface compatible with Popper.js
2563 * and lets you use it as replacement of a real DOM node.<br />
2564 * You can use this method to position a popper relatively to a set of coordinates
2565 * in case you don't have a DOM node to use as reference.
2566 *
2567 * ```
2568 * new Popper(referenceObject, popperNode);
2569 * ```
2570 *
2571 * NB: This feature isn't supported in Internet Explorer 10.
2572 * @name referenceObject
2573 * @property {Function} data.getBoundingClientRect
2574 * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.
2575 * @property {number} data.clientWidth
2576 * An ES6 getter that will return the width of the virtual reference element.
2577 * @property {number} data.clientHeight
2578 * An ES6 getter that will return the height of the virtual reference element.
2579 */
2580
2581
2582Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;
2583Popper.placements = placements;
2584Popper.Defaults = Defaults;
2585
2586return Popper;
2587
2588})));
2589//# sourceMappingURL=popper.js.map
2590
2591/*!
2592  * Bootstrap v4.2.1 (https://getbootstrap.com/)
2593  * Copyright 2011-2018 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
2594  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2595  */
2596!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("popper.js"),require("jquery")):"function"==typeof define&&define.amd?define(["exports","popper.js","jquery"],e):e(t.bootstrap={},t.Popper,t.jQuery)}(this,function(t,u,g){"use strict";function i(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function s(t,e,n){return e&&i(t.prototype,e),n&&i(t,n),t}function l(o){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{},e=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(e=e.concat(Object.getOwnPropertySymbols(r).filter(function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable}))),e.forEach(function(t){var e,n,i;e=o,i=r[n=t],n in e?Object.defineProperty(e,n,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[n]=i})}return o}u=u&&u.hasOwnProperty("default")?u.default:u,g=g&&g.hasOwnProperty("default")?g.default:g;var e="transitionend";function n(t){var e=this,n=!1;return g(this).one(_.TRANSITION_END,function(){n=!0}),setTimeout(function(){n||_.triggerTransitionEnd(e)},t),this}var _={TRANSITION_END:"bsTransitionEnd",getUID:function(t){for(;t+=~~(1e6*Math.random()),document.getElementById(t););return t},getSelectorFromElement:function(t){var e=t.getAttribute("data-target");if(!e||"#"===e){var n=t.getAttribute("href");e=n&&"#"!==n?n.trim():""}return e&&document.querySelector(e)?e:null},getTransitionDurationFromElement:function(t){if(!t)return 0;var e=g(t).css("transition-duration"),n=g(t).css("transition-delay"),i=parseFloat(e),o=parseFloat(n);return i||o?(e=e.split(",")[0],n=n.split(",")[0],1e3*(parseFloat(e)+parseFloat(n))):0},reflow:function(t){return t.offsetHeight},triggerTransitionEnd:function(t){g(t).trigger(e)},supportsTransitionEnd:function(){return Boolean(e)},isElement:function(t){return(t[0]||t).nodeType},typeCheckConfig:function(t,e,n){for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)){var o=n[i],r=e[i],s=r&&_.isElement(r)?"element":(a=r,{}.toString.call(a).match(/\s([a-z]+)/i)[1].toLowerCase());if(!new RegExp(o).test(s))throw new Error(t.toUpperCase()+': Option "'+i+'" provided type "'+s+'" but expected type "'+o+'".')}var a},findShadowRoot:function(t){if(!document.documentElement.attachShadow)return null;if("function"!=typeof t.getRootNode)return t instanceof ShadowRoot?t:t.parentNode?_.findShadowRoot(t.parentNode):null;var e=t.getRootNode();return e instanceof ShadowRoot?e:null}};g.fn.emulateTransitionEnd=n,g.event.special[_.TRANSITION_END]={bindType:e,delegateType:e,handle:function(t){if(g(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var o="alert",r="bs.alert",a="."+r,c=g.fn[o],h={CLOSE:"close"+a,CLOSED:"closed"+a,CLICK_DATA_API:"click"+a+".data-api"},f="alert",d="fade",m="show",p=function(){function i(t){this._element=t}var t=i.prototype;return t.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)}
2596,t.dispose=function(){g.removeData(this._element,r),this._element=null},t._getRootElement=function(t){var e=_.getSelectorFromElement(t),n=!1;return e&&(n=document.querySelector(e)),n||(n=g(t).closest("."+f)[0]),n},t._triggerCloseEvent=function(t){var e=g.Event(h.CLOSE);return g(t).trigger(e),e},t._removeElement=function(e){var n=this;if(g(e).removeClass(m),g(e).hasClass(d)){var t=_.getTransitionDurationFromElement(e);g(e).one(_.TRANSITION_END,function(t){return n._destroyElement(e,t)}).emulateTransitionEnd(t)}else this._destroyElement(e)},t._destroyElement=function(t){g(t).detach().trigger(h.CLOSED).remove()},i._jQueryInterface=function(n){return this.each(function(){var t=g(this),e=t.data(r);e||(e=new i(this),t.data(r,e)),"close"===n&&e[n](this)})},i._handleDismiss=function(e){return function(t){t&&t.preventDefault(),e.close(this)}},s(i,null,[{key:"VERSION",get:function(){return"4.2.1"}}]),i}();g(document).on(h.CLICK_DATA_API,'[data-dismiss="alert"]',p._handleDismiss(new p)),g.fn[o]=p._jQueryInterface,g.fn[o].Constructor=p,g.fn[o].noConflict=function(){return g.fn[o]=c,p._jQueryInterface};var v="button",E="bs.button",y="."+E,C=".data-api",T=g.fn[v],S="active",b="btn",I="focus",D='[data-toggle^="button"]',w='[data-toggle="buttons"]',A='input:not([type="hidden"])',N=".active",O=".btn",k={CLICK_DATA_API:"click"+y+C,FOCUS_BLUR_DATA_API:"focus"+y+C+" blur"+y+C},P=function(){function n(t){this._element=t}var t=n.prototype;return t.toggle=function(){var t=!0,e=!0,n=g(this._element).closest(w)[0];if(n){var i=this._element.querySelector(A);if(i){if("radio"===i.type)if(i.checked&&this._element.classList.contains(S))t=!1;else{var o=n.querySelector(N);o&&g(o).removeClass(S)}if(t){if(i.hasAttribute("disabled")||n.hasAttribute("disabled")||i.classList.contains("disabled")||n.classList.contains("disabled"))return;i.checked=!this._element.classList.contains(S),g(i).trigger("change")}i.focus(),e=!1}}e&&this._element.setAttribute("aria-pressed",!this._element.classList.contains(S)),t&&g(this._element).toggleClass(S)},t.dispose=function(){g.removeData(this._element,E),this._element=null},n._jQueryInterface=function(e){return this.each(function(){var t=g(this).data(E);t||(t=new n(this),g(this).data(E,t)),"toggle"===e&&t[e]()})},s(n,null,[{key:"VERSION",get:function(){return"4.2.1"}}]),n}();g(document).on(k.CLICK_DATA_API,D,function(t){t.preventDefault();var e=t.target;g(e).hasClass(b)||(e=g(e).closest(O)),P._jQueryInterface.call(g(e),"toggle")}).on(k.FOCUS_BLUR_DATA_API,D,function(t){var e=g(t.target).closest(O)[0];g(e).toggleClass(I,/^focus(in)?$/.test(t.type))}),g.fn[v]=P._jQueryInterface,g.fn[v].Constructor=P,g.fn[v].noConflict=function(){return g.fn[v]=T,P._jQueryInterface};var L="carousel",j="bs.carousel",H="."+j,R=".data-api",U=g.fn[L],W={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},x={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},F="next",q="prev",M="left",K="right",Q={SLIDE:"slide"+H,SLID:"slid"+H,KEYDOWN:"keydown"+H,MOUSEENTER:"mouseenter"+H,MOUSELEAVE:"mouseleave"+H,TOUCHSTART:"touchstart"+H,TOUCHMOVE:"touchmove"+H,TOUCHEND:"touchend"+H,POINTERDOWN:"pointerdown"+H,POINTERUP:"pointerup"+H,DRAG_START:"dragstart"+H,LOAD_DATA_API:"load"+H+R,CLICK_DATA_API:"click"+H+R},B="carousel",V="active",Y="slide",X="carousel-item-right",z="carousel-item-left",G="carousel-item-next",J="carousel-item-prev",Z="pointer-event",$=".active",tt=".active.carousel-item",et=".carousel-item",nt=".carousel-item img",it=".carousel-item-next, .carousel-item-prev",ot=".carousel-indicators",rt="[data-slide], [data-slide-to]",st='[data-ride="carousel"]',at={TOUCH:"touch",PEN:"pen"},lt=function(){function r(t,e){this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this.touchStartX=0,this.touchDeltaX=0,this._config=this._getConfig(e),this._element=t,this._indicatorsElement=this._element.querySelector(ot),this._touchSupported="ontouchstart"in document.documentElement||0<navigator.maxTouchPoints,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var t=r.prototype;return t.next=function(){this._isSliding||this._slide(F)},t.nextWhenVisible=function(){!document.hidden&&g(this._element).is(":visible")&&"hidden"
2596!==g(this._element).css("visibility")&&this.next()},t.prev=function(){this._isSliding||this._slide(q)},t.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(it)&&(_.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},t.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},t.to=function(t){var e=this;this._activeElement=this._element.querySelector(tt);var n=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)g(this._element).one(Q.SLID,function(){return e.to(t)});else{if(n===t)return this.pause(),void this.cycle();var i=n<t?F:q;this._slide(i,this._items[t])}},t.dispose=function(){g(this._element).off(H),g.removeData(this._element,j),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},t._getConfig=function(t){return t=l({},W,t),_.typeCheckConfig(L,t,x),t},t._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;0<e&&this.prev(),e<0&&this.next()}},t._addEventListeners=function(){var e=this;this._config.keyboard&&g(this._element).on(Q.KEYDOWN,function(t){return e._keydown(t)}),"hover"===this._config.pause&&g(this._element).on(Q.MOUSEENTER,function(t){return e.pause(t)}).on(Q.MOUSELEAVE,function(t){return e.cycle(t)}),this._addTouchEventListeners()},t._addTouchEventListeners=function(){var n=this;if(this._touchSupported){var e=function(t){n._pointerEvent&&at[t.originalEvent.pointerType.toUpperCase()]?n.touchStartX=t.originalEvent.clientX:n._pointerEvent||(n.touchStartX=t.originalEvent.touches[0].clientX)},i=function(t){n._pointerEvent&&at[t.originalEvent.pointerType.toUpperCase()]&&(n.touchDeltaX=t.originalEvent.clientX-n.touchStartX),n._handleSwipe(),"hover"===n._config.pause&&(n.pause(),n.touchTimeout&&clearTimeout(n.touchTimeout),n.touchTimeout=setTimeout(function(t){return n.cycle(t)},500+n._config.interval))};g(this._element.querySelectorAll(nt)).on(Q.DRAG_START,function(t){return t.preventDefault()}),this._pointerEvent?(g(this._element).on(Q.POINTERDOWN,function(t){return e(t)}),g(this._element).on(Q.POINTERUP,function(t){return i(t)}),this._element.classList.add(Z)):(g(this._element).on(Q.TOUCHSTART,function(t){return e(t)}),g(this._element).on(Q.TOUCHMOVE,function(t){var e;(e=t).originalEvent.touches&&1<e.originalEvent.touches.length?n.touchDeltaX=0:n.touchDeltaX=e.originalEvent.touches[0].clientX-n.touchStartX}),g(this._element).on(Q.TOUCHEND,function(t){return i(t)}))}},t._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},t._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(et)):[],this._items.indexOf(t)},t._getItemByDirection=function(t,e){var n=t===F,i=t===q,o=this._getItemIndex(e),r=this._items.length-1;if((i&&0===o||n&&o===r)&&!this._config.wrap)return e;var s=(o+(t===q?-1:1))%this._items.length;return-1===s?this._items[this._items.length-1]:this._items[s]},t._triggerSlideEvent=function(t,e){var n=this._getItemIndex(t),i=this._getItemIndex(this._element.querySelector(tt)),o=g.Event(Q.SLIDE,{relatedTarget:t,direction:e,from:i,to:n});return g(this._element).trigger(o),o},t._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var e=[].slice.call(this._indicatorsElement.querySelectorAll($));g(e).removeClass(V);var n=this._indicatorsElement.children[this._getItemIndex(t)];n&&g(n).addClass(V)}},t._slide=function(t,e){var n,i,o,r=this,s=this._element.querySelector(tt),a=this._getItemIndex(s),l=e||s&&this._getItemByDirection(t,s),c=this._getItemIndex(l),h=Boolean(this._interval);if(o=t===F?(n=z,i=G,M):(n=X,i=J,K),l&&g(l).hasClass(V))this._isSliding=!1;else if(!this._triggerSlideEvent(l,o).isDefaultPrevented()&&s&&l){this._isSliding=!0,h&&this.pause(),this._setActiveIndicatorElement(l);var u=g.Event(Q.SLID,{relatedTarget:l,direction:o,from:a,to:c});if(g(this._element).hasClass(Y)){g(l).addClass(i),_.reflow(l),g(s).addClass(n),g(l).addClass(n);var f=parseInt(l.getAttribute("data-interval"),10);this._config.interval=f?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,f):this._config.defaultInterval||this._config.interval;var d=_.getTransitionDurationFromElement(s);g(s).one(_.TRANSITION_END,function(){g(l).removeClass(n+" "+i).addClass(V),g(s).removeClass(V+" "+i+" "+n),r._isSliding=!1,setTimeout(function(){return g(r._element).trigger(u)},0)}).emulateTransitionEnd(d)}else g(s).removeClass(V),g(l).addClass(V),this._isSliding=!1,g(this._element).trigger(u);h&&this.cycle()}},r._jQueryInterface=function(i){return this.each(function(){var t=g(this).data(j),e=l({},W,g(this).data());"object"==typeof i&&(e=l({},e,i));var n="string"==typeof i?i:e.slide;if(t||(t=new r(this,e),g(this).data(j,t)),"number"==typeof i)t.to(i);else if("string"==typeof n){if("undefined"==typeof t[n])throw new TypeError('No method n
2596amed "'+n+'"');t[n]()}else e.interval&&(t.pause(),t.cycle())})},r._dataApiClickHandler=function(t){var e=_.getSelectorFromElement(this);if(e){var n=g(e)[0];if(n&&g(n).hasClass(B)){var i=l({},g(n).data(),g(this).data()),o=this.getAttribute("data-slide-to");o&&(i.interval=!1),r._jQueryInterface.call(g(n),i),o&&g(n).data(j).to(o),t.preventDefault()}}},s(r,null,[{key:"VERSION",get:function(){return"4.2.1"}},{key:"Default",get:function(){return W}}]),r}();g(document).on(Q.CLICK_DATA_API,rt,lt._dataApiClickHandler),g(window).on(Q.LOAD_DATA_API,function(){for(var t=[].slice.call(document.querySelectorAll(st)),e=0,n=t.length;e<n;e++){var i=g(t[e]);lt._jQueryInterface.call(i,i.data())}}),g.fn[L]=lt._jQueryInterface,g.fn[L].Constructor=lt,g.fn[L].noConflict=function(){return g.fn[L]=U,lt._jQueryInterface};var ct="collapse",ht="bs.collapse",ut="."+ht,ft=g.fn[ct],dt={toggle:!0,parent:""},gt={toggle:"boolean",parent:"(string|element)"},_t={SHOW:"show"+ut,SHOWN:"shown"+ut,HIDE:"hide"+ut,HIDDEN:"hidden"+ut,CLICK_DATA_API:"click"+ut+".data-api"},mt="show",pt="collapse",vt="collapsing",Et="collapsed",yt="width",Ct="height",Tt=".show, .collapsing",St='[data-toggle="collapse"]',bt=function(){function a(e,t){this._isTransitioning=!1,this._element=e,this._config=this._getConfig(t),this._triggerArray=[].slice.call(document.querySelectorAll('[data-toggle="collapse"][href="#'+e.id+'"],[data-toggle="collapse"][data-target="#'+e.id+'"]'));for(var n=[].slice.call(document.querySelectorAll(St)),i=0,o=n.length;i<o;i++){var r=n[i],s=_.getSelectorFromElement(r),a=[].slice.call(document.querySelectorAll(s)).filter(function(t){return t===e});null!==s&&0<a.length&&(this._selector=s,this._triggerArray.push(r))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var t=a.prototype;return t.toggle=function(){g(this._element).hasClass(mt)?this.hide():this.show()},t.show=function(){var t,e,n=this;if(!this._isTransitioning&&!g(this._element).hasClass(mt)&&(this._parent&&0===(t=[].slice.call(this._parent.querySelectorAll(Tt)).filter(function(t){return"string"==typeof n._config.parent?t.getAttribute("data-parent")===n._config.parent:t.classList.contains(pt)})).length&&(t=null),!(t&&(e=g(t).not(this._selector).data(ht))&&e._isTransitioning))){var i=g.Event(_t.SHOW);if(g(this._element).trigger(i),!i.isDefaultPrevented()){t&&(a._jQueryInterface.call(g(t).not(this._selector),"hide"),e||g(t).data(ht,null));var o=this._getDimension();g(this._element).removeClass(pt).addClass(vt),this._element.style[o]=0,this._triggerArray.length&&g(this._triggerArray).removeClass(Et).attr("aria-expanded",!0),this.setTransitioning(!0);var r="scroll"+(o[0].toUpperCase()+o.slice(1)),s=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,function(){g(n._element).removeClass(vt).addClass(pt).addClass(mt),n._element.style[o]="",n.setTransitioning(!1),g(n._element).trigger(_t.SHOWN)}).emulateTransitionEnd(s),this._element.style[o]=this._element[r]+"px"}}},t.hide=function(){var t=this;if(!this._isTransitioning&&g(this._element).hasClass(mt)){var e=g.Event(_t.HIDE);if(g(this._element).trigger(e),!e.isDefaultPrevented()){var n=this._getDimension();this._element.style[n]=this._element.getBoundingClientRect()[n]+"px",_.reflow(this._element),g(this._element).addClass(vt).removeClass(pt).removeClass(mt);var i=this._triggerArray.length;if(0<i)for(var o=0;o<i;o++){var r=this._triggerArray[o],s=_.getSelectorFromElement(r);if(null!==s)g([].slice.call(document.querySelectorAll(s))).hasClass(mt)||g(r).addClass(Et).attr("aria-expanded",!1)}this.setTransitioning(!0);this._element.style[n]="";var a=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,function(){t.setTransitioning(!1),g(t._element).removeClass(vt).addClass(pt).trigger(_t.HIDDEN)}).emulateTransitionEnd(a)}}},t.setTransitioning=function(t){this._isTransitioning=t},t.dispose=function(){g.removeData(this._element,ht),this._config=null,this._parent=null,this._element=null,this._triggerArray=null,this._isTransitioning=null},t._getConfig=function(t){return(t=l({},dt,t)).toggle=Boolean(t.toggle),_.typeCheckConfig(ct,t,gt),t},t._getDimension=function(){return g(this._element).hasClass(yt)?yt:Ct},t._getParent=function(){var t,n=this;_.isElement(this._config.parent)?(t=this._config.parent,"undefined"!=typeof this._config.parent.jquery&&(t=this._config.parent[0])):t=document.querySelector(this._config.parent);var e='[data-toggle="collapse"][data-parent="'+this._config.parent+'"]',i=[].slice.call(t.querySelectorAll(e));return g(i).each(function(t,e){n._addAriaAndCollapsedClass(a._getTargetFromElement(e),[e])}),t},t._addAriaAndCollapsedClass=function(t,e){var n=g(t).hasClass(mt);e.length&&g(e).toggleClass(Et,!n).attr("aria-expanded",n)},a._getTargetFromElement=function(t){var e=_.getSelectorFromElement(t);return e?document.querySelector(e):null},a._jQueryInterface=function(i){return this.each(function(){var t=g(this),e=t.data(ht),n=l({},dt,t.data(),"object"==typeof i&&i?i:{});if(!e&&n.toggle&&/show|hide/.test(i)&&(n.toggle=!1),e||(e=new a(this,n),t.data(ht,e)),"string"==typeof i){if("undefined"==typeof e[i])throw new TypeError('No method n
2596amed "'+i+'"');e[i]()}})},s(a,null,[{key:"VERSION",get:function(){return"4.2.1"}},{key:"Default",get:function(){return dt}}]),a}();g(document).on(_t.CLICK_DATA_API,St,function(t){"A"===t.currentTarget.tagName&&t.preventDefault();var n=g(this),e=_.getSelectorFromElement(this),i=[].slice.call(document.querySelectorAll(e));g(i).each(function(){var t=g(this),e=t.data(ht)?"toggle":n.data();bt._jQueryInterface.call(t,e)})}),g.fn[ct]=bt._jQueryInterface,g.fn[ct].Constructor=bt,g.fn[ct].noConflict=function(){return g.fn[ct]=ft,bt._jQueryInterface};var It="dropdown",Dt="bs.dropdown",wt="."+Dt,At=".data-api",Nt=g.fn[It],Ot=new RegExp("38|40|27"),kt={HIDE:"hide"+wt,HIDDEN:"hidden"+wt,SHOW:"show"+wt,SHOWN:"shown"+wt,CLICK:"click"+wt,CLICK_DATA_API:"click"+wt+At,KEYDOWN_DATA_API:"keydown"+wt+At,KEYUP_DATA_API:"keyup"+wt+At},Pt="disabled",Lt="show",jt="dropup",Ht="dropright",Rt="dropleft",Ut="dropdown-menu-right",Wt="position-static",xt='[data-toggle="dropdown"]',Ft=".dropdown form",qt=".dropdown-menu",Mt=".navbar-nav",Kt=".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",Qt="top-start",Bt="top-end",Vt="bottom-start",Yt="bottom-end",Xt="right-start",zt="left-start",Gt={offset:0,flip:!0,boundary:"scrollParent",reference:"toggle",display:"dynamic"},Jt={offset:"(number|string|function)",flip:"boolean",boundary:"(string|element)",reference:"(string|element)",display:"string"},Zt=function(){function c(t,e){this._element=t,this._popper=null,this._config=this._getConfig(e),this._menu=this._getMenuElement(),this._inNavbar=this._detectNavbar(),this._addEventListeners()}var t=c.prototype;return t.toggle=function(){if(!this._element.disabled&&!g(this._element).hasClass(Pt)){var t=c._getParentFromElement(this._element),e=g(this._menu).hasClass(Lt);if(c._clearMenus(),!e){var n={relatedTarget:this._element},i=g.Event(kt.SHOW,n);if(g(t).trigger(i),!i.isDefaultPrevented()){if(!this._inNavbar){if("undefined"==typeof u)throw new TypeError("Bootstrap's dropdowns require Popper.js (https://popper.js.org/)");var o=this._element;"parent"===this._config.reference?o=t:_.isElement(this._config.reference)&&(o=this._config.reference,"undefined"!=typeof this._config.reference.jquery&&(o=this._config.reference[0])),"scrollParent"!==this._config.boundary&&g(t).addClass(Wt),this._popper=new u(o,this._menu,this._getPopperConfig())}"ontouchstart"in document.documentElement&&0===g(t).closest(Mt).length&&g(document.body).children().on("mouseover",null,g.noop),this._element.focus(),this._element.setAttribute("aria-expanded",!0),g(this._menu).toggleClass(Lt),g(t).toggleClass(Lt).trigger(g.Event(kt.SHOWN,n))}}}},t.show=function(){if(!(this._element.disabled||g(this._element).hasClass(Pt)||g(this._menu).hasClass(Lt))){var t={relatedTarget:this._element},e=g.Event(kt.SHOW,t),n=c._getParentFromElement(this._element);g(n).trigger(e),e.isDefaultPrevented()||(g(this._menu).toggleClass(Lt),g(n).toggleClass(Lt).trigger(g.Event(kt.SHOWN,t)))}},t.hide=function(){if(!this._element.disabled&&!g(this._element).hasClass(Pt)&&g(this._menu).hasClass(Lt)){var t={relatedTarget:this._element},e=g.Event(kt.HIDE,t),n=c._getParentFromElement(this._element);g(n).trigger(e),e.isDefaultPrevented()||(g(this._menu).toggleClass(Lt),g(n).toggleClass(Lt).trigger(g.Event(kt.HIDDEN,t)))}},t.dispose=function(){g.removeData(this._element,Dt),g(this._element).off(wt),this._element=null,(this._menu=null)!==this._popper&&(this._popper.destroy(),this._popper=null)},t.update=function(){this._inNavbar=this._detectNavbar(),null!==this._popper&&this._popper.scheduleUpdate()},t._addEventListeners=function(){var e=this;g(this._element).on(kt.CLICK,function(t){t.preventDefault(),t.stopPropagation(),e.toggle()})},t._getConfig=function(t){return t=l({},this.constructor.Default,g(this._element).data(),t),_.typeCheckConfig(It,t,this.constructor.DefaultType),t},t._getMenuElement=function(){if(!this._menu){var t=c._getParentFromElement(this._element);t&&(this._menu=t.querySelector(qt))}return this._menu},t._getPlacement=function(){var t=g(this._element.parentNode),e=Vt;return t.hasClass(jt)?(e=Qt,g(this._menu).hasClass(Ut)&&(e=Bt)):t.hasClass(Ht)?e=Xt:t.hasClass(Rt)?e=zt:g(this._menu).hasClass(Ut)&&(e=Yt),e},t._detectNavbar=function(){return 0<g(this._element).closest(".
2596navbar").length},t._getPopperConfig=function(){var e=this,t={};"function"==typeof this._config.offset?t.fn=function(t){return t.offsets=l({},t.offsets,e._config.offset(t.offsets)||{}),t}:t.offset=this._config.offset;var n={placement:this._getPlacement(),modifiers:{offset:t,flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(n.modifiers.applyStyle={enabled:!1}),n},c._jQueryInterface=function(e){return this.each(function(){var t=g(this).data(Dt);if(t||(t=new c(this,"object"==typeof e?e:null),g(this).data(Dt,t)),"string"==typeof e){if("undefined"==typeof t[e])throw new TypeError('No method named "'+e+'"');t[e]()}})},c._clearMenus=function(t){if(!t||3!==t.which&&("keyup"!==t.type||9===t.which))for(var e=[].slice.call(document.querySelectorAll(xt)),n=0,i=e.length;n<i;n++){var o=c._getParentFromElement(e[n]),r=g(e[n]).data(Dt),s={relatedTarget:e[n]};if(t&&"click"===t.type&&(s.clickEvent=t),r){var a=r._menu;if(g(o).hasClass(Lt)&&!(t&&("click"===t.type&&/input|textarea/i.test(t.target.tagName)||"keyup"===t.type&&9===t.which)&&g.contains(o,t.target))){var l=g.Event(kt.HIDE,s);g(o).trigger(l),l.isDefaultPrevented()||("ontouchstart"in document.documentElement&&g(document.body).children().off("mouseover",null,g.noop),e[n].setAttribute("aria-expanded","false"),g(a).removeClass(Lt),g(o).removeClass(Lt).trigger(g.Event(kt.HIDDEN,s)))}}}},c._getParentFromElement=function(t){var e,n=_.getSelectorFromElement(t);return n&&(e=document.querySelector(n)),e||t.parentNode},c._dataApiKeydownHandler=function(t){if((/input|textarea/i.test(t.target.tagName)?!(32===t.which||27!==t.which&&(40!==t.which&&38!==t.which||g(t.target).closest(qt).length)):Ot.test(t.which))&&(t.preventDefault(),t.stopPropagation(),!this.disabled&&!g(this).hasClass(Pt))){var e=c._getParentFromElement(this),n=g(e).hasClass(Lt);if(n&&(!n||27!==t.which&&32!==t.which)){var i=[].slice.call(e.querySelectorAll(Kt));if(0!==i.length){var o=i.indexOf(t.target);38===t.which&&0<o&&o--,40===t.which&&o<i.length-1&&o++,o<0&&(o=0),i[o].focus()}}else{if(27===t.which){var r=e.querySelector(xt);g(r).trigger("focus")}g(this).trigger("click")}}},s(c,null,[{key:"VERSION",get:function(){return"4.2.1"}},{key:"Default",get:function(){return Gt}},{key:"DefaultType",get:function(){return Jt}}]),c}();g(document).on(kt.KEYDOWN_DATA_API,xt,Zt._dataApiKeydownHandler).on(kt.KEYDOWN_DATA_API,qt,Zt._dataApiKeydownHandler).on(kt.CLICK_DATA_API+" "+kt.KEYUP_DATA_API,Zt._clearMenus).on(kt.CLICK_DATA_API,xt,function(t){t.preventDefault(),t.stopPropagation(),Zt._jQueryInterface.call(g(this),"toggle")}).on(kt.CLICK_DATA_API,Ft,function(t){t.stopPropagation()}),g.fn[It]=Zt._jQueryInterface,g.fn[It].Constructor=Zt,g.fn[It].noConflict=function(){return g.fn[It]=Nt,Zt._jQueryInterface};var $t="modal",te="bs.modal",ee="."+te,ne=g.fn[$t],ie={backdrop:!0,keyboard:!0,focus:!0,show:!0},oe={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean",show:"boolean"},re={HIDE:"hide"+ee,HIDDEN:"hidden"+ee,SHOW:"show"+ee,SHOWN:"shown"+ee,FOCUSIN:"focusin"+ee,RESIZE:"resize"+ee,CLICK_DISMISS:"click.dismiss"+ee,KEYDOWN_DISMISS:"keydown.dismiss"+ee,MOUSEUP_DISMISS:"mouseup.dismiss"+ee,MOUSEDOWN_DISMISS:"mousedown.dismiss"+ee,CLICK_DATA_API:"click"+ee+".data-api"},se="modal-scrollbar-measure",ae="modal-backdrop",le="modal-open",ce="fade",he="show",ue=".modal-dialog",fe='[data-toggle="modal"]',de='[data-dismiss="modal"]',ge=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",_e=".sticky-top",me=function(){function o(t,e){this._config=this._getConfig(e),this._element=t,this._dialog=t.querySelector(ue),this._backdrop=null,this._isShown=!1,this._isBodyOverflowing=!1,this._ignoreBackdropClick=!1,this._isTransitioning=!1,this._scrollbarWidth=0}var t=o.prototype;return t.toggle=function(t){return this._isShown?this.hide():this.show(t)},t.show=function(t){var e=this;if(!this._isShown&&!this._isTransitioning){g(this._element).hasClass(ce)&&(this._isTransitioning=!0);var n=g.Event(re.SHOW,{relatedTarget:t});g(this._element).trigger(n),this._isShown||n.isDefaultPrevented()||(this._isShown=!0,this._checkScrollbar(),this._setScrollbar(),this._adjustDialog(),this._setEscapeEvent(),this._setResizeEvent(),g(this._element).on(re.CLICK_DISMISS,de,function(t){return e.hide(t)}),g(this._dialog).on(re.MOUSEDOWN_DISMISS,function(){g(e._element).one(re.MOUSEUP_DISMISS,function(t){g(t.target).is(e._element)&&(e._ignoreBackdropClick=!0)})}),this._showBackdrop(function(){return e._showElement(t)}))}},t.hide=function(t){var e=this;if(t&&t.preventDefault(),this._isShown&&!this._isTransitioning){var n=g.Event(re.HIDE);if(g(this._element).trigger(n),this._isShown&&!n.isDefaultPrevented()){this._isShown=!1;var i=g(this._element).hasClass(ce);if(i&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),g(document).off(re.FOCUSIN),g(this._element).removeClass(he),g(this._element).off(re.CLICK_DISMISS),g(this._dialog).off(re.MOUSEDOWN_DISMISS),i){var o=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,function(t){return e._hideModal(t)}).emulateTransitionEnd(o)}else this._hideModal()}}},t.dispose=function(){[window,this._element,this._dialog].forEach(function(t){return g(t).off(ee)}),g(document).off(re.FOCUSIN),g.removeData(this._element,te),this._config=null,this._element=null,this._dialog=null,this._backdrop=null,this._isShown=null,this._isBodyOverflowing=null,this._ignoreBackdropClick=null,this._isTransitioning=null,this._scrollbarWidth=null},t.handleUpdate=function(){this._adjustDialog()},t._getConfig=function(t){return t=l({},ie,t),_.typeCheckConfig($t,t,oe),t},t._showElement=function(t){var e=this,n=g(this._element).hasClass(ce);this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.scrollTop=0,n&&_.reflow(this._element),g(this._element).addClass(he),this._config.focus&&this._enforceFocus();
2596var i=g.Event(re.SHOWN,{relatedTarget:t}),o=function(){e._config.focus&&e._element.focus(),e._isTransitioning=!1,g(e._element).trigger(i)};if(n){var r=_.getTransitionDurationFromElement(this._dialog);g(this._dialog).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o()},t._enforceFocus=function(){var e=this;g(document).off(re.FOCUSIN).on(re.FOCUSIN,function(t){document!==t.target&&e._element!==t.target&&0===g(e._element).has(t.target).length&&e._element.focus()})},t._setEscapeEvent=function(){var e=this;this._isShown&&this._config.keyboard?g(this._element).on(re.KEYDOWN_DISMISS,function(t){27===t.which&&(t.preventDefault(),e.hide())}):this._isShown||g(this._element).off(re.KEYDOWN_DISMISS)},t._setResizeEvent=function(){var e=this;this._isShown?g(window).on(re.RESIZE,function(t){return e.handleUpdate(t)}):g(window).off(re.RESIZE)},t._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._isTransitioning=!1,this._showBackdrop(function(){g(document.body).removeClass(le),t._resetAdjustments(),t._resetScrollbar(),g(t._element).trigger(re.HIDDEN)})},t._removeBackdrop=function(){this._backdrop&&(g(this._backdrop).remove(),this._backdrop=null)},t._showBackdrop=function(t){var e=this,n=g(this._element).hasClass(ce)?ce:"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className=ae,n&&this._backdrop.classList.add(n),g(this._backdrop).appendTo(document.body),g(this._element).on(re.CLICK_DISMISS,function(t){e._ignoreBackdropClick?e._ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"===e._config.backdrop?e._element.focus():e.hide())}),n&&_.reflow(this._backdrop),g(this._backdrop).addClass(he),!t)return;if(!n)return void t();var i=_.getTransitionDurationFromElement(this._backdrop);g(this._backdrop).one(_.TRANSITION_END,t).emulateTransitionEnd(i)}else if(!this._isShown&&this._backdrop){g(this._backdrop).removeClass(he);var o=function(){e._removeBackdrop(),t&&t()};if(g(this._element).hasClass(ce)){var r=_.getTransitionDurationFromElement(this._backdrop);g(this._backdrop).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o()}else t&&t()},t._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},t._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},t._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=t.left+t.right<window.innerWidth,this._scrollbarWidth=this._getScrollbarWidth()},t._setScrollbar=function(){var o=this;if(this._isBodyOverflowing){var t=[].slice.call(document.querySelectorAll(ge)),e=[].slice.call(document.querySelectorAll(_e));g(t).each(function(t,e){var n=e.style.paddingRight,i=g(e).css("padding-right");g(e).data("padding-right",n).css("padding-right",parseFloat(i)+o._scrollbarWidth+"px")}),g(e).each(function(t,e){var n=e.style.marginRight,i=g(e).css("margin-right");g(e).data("margin-right",n).css("margin-right",parseFloat(i)-o._scrollbarWidth+"px")});var n=document.body.style.paddingRight,i=g(document.body).css("padding-right");g(document.body).data("padding-right",n).css("padding-right",parseFloat(i)+this._scrollbarWidth+"px")}g(document.body).addClass(le)},t._resetScrollbar=function(){var t=[].slice.call(document.querySelectorAll(ge));g(t).each(function(t,e){var n=g(e).data("padding-right");g(e).removeData("padding-right"),e.style.paddingRight=n||""});var e=[].slice.call(document.querySelectorAll(""+_e));g(e).each(function(t,e){var n=g(e).data("margin-right");"undefined"!=typeof n&&g(e).css("margin-right",n).removeData("margin-right")});var n=g(document.body).data("padding-right");g(document.body).removeData("padding-right"),document.body.style.paddingRight=n||""},t._getScrollbarWidth=function(){var t=document.createElement("div");t.className=se,document.body.appendChild(t);var e=t.getBoundingClientRect().width-t.clientWidth;return document.body.removeChild(t),e},o._jQueryInterface=function(n,i){return this.each(function(){var t=g(this).data(te),e=l({},ie,g(this).data(),"object"==typeof n&&n?n:{});if(t||(t=new o(this,e),g(this).data(te,t)),"string"==typeof n){if("undefined"==typeof t[n])throw new TypeError('No method n
2596amed "'+n+'"');t[n](i)}else e.show&&t.show(i)})},s(o,null,[{key:"VERSION",get:function(){return"4.2.1"}},{key:"Default",get:function(){return ie}}]),o}();g(document).on(re.CLICK_DATA_API,fe,function(t){var e,n=this,i=_.getSelectorFromElement(this);i&&(e=document.querySelector(i));var o=g(e).data(te)?"toggle":l({},g(e).data(),g(this).data());"A"!==this.tagName&&"AREA"!==this.tagName||t.preventDefault();var r=g(e).one(re.SHOW,function(t){t.isDefaultPrevented()||r.one(re.HIDDEN,function(){g(n).is(":visible")&&n.focus()})});me._jQueryInterface.call(g(e),o,this)}),g.fn[$t]=me._jQueryInterface,g.fn[$t].Constructor=me,g.fn[$t].noConflict=function(){return g.fn[$t]=ne,me._jQueryInterface};var pe="tooltip",ve="bs.tooltip",Ee="."+ve,ye=g.fn[pe],Ce="bs-tooltip",Te=new RegExp("(^|\\s)"+Ce+"\\S+","g"),Se={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)"},be={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"},Ie={animation:!0,template:'<div class="tooltip" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent"},De="show",we="out",Ae={HIDE:"hide"+Ee,HIDDEN:"hidden"+Ee,SHOW:"show"+Ee,SHOWN:"shown"+Ee,INSERTED:"inserted"+Ee,CLICK:"click"+Ee,FOCUSIN:"focusin"+Ee,FOCUSOUT:"focusout"+Ee,MOUSEENTER:"mouseenter"+Ee,MOUSELEAVE:"mouseleave"+Ee},Ne="fade",Oe="show",ke=".tooltip-inner",Pe=".arrow",Le="hover",je="focus",He="click",Re="manual",Ue=function(){function i(t,e){if("undefined"==typeof u)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=g(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(g(this.getTipElement()).hasClass(Oe))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),g.removeData(this.element,this.constructor.DATA_KEY),g(this.element).off(this.constructor.EVENT_KEY),g(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&g(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===g(this.element).css("display"))throw new Error("Please use show on visible elements");var t=g.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){g(this.element).trigger(t);var n=_.findShadowRoot(this.element),i=g.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!i)return;var o=this.getTipElement(),r=_.getUID(this.constructor.NAME);o.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&g(o).addClass(Ne);var s="function"==typeof this.config.placement?this.config.placement.call(this,o,this.element):this.config.placement,a=this._getAttachment(s);this.addAttachmentClass(a);var l=this._getContainer();g(o).data(this.constructor.DATA_KEY,this),g.contains(this.element.ownerDocument.documentElement,this.tip)||g(o).appendTo(l),g(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new u(this.element,o,{placement:a,modifiers:{offset:{offset:this.config.offset},flip:{behavior:this.config.fallbackPlacement},arrow:{element:Pe}
2596,preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),g(o).addClass(Oe),"ontouchstart"in document.documentElement&&g(document.body).children().on("mouseover",null,g.noop);var c=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,g(e.element).trigger(e.constructor.Event.SHOWN),t===we&&e._leave(null,e)};if(g(this.tip).hasClass(Ne)){var h=_.getTransitionDurationFromElement(this.tip);g(this.tip).one(_.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},t.hide=function(t){var e=this,n=this.getTipElement(),i=g.Event(this.constructor.Event.HIDE),o=function(){e._hoverState!==De&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),g(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(g(this.element).trigger(i),!i.isDefaultPrevented()){if(g(n).removeClass(Oe),"ontouchstart"in document.documentElement&&g(document.body).children().off("mouseover",null,g.noop),this._activeTrigger[He]=!1,this._activeTrigger[je]=!1,this._activeTrigger[Le]=!1,g(this.tip).hasClass(Ne)){var r=_.getTransitionDurationFromElement(n);g(n).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){g(this.getTipElement()).addClass(Ce+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},t.setContent=function(){var t=this.getTipElement();this.setElementContent(g(t.querySelectorAll(ke)),this.getTitle()),g(t).removeClass(Ne+" "+Oe)},t.setElementContent=function(t,e){var n=this.config.html;"object"==typeof e&&(e.nodeType||e.jquery)?n?g(e).parent().is(t)||t.empty().append(e):t.text(g(e).text()):t[n?"html":"text"](e)},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},t._getContainer=function(){return!1===this.config.container?document.body:_.isElement(this.config.container)?g(this.config.container):g(document).find(this.config.container)},t._getAttachment=function(t){return be[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)g(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==Re){var e=t===Le?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===Le?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;g(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}}),g(this.element).closest(".modal").on("hide.bs.modal",function(){i.element&&i.hide()}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?je:Le]=!0),g(e.getTipElement()).hasClass(Oe)||e._hoverState===De?e._hoverState=De:(clearTimeout(e._timeout),e._hoverState=De,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===De&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?je:Le]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=we,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===we&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){return"number"==typeof(t=l({},this.constructor.Default,g(this.element).data(),"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),_.typeCheckConfig(pe,t,this.constructor.DefaultType),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Te);null!==e&&e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){var e=t.instance;this.tip=e.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(g(t).removeClass(Ne),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=g(this).data(ve),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),g(this).data(ve,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method n
2596amed "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.2.1"}},{key:"Default",get:function(){return Ie}},{key:"NAME",get:function(){return pe}},{key:"DATA_KEY",get:function(){return ve}},{key:"Event",get:function(){return Ae}},{key:"EVENT_KEY",get:function(){return Ee}},{key:"DefaultType",get:function(){return Se}}]),i}();g.fn[pe]=Ue._jQueryInterface,g.fn[pe].Constructor=Ue,g.fn[pe].noConflict=function(){return g.fn[pe]=ye,Ue._jQueryInterface};var We="popover",xe="bs.popover",Fe="."+xe,qe=g.fn[We],Me="bs-popover",Ke=new RegExp("(^|\\s)"+Me+"\\S+","g"),Qe=l({},Ue.Default,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'}),Be=l({},Ue.DefaultType,{content:"(string|element|function)"}),Ve="fade",Ye="show",Xe=".popover-header",ze=".popover-body",Ge={HIDE:"hide"+Fe,HIDDEN:"hidden"+Fe,SHOW:"show"+Fe,SHOWN:"shown"+Fe,INSERTED:"inserted"+Fe,CLICK:"click"+Fe,FOCUSIN:"focusin"+Fe,FOCUSOUT:"focusout"+Fe,MOUSEENTER:"mouseenter"+Fe,MOUSELEAVE:"mouseleave"+Fe},Je=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),(e.prototype.constructor=e).__proto__=n;var o=i.prototype;return o.isWithContent=function(){return this.getTitle()||this._getContent()},o.addAttachmentClass=function(t){g(this.getTipElement()).addClass(Me+"-"+t)},o.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},o.setContent=function(){var t=g(this.getTipElement());this.setElementContent(t.find(Xe),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(ze),e),t.removeClass(Ve+" "+Ye)},o._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},o._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ke);null!==e&&0<e.length&&t.removeClass(e.join(""))},i._jQueryInterface=function(n){return this.each(function(){var t=g(this).data(xe),e="object"==typeof n?n:null;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),g(this).data(xe,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.2.1"}},{key:"Default",get:function(){return Qe}},{key:"NAME",get:function(){return We}},{key:"DATA_KEY",get:function(){return xe}},{key:"Event",get:function(){return Ge}},{key:"EVENT_KEY",get:function(){return Fe}},{key:"DefaultType",get:function(){return Be}}]),i}(Ue);g.fn[We]=Je._jQueryInterface,g.fn[We].Constructor=Je,g.fn[We].noConflict=function(){return g.fn[We]=qe,Je._jQueryInterface};var Ze="scrollspy",$e="bs.scrollspy",tn="."+$e,en=g.fn[Ze],nn={offset:10,method:"auto",target:""},on={offset:"number",method:"string",target:"(string|element)"},rn={ACTIVATE:"activate"+tn,SCROLL:"scroll"+tn,LOAD_DATA_API:"load"+tn+".data-api"},sn="dropdown-item",an="active",ln='[data-spy="scroll"]',cn=".nav, .list-group",hn=".nav-link",un=".nav-item",fn=".list-group-item",dn=".dropdown",gn=".dropdown-item",_n=".dropdown-toggle",mn="offset",pn="position",vn=function(){function n(t,e){var n=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(e),this._selector=this._config.target+" "+hn+","+this._config.target+" "+fn+","+this._config.target+" "+gn,this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,g(this._scrollElement).on(rn.SCROLL,function(t){return n._process(t)}),this.refresh(),this._process()}var t=n.prototype;return t.refresh=function(){var e=this,t=this._scrollElement===this._scrollElement.window?mn:pn,o="auto"===this._config.method?t:this._config.method,r=o===pn?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map(function(t){var e,n=_.getSelectorFromElement(t);if(n&&(e=document.querySelector(n)),e){var i=e.getBoundingClientRect();if(i.width||i.height)return[g(e)[o]().top+r,n]}return null}).filter(function(t){return t}).sort(function(t,e){return t[0]-e[0]}
2596).forEach(function(t){e._offsets.push(t[0]),e._targets.push(t[1])})},t.dispose=function(){g.removeData(this._element,$e),g(this._scrollElement).off(tn),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},t._getConfig=function(t){if("string"!=typeof(t=l({},nn,"object"==typeof t&&t?t:{})).target){var e=g(t.target).attr("id");e||(e=_.getUID(Ze),g(t.target).attr("id",e)),t.target="#"+e}return _.typeCheckConfig(Ze,t,on),t},t._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},t._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},t._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},t._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),n<=t){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t<this._offsets[0]&&0<this._offsets[0])return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;){this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t<this._offsets[o+1])&&this._activate(this._targets[o])}}},t._activate=function(e){this._activeTarget=e,this._clear();var t=this._selector.split(",").map(function(t){return t+'[data-target="'+e+'"],'+t+'[href="'+e+'"]'}),n=g([].slice.call(document.querySelectorAll(t.join(","))));n.hasClass(sn)?(n.closest(dn).find(_n).addClass(an),n.addClass(an)):(n.addClass(an),n.parents(cn).prev(hn+", "+fn).addClass(an),n.parents(cn).prev(un).children(hn).addClass(an)),g(this._scrollElement).trigger(rn.ACTIVATE,{relatedTarget:e})},t._clear=function(){[].slice.call(document.querySelectorAll(this._selector)).filter(function(t){return t.classList.contains(an)}).forEach(function(t){return t.classList.remove(an)})},n._jQueryInterface=function(e){return this.each(function(){var t=g(this).data($e);if(t||(t=new n(this,"object"==typeof e&&e),g(this).data($e,t)),"string"==typeof e){if("undefined"==typeof t[e])throw new TypeError('No method named "'+e+'"');t[e]()}})},s(n,null,[{key:"VERSION",get:function(){return"4.2.1"}},{key:"Default",get:function(){return nn}}]),n}();g(window).on(rn.LOAD_DATA_API,function(){for(var t=[].slice.call(document.querySelectorAll(ln)),e=t.length;e--;){var n=g(t[e]);vn._jQueryInterface.call(n,n.data())}}),g.fn[Ze]=vn._jQueryInterface,g.fn[Ze].Constructor=vn,g.fn[Ze].noConflict=function(){return g.fn[Ze]=en,vn._jQueryInterface};var En="bs.tab",yn="."+En,Cn=g.fn.tab,Tn={HIDE:"hide"+yn,HIDDEN:"hidden"+yn,SHOW:"show"+yn,SHOWN:"shown"+yn,CLICK_DATA_API:"click"+yn+".data-api"},Sn="dropdown-menu",bn="active",In="disabled",Dn="fade",wn="show",An=".dropdown",Nn=".nav, .list-group",On=".active",kn="> li > .active",Pn='[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',Ln=".dropdown-toggle",jn="> .dropdown-menu .active",Hn=function(){function i(t){this._element=t}var t=i.prototype;return t.show=function(){var n=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&g(this._element).hasClass(bn)||g(this._element).hasClass(In))){var t,i,e=g(this._element).closest(Nn)[0],o=_.getSelectorFromElement(this._element);if(e){var r="UL"===e.nodeName||"OL"===e.nodeName?kn:On;i=(i=g.makeArray(g(e).find(r)))[i.length-1]}var s=g.Event(Tn.HIDE,{relatedTarget:this._element}),a=g.Event(Tn.SHOW,{relatedTarget:i});if(i&&g(i).trigger(s),g(this._element).trigger(a),!a.isDefaultPrevented()&&!s.isDefaultPrevented()){o&&(t=document.querySelector(o)),this._activate(this._element,e);var l=function(){var t=g.Event(Tn.HIDDEN,{relatedTarget:n._element}),e=g.Event(Tn.SHOWN,{relatedTarget:i});g(i).trigger(t),g(n._element).trigger(e)};t?this._activate(t,t.parentNode,l):l()}}},t.dispose=function(){g.removeData(this._element,En),this._element=null},t._activate=function(t,e,n){var i=this,o=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?g(e).children(On):g(e).find(kn))[0],r=n&&o&&g(o).hasClass(Dn),s=function(){return i._transitionComplete(t,o,n)};if(o&&r){var a=_.getTransitionDurationFromElement(o);g(o).removeClass(wn).one(_.TRANSITION_END,s).emulateTransitionEnd(a)}else s()},t._transitionComplete=function(t,e,n){if(e){g(e).removeClass(bn);var i=g(e.parentNode).find(jn)[0];i&&g(i).removeClass(bn),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}if(g(t).addClass(bn),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),_.reflow(t),g(t).addClass(wn),t.parentNode&&g(t.parentNode).hasClass(Sn)){var o=g(t).closest(An)[0];if(o){var r=[].slice.call(o.querySelectorAll(Ln));g(r).addClass(bn)}t.setAttribute("aria-expanded",!0)}n&&n()},i._jQueryInterface=function(n){return this.each(function(){var t=g(this),e=t.data(En);if(e||(e=new i(this),t.data(En,e)),"string"==typeof n){if("undefined"==typeof e[n])throw new TypeError('No method n
2596amed "'+n+'"');e[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.2.1"}}]),i}();g(document).on(Tn.CLICK_DATA_API,Pn,function(t){t.preventDefault(),Hn._jQueryInterface.call(g(this),"show")}),g.fn.tab=Hn._jQueryInterface,g.fn.tab.Constructor=Hn,g.fn.tab.noConflict=function(){return g.fn.tab=Cn,Hn._jQueryInterface};var Rn="toast",Un="bs.toast",Wn="."+Un,xn=g.fn[Rn],Fn={CLICK_DISMISS:"click.dismiss"+Wn,HIDE:"hide"+Wn,HIDDEN:"hidden"+Wn,SHOW:"show"+Wn,SHOWN:"shown"+Wn},qn="fade",Mn="hide",Kn="show",Qn="showing",Bn={animation:"boolean",autohide:"boolean",delay:"number"},Vn={animation:!0,autohide:!0,delay:500},Yn='[data-dismiss="toast"]',Xn=function(){function i(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var t=i.prototype;return t.show=function(){var t=this;g(this._element).trigger(Fn.SHOW),this._config.animation&&this._element.classList.add(qn);var e=function(){t._element.classList.remove(Qn),t._element.classList.add(Kn),g(t._element).trigger(Fn.SHOWN),t._config.autohide&&t.hide()};if(this._element.classList.remove(Mn),this._element.classList.add(Qn),this._config.animation){var n=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},t.hide=function(t){var e=this;this._element.classList.contains(Kn)&&(g(this._element).trigger(Fn.HIDE),t?this._close():this._timeout=setTimeout(function(){e._close()},this._config.delay))},t.dispose=function(){clearTimeout(this._timeout),this._timeout=null,this._element.classList.contains(Kn)&&this._element.classList.remove(Kn),g(this._element).off(Fn.CLICK_DISMISS),g.removeData(this._element,Un),this._element=null,this._config=null},t._getConfig=function(t){return t=l({},Vn,g(this._element).data(),"object"==typeof t&&t?t:{}),_.typeCheckConfig(Rn,t,this.constructor.DefaultType),t},t._setListeners=function(){var t=this;g(this._element).on(Fn.CLICK_DISMISS,Yn,function(){return t.hide(!0)})},t._close=function(){var t=this,e=function(){t._element.classList.add(Mn),g(t._element).trigger(Fn.HIDDEN)};if(this._element.classList.remove(Kn),this._config.animation){var n=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},i._jQueryInterface=function(n){return this.each(function(){var t=g(this),e=t.data(Un);if(e||(e=new i(this,"object"==typeof n&&n),t.data(Un,e)),"string"==typeof n){if("undefined"==typeof e[n])throw new TypeError('No method named "'+n+'"');e[n](this)}})},s(i,null,[{key:"VERSION",get:function(){return"4.2.1"}},{key:"DefaultType",get:function(){return Bn}}]),i}();g.fn[Rn]=Xn._jQueryInterface,g.fn[Rn].Constructor=Xn,g.fn[Rn].noConflict=function(){return g.fn[Rn]=xn,Xn._jQueryInterface},function(){if("undefined"==typeof g)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var t=g.fn.jquery.split(" ")[0].split(".");if(t[0]<2&&t[1]<9||1===t[0]&&9===t[1]&&t[2]<1||4<=t[0])throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}(),t.Util=_,t.Alert=p,t.Button=P,t.Carousel=lt,t.Collapse=bt,t.Dropdown=Zt,t.Modal=me,t.Popover=Je,t.Scrollspy=vn,t.Tab=Hn,t.Toast=Xn,t.Tooltip=Ue,Object.defineProperty(t,"__esModule",{value:!0})});
2597//# sourceMappingURL=bootstrap.min.js.map
2598/*!
2599 * JavaScript Cookie v2.2.0
2600 * https://github.com/js-cookie/js-cookie
2601 *
2602 * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
2603 * Released under the MIT license
2604 */
2605;(function (factory) {
2606	var registeredInModuleLoader = false;
2607	if (typeof define === 'function' && define.amd) {
2608		define(factory);
2609		registeredInModuleLoader = true;
2610	}
2611	if (typeof exports === 'object') {
2612		module.exports = factory();
2613		registeredInModuleLoader = true;
2614	}
2615	if (!registeredInModuleLoader) {
2616		var OldCookies = window.Cookies;
2617		var api = window.Cookies = factory();
2618		api.noConflict = function () {
2619			window.Cookies = OldCookies;
2620			return api;
2621		};
2622	}
2623}(function () {
2624	function extend () {
2625		var i = 0;
2626		var result = {};
2627		for (; i < arguments.length; i++) {
2628			var attributes = arguments[ i ];
2629			for (var key in attributes) {
2630				result[key] = attributes[key];
2631			}
2632		}
2633		return result;
2634	}
2635
2636	function init (converter) {
2637		function api (key, value, attributes) {
2638			var result;
2639			if (typeof document === 'undefined') {
2640				return;
2641			}
2642
2643			// Write
2644
2645			if (arguments.length > 1) {
2646				attributes = extend({
2647					path: '/'
2648				}, api.defaults, attributes);
2649
2650				if (typeof attributes.expires === 'number') {
2651					var expires = new Date();
2652					expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
2653					attributes.expires = expires;
2654				}
2655
2656				// We're using "expires" because "max-age" is not supported by IE
2657				attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';
2658
2659				try {
2660					result = JSON.stringify(value);
2661					if (/^[\{\[]/.test(result)) {
2662						value = result;
2663					}
2664				} catch (e) {}
2665
2666				if (!converter.write) {
2667					value = encodeURIComponent(String(value))
2668						.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
2669				} else {
2670					value = converter.write(value, key);
2671				}
2672
2673				key = encodeURIComponent(String(key));
2674				key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
2675				key = key.replace(/[\(\)]/g, escape);
2676
2677				var stringifiedAttributes = '';
2678
2679				for (var attributeName in attributes) {
2680					if (!attributes[attributeName]) {
2681						continue;
2682					}
2683					stringifiedAttributes += '; ' + attributeName;
2684					if (attributes[attributeName] === true) {
2685						continue;
2686					}
2687					stringifiedAttributes += '=' + attributes[attributeName];
2688				}
2689				return (document.cookie = key + '=' + value + stringifiedAttributes);
2690			}
2691
2692			// Read
2693
2694			if (!key) {
2695				result = {};
2696			}
2697
2698			// To prevent the for loop in the first place assign an empty array
2699			// in case there are no cookies at all. Also prevents odd result when
2700			// calling "get()"
2701			var cookies = document.cookie ? document.cookie.split('; ') : [];
2702			var rdecode = /(%[0-9A-Z]{2})+/g;
2703			var i = 0;
2704
2705			for (; i < cookies.length; i++) {
2706				var parts = cookies[i].split('=');
2707				var cookie = parts.slice(1).join('=');
2708
2709				if (!this.json && cookie.charAt(0) === '"') {
2710					cookie = cookie.slice(1, -1);
2711				}
2712
2713				try {
2714					var name = parts[0].replace(rdecode, decodeURIComponent);
2715					cookie = converter.read ?
2716						converter.read(cookie, name) : converter(cookie, name) ||
2717						cookie.replace(rdecode, decodeURIComponent);
2718
2719					if (this.json) {
2720						try {
2721							cookie = JSON.parse(cookie);
2722						} catch (e) {}
2723					}
2724
2725					if (key === name) {
2726						result = cookie;
2727						break;
2728					}
2729
2730					if (!key) {
2731						result[name] = cookie;
2732					}
2733				} catch (e) {}
2734			}
2735
2736			return result;
2737		}
2738
2739		api.set = api;
2740		api.get = function (key) {
2741			return api.call(api, key);
2742		};
2743		api.getJSON = function () {
2744			return api.apply({
2745				json: true
2746			}, [].slice.call(arguments));
2747		};
2748		api.defaults = {};
2749
2750		api.remove = function (key, attributes) {
2751			api(key, '', extend(attributes, {
2752				expires: -1
2753			}));
2754		};
2755
2756		api.withConverter = init;
2757
2758		return api;
2759	}
2760
2761	return init(function () {});
2762}));
2763
2764!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(
vendor: 18,994 bytes, line 2764
2764t):e.moment=t()}(this,function(){"use strict";var e,i;function c(){return e.apply(null,arguments)}function o(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function u(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function l(e){return void 0===e}function h(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function d(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function f(e,t){var n,s=[];for(n=0;n<e.length;++n)s.push(t(e[n],n));return s}function m(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function _(e,t){for(var n in t)m(t,n)&&(e[n]=t[n]);return m(t,"toString")&&(e.toString=t.toString),m(t,"valueOf")&&(e.valueOf=t.valueOf),e}function y(e,t,n,s){return Tt(e,t,n,s,!0).utc()}function g(e){return null==e._pf&&(e._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}),e._pf}function v(e){if(null==e._isValid){var t=g(e),n=i.call(t.parsedDateParts,function(e){return null!=e}),s=!isNaN(e._d.getTime())&&t.overflow<0&&!t.empty&&!t.invalidMonth&&!t.invalidWeekday&&!t.weekdayMismatch&&!t.nullInput&&!t.invalidFormat&&!t.userInvalidated&&(!t.meridiem||t.meridiem&&n);if(e._strict&&(s=s&&0===t.charsLeftOver&&0===t.unusedTokens.length&&void 0===t.bigHour),null!=Object.isFrozen&&Object.isFrozen(e))return s;e._isValid=s}return e._isValid}function p(e){var t=y(NaN);return null!=e?_(g(t),e):g(t).userInvalidated=!0,t}i=Array.prototype.some?Array.prototype.some:function(e){for(var t=Object(this),n=t.length>>>0,s=0;s<n;s++)if(s in t&&e.call(this,t[s],s,t))return!0;return!1};var r=c.momentProperties=[];function w(e,t){var n,s,i;if(l(t._isAMomentObject)||(e._isAMomentObject=t._isAMomentObject),l(t._i)||(e._i=t._i),l(t._f)||(e._f=t._f),l(t._l)||(e._l=t._l),l(t._strict)||(e._strict=t._strict),l(t._tzm)||(e._tzm=t._tzm),l(t._isUTC)||(e._isUTC=t._isUTC),l(t._offset)||(e._offset=t._offset),l(t._pf)||(e._pf=g(t)),l(t._locale)||(e._locale=t._locale),0<r.length)for(n=0;n<r.length;n++)l(i=t[s=r[n]])||(e[s]=i);return e}var t=!1;function M(e){w(this,e),this._d=new Date(null!=e._d?e._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===t&&(t=!0,c.updateOffset(this),t=!1)}function k(e){return e instanceof M||null!=e&&null!=e._isAMomentObject}function S(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function D(e){var t=+e,n=0;return 0!==t&&isFinite(t)&&(n=S(t)),n}function a(e,t,n){var s,i=Math.min(e.length,t.length),r=Math.abs(e.length-t.length),a=0;for(s=0;s<i;s++)(n&&e[s]!==t[s]||!n&&D(e[s])!==D(t[s]))&&a++;return a+r}function Y(e){!1===c.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+e)}function n(i,r){var a=!0;return _(function(){if(null!=c.deprecationHandler&&c.deprecationHandler(null,i),a){for(var e,t=[],n=0;n<arguments.length;n++){if(e="","object"==typeof arguments[n]){for(var s in e+="\n["+n+"] ",arguments[0])e+=s+": "+arguments[0][s]+", ";e=e.slice(0,-2)}else e=arguments[n];t.push(e)}Y(i+"\nArguments: "+Array.prototype.slice.call(t).join("")+"\n"+(new Error).stack),a=!1}return r.apply(this,arguments)},r)}var s,O={};function T(e,t){null!=c.deprecationHandler&&c.deprecationHandler(e,t),O[e]||(Y(t),O[e]=!0)}function b(e){return e instanceof Function||"[object Function]"===Object.prototype.toString.call(e)}function x(e,t){var n,s=_({},e);for(n in t)m(t,n)&&(u(e[n])&&u(t[n])?(s[n]={},_(s[n],e[n]),_(s[n],t[n])):null!=t[n]?s[n]=t[n]:delete s[n]);for(n in e)m(e,n)&&!m(t,n)&&u(e[n])&&(s[n]=_({},s[n]));return s}function P(e){null!=e&&this.set(e)}c.suppressDeprecationWarnings=!1,c.deprecationHandler=null,s=Object.keys?Object.keys:function(e){var t,n=[];for(t in e)m(e,t)&&n.push(t);return n};var W={};function C(e,t){var n=e.toLowerCase();W[n]=W[n+"s"]=W[t]=e}function H(e){return"string"==typeof e?W[e]||W[e.toLowerCase()]:void 0}function R(e){var t,n,s={};for(n in e)m(e,n)&&(t=H(n))&&(s[t]=e[n]);return s}var U={};function F(e,t){U[e]=t}function L(e,t,n){var s=""+Math.abs(e),i=t-s.length;return(0<=e?n?"+":"":"-")+Math.pow(10,Math.max(0,i)).toString().substr(1)+s}var N=/(\[[^\[]*\])|(\\)?([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,G=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,V={},E={};function I(e,t,n,s){var i=s;"string"==typeof s&&(i=function(){return this[s]()}),e&&(E[e]=i),t&&(E[t[0]]=function(){return L(i.apply(this,arguments),t[1],t[2])}),n&&(E[n]=function(){return this.localeData().ordinal(i.apply(this,arguments),e)})}function A(e,t){return e.isValid()?(t=j(t,e.localeData()),V[t]=V[t]||function(s){var e,i,t,r=s.match(N);for(e=0,i=r.length;e<i;e++)E[r[e]]?r[e]=E[r[e]]:r[e]=(t=r[e]).match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"");return function(e){var t,n="";for(t=0;t<i;t++)n+=b(r[t])?r[t].call(e,s):r[t];return n}}(t),V[t](e)):e.localeData().invalidDate()}function j(e,t){var n=5;function s(e){return t.longDateFormat(e)||e}for(G.lastIndex=0;0<=n&&G.test(e);)e=e.replace(G,s),G.lastIndex=0,n-=1;return e}var Z=/\d/,z=/\d\d/,$=/\d{3}/,q=/\d{4}/,J=/[+-]?\d{6}/,B=/\d\d?/,Q=/\d\d\d\d?/,X=/\d\d\d\d\d\d?/,K=/\d{1,3}/,ee=/\d{1,4}/,te=/[+-]?\d{1,6}/,ne=/\d+/,se=/[+-]?\d+/,ie=/Z|[+-]\d\d:?\d\d/gi,re=/Z|[+-]\d\d(?::?\d\d)?/gi,ae=/[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,oe={};function ue(e,n,s){oe[e]=b(n)?n:function(e,t){return e&&s?s:n}}function le(e,t){return m(oe,e)?oe[e](t._strict,t._locale):new RegExp(he(e.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(e,t,n,s,i){return t||n||s||i})))}function he(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}var de={};function ce(e,n){var t,s=n;for("string"==typeof e&&(e=[e]),h(n)&&(s=function(e,t){t[n]=D(e)}),t=0;t<e.length;t++)de[e[t]]=s}function fe(e,i){ce(e,function(e,t,n,s){n._w=n._w||{},i(e,n._w,n,s)})}var me=0,_e=1,ye=2,ge=3,ve=4,pe=5,we=6,Me=7,ke=8;function Se(e){return De(e)?366:365}function De(e){return e%4==0&&e%100!=0||e%400==0}I("Y",0,0,function(){var e=this.year();return e<=9999?""+e:"+"+e}),I(0,["YY",2],0,function(){return this.year()%100}),I(0,["YYYY",4],0,"year"),I(0,["YYYYY",5],0,"year"),I(0,["YYYYYY",6,!0],0,"year"),C("year","y"),F("year",1),ue("Y",se),ue("YY",B,z),ue("YYYY",ee,q),ue("YYYYY",te,J),ue("YYYYYY",te,J),ce(["YYYYY","YYYYYY"],me),ce("YYYY",function(e,t){t[me]=2===e.length?c.parseTwoDigitYear(e):D(e)}),ce("YY",function(e,t){t[me]=c.parseTwoDigitYear(e)}),ce("Y",function(e,t){t[me]=parseInt(e,10)}),c.parseTwoDigitYear=function(e){return D(e)+(68<D(e)?1900:2e3)};var Ye,Oe=Te("FullYear",!0);function Te(t,n){return function(e){return null!=e?(xe(this,t,e),c.updateOffset(this,n),this):be(this,t)}}function be(e,t){return e.isValid()?e._d["get"+(e._isUTC?"UTC":"")+t]():NaN}function xe(e,t,n){e.isValid()&&!isNaN(n)&&("FullYear"===t&&De(e.year())&&1===e.month()&&29===e.date()?e._d["set"+(e._isUTC?"UTC":"")+t](n,e.month(),Pe(n,e.month())):e._d["set"+(e._isUTC?"UTC":"")+t](n))}function Pe(e,t){if(isNaN(e)||isNaN(t))return NaN;var n,s=(t%(n=12)+n)%n;return e+=(t-s)/12,1===s?De(e)?29:28:31-s%7%2}Ye=Array.prototype.indexOf?Array.prototype.indexOf:function(e){var t;for(t=0;t<this.length;++t)if(this[t]===e)return t;return-1},I("M",["MM",2],"Mo",function(){return this.month()+1}),I("MMM",0,0,function(e){return this.localeData().monthsShort(this,e)}),I("MMMM",0,0,function(e){return this.localeData().months(this,e)}),C("month","M"),F("month",8),ue("M",B),ue("MM",B,z),ue("MMM",function(e,t){return t.monthsShortRegex(e)}),ue("MMMM",function(e,t){return t.monthsRegex(e)}),ce(["M","MM"],function(e,t){t[_e]=D(e)-1}),ce(["MMM","MMMM"],function(e,t,n,s){var i=n._locale.monthsParse(e,s,n._strict);null!=i?t[_e]=i:g(n).invalidMonth=e});var We=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,Ce="January_February_March_April_May_June_July_August_September_October_November_December".split("_");var He="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_");function Re(e,t){var n;if(!e.isValid())return e;if("string"==typeof t)if(/^\d+$/.test(t))t=D(t);else if(!h(t=e.localeData().monthsParse(t)))return e;return n=Math.min(e.date(),Pe(e.year(),t)),e._d["set"+(e._isUTC?"UTC":"")+"Month"](t,n),e}function Ue(e){return null!=e?(Re(this,e),c.updateOffset(this,!0),this):be(this,"Month")}var Fe=ae;var Le=ae;function Ne(){function e(e,t){return t.length-e.length}var t,n,s=[],i=[],r=[];for(t=0;t<12;t++)n=y([2e3,t]),s.push(this.monthsShort(n,"")),i.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(s.sort(e),i.sort(e),r.sort(e),t=0;t<12;t++)s[t]=he(s[t]),i[t]=he(i[t]);for(t=0;t<24;t++)r[t]=he(r[t]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+s.join("|")+")","i")}function Ge(e){var t;if(e<100&&0<=e){var n=Array.prototype.slice.call(arguments);n[0]=e+400,t=new Date(Date.UTC.apply(null,n)),isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e)}else t=new Date(Date.UTC.apply(null,arguments));return t}function Ve(e,t,n){var s=7+t-n;return-((7+Ge(e,0,s).getUTCDay()-t)%7)+s-1}function Ee(e,t,n,s,i){var r,a,o=1+7*(t-1)+(7+n-s)%7+Ve(e,s,i);return a=o<=0?Se(r=e-1)+o:o>Se(e)?(r=e+1,o-Se(e)):(r=e,o),{year:r,dayOfYear:a}}function Ie(e,t,n){var s,i,r=Ve(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?s=a+Ae(i=e.year()-1,t,n):a>Ae(e.year(),t,n)?(s=a-Ae(e.year(),t,n),i=e.year()+1):(i=e.year(),s=a),{week:s,year:i}}function Ae(e,t,n){var s=Ve(e,t,n),i=Ve(e+1,t,n);return(Se(e)-s+i)/7}I("w",["ww",2],"wo","week"),I("W",["WW",2],"Wo","isoWeek"),C("week","w"),C("isoWeek","W"),F("week",5),F("isoWeek",5),ue("w",B),ue("ww",B,z),ue("W",B),ue("WW",B,z),fe(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=D(e)});function je(e,t){return e.slice(t,7).concat(e.slice(0,t))}I("d",0,"do","day"),I("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),I("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),I("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),I("e",0,0,"weekday"),I("E",0,0,"isoWeekday"),C("day","d"),C("weekday","e"),C("isoWeekday","E"),F("day",11),F("weekday",11),F("isoWeekday",11),ue("d",B),ue("e",B),ue("E",B),ue("dd",function(e,t){return t.weekdaysMinRegex(e)}),ue("ddd",function(e,t){return t.weekdaysShortRegex(e)}),ue("dddd",function(e,t){return t.weekdaysRegex(e)}),fe(["dd","ddd","dddd"],function(e,t,n,s){var i=n._locale.weekdaysParse(e,s,n._strict);null!=i?t.d=i:g(n).invalidWeekday=e}),fe(["d","e","E"],function(e,t,n,s){t[s]=D(e)});var Ze="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");var ze="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");var $e="Su_Mo_Tu_We_Th_Fr_Sa".split("_");var qe=ae;var Je=ae;var Be=ae;function Qe(){function e(e,t){return t.length-e.length}var t,n,s,i,r,a=[],o=[],u=[],l=[];for(t=0;t<7;t++)n=y([2e3,1]).day(t),s=this.weekdaysMin(n,""),i=this.weekdaysShort(n,""),r=this.weekdays(n,""),a.push(s),o.push(i),u.push(r),l.push(s),l.push(i),l.push(r);for(a.sort(e),o.sort(e),u.sort(e),l.sort(e),t=0;t<7;t++)o[t]=he(o[t]),u[t]=he(u[t]),l[t]=he(l[t]);this._weekdaysRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function Xe(){return this.hours()%12||12}function Ke(e,t){I(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function et(e,t){return t._meridiemParse}I("H",["HH",2],0,"hour"),I("h",["hh",2],0,Xe),I("k",["kk",2],0,function(){return this.hours()||24}),I("hmm",0,0,function(){return""+Xe.apply(this)+L(this.minutes(),2)}),I("hmmss",0,0,function(){return""+Xe.apply(this)+L(this.minutes(),2)+L(this.seconds(),2)}),I("Hmm",0,0,function(){return""+this.hours()+L(this.minutes(),2)}),I("Hmmss",0,0,function(){return""+this.hours()+L(this.minutes(),2)+L(this.seconds(),2)}),Ke("a",!0),Ke("A",!1),C("hour","h"),F("hour",13),ue("a",et),ue("A",et),ue("H",B),ue("h",B),ue("k",B),ue("HH",B,z),ue("hh",B,z),ue("kk",B,z),ue("hmm",Q),ue("hmmss",X),ue("Hmm",Q),ue("Hmmss",X),ce(["H","HH"],ge),ce(["k","kk"],function(e,t,n){var s=D(e);t[ge]=24===s?0:s}),ce(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),ce(["h","hh"],function(e,t,n){t[ge]=D(e),g(n).bigHour=!0}),ce("hmm",function(e,t,n){var s=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s)),g(n).bigHour=!0}),ce("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s,2)),t[pe]=D(e.substr(i)),g(n).bigHour=!0}),ce("Hmm",function(e,t,n){var s=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s))}),ce("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s,2)),t[pe]=D(e.substr(i))});var tt,nt=Te("Hours",!0),st={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Ce,monthsShort:He,week:{dow:0,doy:6},weekdays:Ze,weekdaysMin:$e,weekdaysShort:ze,meridiemParse:/[ap]\.?m?\.?/i},it={},rt={};function at(e){return e?e.toLowerCase().replace("_","-"):e}function ot(e){var t=null;if(!it[e]&&"undefined"!=typeof module&&module&&module.exports)try{t=tt._abbr,require("./locale/"+e),ut(t)}catch(e){}return it[e]}function ut(e,t){var n;return e&&((n=l(t)?ht(e):lt(e,t))?tt=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),tt._abbr}function lt(e,t){if(null===t)return delete it[e],null;var n,s=st;if(t.abbr=e,null!=it[e])T("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=it[e]._config;else if(null!=t.parentLocale)if(null!=it[t.parentLocale])s=it[t.parentLocale]._config;else{if(null==(n=ot(t.parentLocale)))return rt[t.parentLocale]||(rt[t.parentLocale]=[]),rt[t.parentLocale].push({name:e,config:t}),null;s=n._config}return it[e]=new P(x(s,t)),rt[e]&&rt[e].forEach(function(e){lt(e.name,e.config)}),ut(e),it[e]}function ht(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return tt;if(!o(e)){if(t=ot(e))return t;e=[e]}return function(e){for(var t,n,s,i,r=0;r<e.length;){for(t=(i=at(e[r]).split("-")).length,n=(n=at(e[r+1]))?n.split("-"):null;0<t;){if(s=ot(i.slice(0,t).join("-")))return s;if(n&&n.length>=t&&a(i,n,!0)>=t-1)break;t--}r++}return tt}(e)}function dt(e){var t,n=e._a;return n&&-2===g(e).overflow&&(t=n[_e]<0||11<n[_e]?_e:n[ye]<1||n[ye]>Pe(n[me],n[_e])?ye:n[ge]<0||24<n[ge]||24===n[ge]&&(0!==n[ve]||0!==n[pe]||0!==n[we])?ge:n[ve]<0||59<n[ve]?ve:n[pe]<0||59<n[pe]?pe:n[we]<0||999<n[we]?we:-1,g(e)._overflowDayOfYear&&(t<me||ye<t)&&(t=ye),g(e)._overflowWeeks&&-1===t&&(t=Me),g(e)._overflowWeekday&&-1===t&&(t=ke),g(e).overflow=t),e}function ct(e,t,n){return null!=e?e:null!=t?t:n}function ft(e){var t,n,s,i,r,a=[];if(!e._d){var o,u;for(o=e,u=new Date(c.now()),s=o._useUTC?[u.getUTCFullYear(),u.getUTCMonth(),u.getUTCDate()]:[u.getFullYear(),u.getMonth(),u.getDate()],e._w&&null==e._a[ye]&&null==e._a[_e]&&function(e){var t,n,s,i,r,a,o,u;if(null!=(t=e._w).GG||null!=t.W||null!=t.E)r=1,a=4,n=ct(t.GG,e._a[me],Ie(bt(),1,4).year),s=ct(t.W,1),((i=ct(t.E,1))<1||7<i)&&(u=!0);else{r=e._locale._week.dow,a=e._locale._week.doy;var l=Ie(bt(),r,a);n=ct(t.gg,e._a[me],l.year),s=ct(t.w,l.week),null!=t.d?((i=t.d)<0||6<i)&&(u=!0):null!=t.e?(i=t.e+r,(t.e<0||6<t.e)&&(u=!0)):i=r}s<1||s>Ae(n,r,a)?g(e)._overflowWeeks=!0:null!=u?g(e)._overflowWeekday=!0:(o=Ee(n,s,i,r,a),e._a[me]=o.year,e._dayOfYear=o.dayOfYear)}(e),null!=e._dayOfYear&&(r=ct(e._a[me],s[me]),(e._dayOfYear>Se(r)||0===e._dayOfYear)&&(g(e)._overflowDayOfYear=!0),n=Ge(r,0,e._dayOfYear),e._a[_e]=n.getUTCMonth(),e._a[ye]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=a[t]=s[t];for(;t<7;t++)e._a[t]=a[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[ge]&&0===e._a[ve]&&0===e._a[pe]&&0===e._a[we]&&(e._nextDay=!0,e._a[ge]=0),e._d=(e._useUTC?Ge:function(e,t,n,s,i,r,a){var o;return e<100&&0<=e?(o=new Date(e+400,t,n,s,i,r,a),isFinite(o.getFullYear())&&o.setFullYear(e)):o=new Date(e,t,n,s,i,r,a),o}).apply(null,a),i=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[ge]=24),e._w&&void 0!==e._w.d&&e._w.d!==i&&(g(e).weekdayMismatch=!0)}}var mt=/^\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)?)?$/,_t=/^\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)?)?$/,yt=/Z|[+-]\d\d(?::?\d\d)?/,gt=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],vt=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],pt=/^\/?Date\((\-?\d+)/i;function wt(e){var t,n,s,i,r,a,o=e._i,u=mt.exec(o)||_t.exec(o);if(u){for(g(e).iso=!0,t=0,n=gt.length;t<n;t++)if(gt[t][1].exec(u[1])){i=gt[t][0],s=!1!==gt[t][2];break}if(null==i)return void(e._isValid=!1);if(u[3]){for(t=0,n=vt.length;t<n;t++)if(vt[t][1].exec(u[3])){r=(u[2]||" ")+vt[t][0];break}if(null==r)return void(e._isValid=!1)}if(!s&&null!=r)return void(e._isValid=!1);if(u[4]){if(!yt.exec(u[4]))return void(e._isValid=!1);a="Z"}e._f=i+(r||"")+(a||""),Yt(e)}else e._isValid=!1}var Mt=/^(?:(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}))$/;function kt(e,t,n,s,i,r){var a=[function(e){var t=parseInt(e,10);
vendor: 34,198 bytes, line 2764
2764{if(t<=49)return 2e3+t;if(t<=999)return 1900+t}return t}(e),He.indexOf(t),parseInt(n,10),parseInt(s,10),parseInt(i,10)];return r&&a.push(parseInt(r,10)),a}var St={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function Dt(e){var t,n,s,i=Mt.exec(e._i.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").replace(/^\s\s*/,"").replace(/\s\s*$/,""));if(i){var r=kt(i[4],i[3],i[2],i[5],i[6],i[7]);if(t=i[1],n=r,s=e,t&&ze.indexOf(t)!==new Date(n[0],n[1],n[2]).getDay()&&(g(s).weekdayMismatch=!0,!(s._isValid=!1)))return;e._a=r,e._tzm=function(e,t,n){if(e)return St[e];if(t)return 0;var s=parseInt(n,10),i=s%100;return(s-i)/100*60+i}(i[8],i[9],i[10]),e._d=Ge.apply(null,e._a),e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),g(e).rfc2822=!0}else e._isValid=!1}function Yt(e){if(e._f!==c.ISO_8601)if(e._f!==c.RFC_2822){e._a=[],g(e).empty=!0;var t,n,s,i,r,a,o,u,l=""+e._i,h=l.length,d=0;for(s=j(e._f,e._locale).match(N)||[],t=0;t<s.length;t++)i=s[t],(n=(l.match(le(i,e))||[])[0])&&(0<(r=l.substr(0,l.indexOf(n))).length&&g(e).unusedInput.push(r),l=l.slice(l.indexOf(n)+n.length),d+=n.length),E[i]?(n?g(e).empty=!1:g(e).unusedTokens.push(i),a=i,u=e,null!=(o=n)&&m(de,a)&&de[a](o,u._a,u,a)):e._strict&&!n&&g(e).unusedTokens.push(i);g(e).charsLeftOver=h-d,0<l.length&&g(e).unusedInput.push(l),e._a[ge]<=12&&!0===g(e).bigHour&&0<e._a[ge]&&(g(e).bigHour=void 0),g(e).parsedDateParts=e._a.slice(0),g(e).meridiem=e._meridiem,e._a[ge]=function(e,t,n){var s;if(null==n)return t;return null!=e.meridiemHour?e.meridiemHour(t,n):(null!=e.isPM&&((s=e.isPM(n))&&t<12&&(t+=12),s||12!==t||(t=0)),t)}(e._locale,e._a[ge],e._meridiem),ft(e),dt(e)}else Dt(e);else wt(e)}function Ot(e){var t,n,s,i,r=e._i,a=e._f;return e._locale=e._locale||ht(e._l),null===r||void 0===a&&""===r?p({nullInput:!0}):("string"==typeof r&&(e._i=r=e._locale.preparse(r)),k(r)?new M(dt(r)):(d(r)?e._d=r:o(a)?function(e){var t,n,s,i,r;if(0===e._f.length)return g(e).invalidFormat=!0,e._d=new Date(NaN);for(i=0;i<e._f.length;i++)r=0,t=w({},e),null!=e._useUTC&&(t._useUTC=e._useUTC),t._f=e._f[i],Yt(t),v(t)&&(r+=g(t).charsLeftOver,r+=10*g(t).unusedTokens.length,g(t).score=r,(null==s||r<s)&&(s=r,n=t));_(e,n||t)}(e):a?Yt(e):l(n=(t=e)._i)?t._d=new Date(c.now()):d(n)?t._d=new Date(n.valueOf()):"string"==typeof n?(s=t,null===(i=pt.exec(s._i))?(wt(s),!1===s._isValid&&(delete s._isValid,Dt(s),!1===s._isValid&&(delete s._isValid,c.createFromInputFallback(s)))):s._d=new Date(+i[1])):o(n)?(t._a=f(n.slice(0),function(e){return parseInt(e,10)}),ft(t)):u(n)?function(e){if(!e._d){var t=R(e._i);e._a=f([t.year,t.month,t.day||t.date,t.hour,t.minute,t.second,t.millisecond],function(e){return e&&parseInt(e,10)}),ft(e)}}(t):h(n)?t._d=new Date(n):c.createFromInputFallback(t),v(e)||(e._d=null),e))}function Tt(e,t,n,s,i){var r,a={};return!0!==n&&!1!==n||(s=n,n=void 0),(u(e)&&function(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;var t;for(t in e)if(e.hasOwnProperty(t))return!1;return!0}(e)||o(e)&&0===e.length)&&(e=void 0),a._isAMomentObject=!0,a._useUTC=a._isUTC=i,a._l=n,a._i=e,a._f=t,a._strict=s,(r=new M(dt(Ot(a))))._nextDay&&(r.add(1,"d"),r._nextDay=void 0),r}function bt(e,t,n,s){return Tt(e,t,n,s,!1)}c.createFromInputFallback=n("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(e){e._d=new Date(e._i+(e._useUTC?" UTC":""))}),c.ISO_8601=function(){},c.RFC_2822=function(){};var xt=n("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=bt.apply(null,arguments);return this.isValid()&&e.isValid()?e<this?this:e:p()}),Pt=n("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=bt.apply(null,arguments);return this.isValid()&&e.isValid()?this<e?this:e:p()});function Wt(e,t){var n,s;if(1===t.length&&o(t[0])&&(t=t[0]),!t.length)return bt();for(n=t[0],s=1;s<t.length;++s)t[s].isValid()&&!t[s][e](n)||(n=t[s]);return n}var Ct=["year","quarter","month","week","day","hour","minute","second","millisecond"];function Ht(e){var t=R(e),n=t.year||0,s=t.quarter||0,i=t.month||0,r=t.week||t.isoWeek||0,a=t.day||0,o=t.hour||0,u=t.minute||0,l=t.second||0,h=t.millisecond||0;this._isValid=function(e){for(var t in e)if(-1===Ye.call(Ct,t)||null!=e[t]&&isNaN(e[t]))return!1;for(var n=!1,s=0;s<Ct.length;++s)if(e[Ct[s]]){if(n)return!1;parseFloat(e[Ct[s]])!==D(e[Ct[s]])&&(n=!0)}return!0}(t),this._milliseconds=+h+1e3*l+6e4*u+1e3*o*60*60,this._days=+a+7*r,this._months=+i+3*s+12*n,this._data={},this._locale=ht(),this._bubble()}function Rt(e){return e instanceof Ht}function Ut(e){return e<0?-1*Math.round(-1*e):Math.round(e)}function Ft(e,n){I(e,0,0,function(){var e=this.utcOffset(),t="+";return e<0&&(e=-e,t="-"),t+L(~~(e/60),2)+n+L(~~e%60,2)})}Ft("Z",":"),Ft("ZZ",""),ue("Z",re),ue("ZZ",re),ce(["Z","ZZ"],function(e,t,n){n._useUTC=!0,n._tzm=Nt(re,e)});var Lt=/([\+\-]|\d\d)/gi;function Nt(e,t){var n=(t||"").match(e);if(null===n)return null;var s=((n[n.length-1]||[])+"").match(Lt)||["-",0,0],i=60*s[1]+D(s[2]);return 0===i?0:"+"===s[0]?i:-i}function Gt(e,t){var n,s;return t._isUTC?(n=t.clone(),s=(k(e)||d(e)?e.valueOf():bt(e).valueOf())-n.valueOf(),n._d.setTime(n._d.valueOf()+s),c.updateOffset(n,!1),n):bt(e).local()}function Vt(e){return 15*-Math.round(e._d.getTimezoneOffset()/15)}function Et(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}c.updateOffset=function(){};var It=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,At=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function jt(e,t){var n,s,i,r=e,a=null;return Rt(e)?r={ms:e._milliseconds,d:e._days,M:e._months}:h(e)?(r={},t?r[t]=e:r.milliseconds=e):(a=It.exec(e))?(n="-"===a[1]?-1:1,r={y:0,d:D(a[ye])*n,h:D(a[ge])*n,m:D(a[ve])*n,s:D(a[pe])*n,ms:D(Ut(1e3*a[we]))*n}):(a=At.exec(e))?(n="-"===a[1]?-1:1,r={y:Zt(a[2],n),M:Zt(a[3],n),w:Zt(a[4],n),d:Zt(a[5],n),h:Zt(a[6],n),m:Zt(a[7],n),s:Zt(a[8],n)}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(i=function(e,t){var n;if(!e.isValid()||!t.isValid())return{milliseconds:0,months:0};t=Gt(t,e),e.isBefore(t)?n=zt(e,t):((n=zt(t,e)).milliseconds=-n.milliseconds,n.months=-n.months);return n}(bt(r.from),bt(r.to)),(r={}).ms=i.milliseconds,r.M=i.months),s=new Ht(r),Rt(e)&&m(e,"_locale")&&(s._locale=e._locale),s}function Zt(e,t){var n=e&&parseFloat(e.replace(",","."));return(isNaN(n)?0:n)*t}function zt(e,t){var n={};return n.months=t.month()-e.month()+12*(t.year()-e.year()),e.clone().add(n.months,"M").isAfter(t)&&--n.months,n.milliseconds=+t-+e.clone().add(n.months,"M"),n}function $t(s,i){return function(e,t){var n;return null===t||isNaN(+t)||(T(i,"moment()."+i+"(period, number) is deprecated. Please use moment()."+i+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),n=e,e=t,t=n),qt(this,jt(e="string"==typeof e?+e:e,t),s),this}}function qt(e,t,n,s){var i=t._milliseconds,r=Ut(t._days),a=Ut(t._months);e.isValid()&&(s=null==s||s,a&&Re(e,be(e,"Month")+a*n),r&&xe(e,"Date",be(e,"Date")+r*n),i&&e._d.setTime(e._d.valueOf()+i*n),s&&c.updateOffset(e,r||a))}jt.fn=Ht.prototype,jt.invalid=function(){return jt(NaN)};var Jt=$t(1,"add"),Bt=$t(-1,"subtract");function Qt(e,t){var n=12*(t.year()-e.year())+(t.month()-e.month()),s=e.clone().add(n,"months");return-(n+(t-s<0?(t-s)/(s-e.clone().add(n-1,"months")):(t-s)/(e.clone().add(n+1,"months")-s)))||0}function Xt(e){var t;return void 0===e?this._locale._abbr:(null!=(t=ht(e))&&(this._locale=t),this)}c.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",c.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Kt=n("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(e){return void 0===e?this.localeData():this.locale(e)});function en(){return this._locale}var tn=126227808e5;function nn(e,t){return(e%t+t)%t}function sn(e,t,n){return e<100&&0<=e?new Date(e+400,t,n)-tn:new Date(e,t,n).valueOf()}function rn(e,t,n){return e<100&&0<=e?Date.UTC(e+400,t,n)-tn:Date.UTC(e,t,n)}function an(e,t){I(0,[e,e.length],0,t)}function on(e,t,n,s,i){var r;return null==e?Ie(this,s,i).year:((r=Ae(e,s,i))<t&&(t=r),function(e,t,n,s,i){var r=Ee(e,t,n,s,i),a=Ge(r.year,0,r.dayOfYear);return this.year(a.getUTCFullYear()),this.month(a.getUTCMonth()),this.date(a.getUTCDate()),this}.call(this,e,t,n,s,i))}I(0,["gg",2],0,function(){return this.weekYear()%100}),I(0,["GG",2],0,function(){return this.isoWeekYear()%100}),an("gggg","weekYear"),an("ggggg","weekYear"),an("GGGG","isoWeekYear"),an("GGGGG","isoWeekYear"),C("weekYear","gg"),C("isoWeekYear","GG"),F("weekYear",1),F("isoWeekYear",1),ue("G",se),ue("g",se),ue("GG",B,z),ue("gg",B,z),ue("GGGG",ee,q),ue("gggg",ee,q),ue("GGGGG",te,J),ue("ggggg",te,J),fe(["gggg","ggggg","GGGG","GGGGG"],function(e,t,n,s){t[s.substr(0,2)]=D(e)}),fe(["gg","GG"],function(e,t,n,s){t[s]=c.parseTwoDigitYear(e)}),I("Q",0,"Qo","quarter"),C("quarter","Q"),F("quarter",7),ue("Q",Z),ce("Q",function(e,t){t[_e]=3*(D(e)-1)}),I("D",["DD",2],"Do","date"),C("date","D"),F("date",9),ue("D",B),ue("DD",B,z),ue("Do",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient}),ce(["D","DD"],ye),ce("Do",function(e,t){t[ye]=D(e.match(B)[0])});var un=Te("Date",!0);I("DDD",["DDDD",3],"DDDo","dayOfYear"),C("dayOfYear","DDD"),F("dayOfYear",4),ue("DDD",K),ue("DDDD",$),ce(["DDD","DDDD"],function(e,t,n){n._dayOfYear=D(e)}),I("m",["mm",2],0,"minute"),C("minute","m"),F("minute",14),ue("m",B),ue("mm",B,z),ce(["m","mm"],ve);var ln=Te("Minutes",!1);I("s",["ss",2],0,"second"),C("second","s"),F("second",15),ue("s",B),ue("ss",B,z),ce(["s","ss"],pe);var hn,dn=Te("Seconds",!1);for(I("S",0,0,function(){return~~(this.millisecond()/100)}),I(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),I(0,["SSS",3],0,"millisecond"),I(0,["SSSS",4],0,function(){return 10*this.millisecond()}),I(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),I(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),I(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),I(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),I(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),C("millisecond","ms"),F("millisecond",16),ue("S",K,Z),ue("SS",K,z),ue("SSS",K,$),hn="SSSS";hn.length<=9;hn+="S")ue(hn,ne);function cn(e,t){t[we]=D(1e3*("0."+e))}for(hn="S";hn.length<=9;hn+="S")ce(hn,cn);var fn=Te("Milliseconds",!1);I("z",0,0,"zoneAbbr"),I("zz",0,0,"zoneName");var mn=M.prototype;function _n(e){return e}mn.add=Jt,mn.calendar=function(e,t){var n=e||bt(),s=Gt(n,this).startOf("day"),i=c.calendarFormat(this,s)||"sameElse",r=t&&(b(t[i])?t[i].call(this,n):t[i]);return this.format(r||this.localeData().calendar(i,this,bt(n)))},mn.clone=function(){return new M(this)},mn.diff=function(e,t,n){var s,i,r;if(!this.isValid())return NaN;if(!(s=Gt(e,this)).isValid())return NaN;switch(i=6e4*(s.utcOffset()-this.utcOffset()),t=H(t)){case"year":r=Qt(this,s)/12;break;case"month":r=Qt(this,s);break;case"quarter":r=Qt(this,s)/3;break;case"second":r=(this-s)/1e3;break;case"minute":r=(this-s)/6e4;break;case"hour":r=(this-s)/36e5;break;case"day":r=(this-s-i)/864e5;break;case"week":r=(this-s-i)/6048e5;break;default:r=this-s}return n?r:S(r)},mn.endOf=function(e){var t;if(void 0===(e=H(e))||"millisecond"===e||!this.isValid())return this;var n=this._isUTC?rn:sn;switch(e){case"year":t=n(this.year()+1,0,1)-1;break;case"quarter":t=n(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":t=n(this.year(),this.month()+1,1)-1;break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":t=n(this.year(),this.month(),this.date()+1)-1;break;case"hour":t=this._d.valueOf(),t+=36e5-nn(t+(this._isUTC?0:6e4*this.utcOffset()),36e5)-1;break;case"minute":t=this._d.valueOf(),t+=6e4-nn(t,6e4)-1;break;case"second":t=this._d.valueOf(),t+=1e3-nn(t,1e3)-1;break}return this._d.setTime(t),c.updateOffset(this,!0),this},mn.format=function(e){e||(e=this.isUtc()?c.defaultFormatUtc:c.defaultFormat);var t=A(this,e);return this.localeData().postformat(t)},mn.from=function(e,t){return this.isValid()&&(k(e)&&e.isValid()||bt(e).isValid())?jt({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},mn.fromNow=function(e){return this.from(bt(),e)},mn.to=function(e,t){return this.isValid()&&(k(e)&&e.isValid()||bt(e).isValid())?jt({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},mn.toNow=function(e){return this.to(bt(),e)},mn.get=function(e){return b(this[e=H(e)])?this[e]():this},mn.invalidAt=function(){return g(this).overflow},mn.isAfter=function(e,t){var n=k(e)?e:bt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=H(t)||"millisecond")?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(t).valueOf())},mn.isBefore=function(e,t){var n=k(e)?e:bt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=H(t)||"millisecond")?this.valueOf()<n.valueOf():this.clone().endOf(t).valueOf()<n.valueOf())},mn.isBetween=function(e,t,n,s){var i=k(e)?e:bt(e),r=k(t)?t:bt(t);return!!(this.isValid()&&i.isValid()&&r.isValid())&&("("===(s=s||"()")[0]?this.isAfter(i,n):!this.isBefore(i,n))&&(")"===s[1]?this.isBefore(r,n):!this.isAfter(r,n))},mn.isSame=function(e,t){var n,s=k(e)?e:bt(e);return!(!this.isValid()||!s.isValid())&&("millisecond"===(t=H(t)||"millisecond")?this.valueOf()===s.valueOf():(n=s.valueOf(),this.clone().startOf(t).valueOf()<=n&&n<=this.clone().endOf(t).valueOf()))},mn.isSameOrAfter=function(e,t){return this.isSame(e,t)||this.isAfter(e,t)},mn.isSameOrBefore=function(e,t){return this.isSame(e,t)||this.isBefore(e,t)},mn.isValid=function(){return v(this)},mn.lang=Kt,mn.locale=Xt,mn.localeData=en,mn.max=Pt,mn.min=xt,mn.parsingFlags=function(){return _({},g(this))},mn.set=function(e,t){if("object"==typeof e)for(var n=function(e){var t=[];for(var n in e)t.push({unit:n,priority:U[n]});return t.sort(function(e,t){return e.priority-t.priority}),t}(e=R(e)),s=0;s<n.length;s++)this[n[s].unit](e[n[s].unit]);else if(b(this[e=H(e)]))return this[e](t);return this},mn.startOf=function(e){var t;if(void 0===(e=H(e))||"millisecond"===e||!this.isValid())return this;var n=this._isUTC?rn:sn;switch(e){case"year":t=n(this.year(),0,1);break;case"quarter":t=n(this.year(),this.month()-this.month()%3,1);break;case"month":t=n(this.year(),this.month(),1);break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":t=n(this.year(),this.month(),this.date());break;case"hour":t=this._d.valueOf(),t-=nn(t+(this._isUTC?0:6e4*this.utcOffset()),36e5);break;case"minute":t=this._d.valueOf(),t-=nn(t,6e4);break;case"second":t=this._d.valueOf(),t-=nn(t,1e3);break}return this._d.setTime(t),c.updateOffset(this,!0),this},mn.subtract=Bt,mn.toArray=function(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]},mn.toObject=function(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}},mn.toDate=function(){return new Date(this.valueOf())},mn.toISOString=function(e){if(!this.isValid())return null;var t=!0!==e,n=t?this.clone().utc():this;return n.year()<0||9999<n.year()?A(n,t?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):b(Date.prototype.toISOString)?t?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",A(n,"Z")):A(n,t?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")},mn.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e="moment",t="";this.isLocal()||(e=0===this.utcOffset()?"moment.utc":"moment.parseZone",t="Z");var n="["+e+'("]',s=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",i=t+'[")]';return this.format(n+s+"-MM-DD[T]HH:mm:ss.SSS"+i)},mn.toJSON=function(){return this.isValid()?this.toISOString():null},mn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},mn.unix=function(){return Math.floor(this.valueOf()/1e3)},mn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},mn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},mn.year=Oe,mn.isLeapYear=function(){return De(this.year())},mn.weekYear=function(e){return on.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},mn.isoWeekYear=function(e){return on.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)},mn.quarter=mn.quarters=function(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)},mn.month=Ue,mn.daysInMonth=function(){return Pe(this.year(),this.month())},mn.week=mn.weeks=function(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")},mn.isoWeek=mn.isoWeeks=function(e){var t=Ie(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")},mn.weeksInYear=function(){var e=this.localeData()._week;return Ae(this.year(),e.dow,e.doy)},mn.isoWeeksInYear=function(){return Ae(this.year(),1,4)},mn.date=un,mn.day=mn.days=function(e){if(!this.isValid())return null!=e?this:NaN;var t,n,s=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=e?(t=e,n=this.localeData(),e="string"!=typeof t?t:isNaN(t)?"number"==typeof(t=n.weekdaysParse(t))?t:null:parseInt(t,10),this.add(e-s,"d")):s},mn.weekday=function(e){if(!this.isValid())return null!=e?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return null==e?t:this.add(e-t,"d")},mn.isoWeekday=function(e){if(!this.isValid())return null!=e?this:NaN;if(null==e)return this.day()||7;var t,n,s=(t=e,n=this.localeData(),"string"==typeof t?n.weekdaysParse(t)%7||7:isNaN(t)?null:t);return this.day(this.day()%7?s:s-7)},mn.dayOfYear=function(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?t:this.add(e-t,"d")},mn.hour=mn.hours=nt,mn.minute=mn.minutes=ln,mn.second=mn.seconds=dn,mn.millisecond=mn.milliseconds=fn,mn.utcOffset=function(e,t,n){var s,i=this._offset||0;if(!this.isValid())return null!=e?this:NaN;if(null==e)return this._isUTC?i:Vt(this);if("string"==typeof e){if(null===(e=Nt(re,e)))return this}else Math.abs(e)<16&&!n&&(e*=60);return!this._isUTC&&t&&(s=Vt(this)),this._offset=e,this._isUTC=!0,null!=s&&this.add(s,"m"),i!==e&&(!t||this._changeInProgress?qt(this,jt(e-i,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,c.updateOffset(this,!0),this._changeInProgress=null)),this},mn.utc=function(e){return this.utcOffset(0,e)},mn.local=function(e){return this._isUTC&&(this.utcOffset(0,e),this._isUTC=!1,e&&this.subtract(Vt(this),"m")),this},mn.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var e=Nt(ie,this._i);null!=e?this.utcOffset(e):this.utcOffset(0,!0)}return this},mn.hasAlignedHourOffset=function(e){return!!this.isValid()&&(e=e?bt(e).utcOffset():0,(this.utcOffset()-e)%60==0)},mn.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},mn.isLocal=function(){return!!this.isValid()&&!this._isUTC},mn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},mn.isUtc=Et,mn.isUTC=Et,mn.zoneAbbr=function(){return this._isUTC?"UTC":""},mn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},mn.dates=n("dates accessor is deprecated. Use date instead.",un),mn.months=n("months accessor is deprecated. Use month instead",Ue),mn.years=n("years accessor is deprecated. Use year instead",Oe),mn.zone=n("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()}),mn.isDSTShifted=n("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!l(this._isDSTShifted))return this._isDSTShifted;var e={};if(w(e,this),(e=Ot(e))._a){var t=e._isUTC?y(e._a):bt(e._a);this._isDSTShifted=this.isValid()&&0<a(e._a,t.toArray())}else this._isDSTShifted=!1;return this._isDSTShifted});var yn=P.prototype;function gn(e,t,n,s){var i=ht(),r=y().set(s,t);return i[n](r,e)}function vn(e,t,n){if(h(e)&&(t=e,e=void 0),e=e||"",null!=t)return gn(e,t,n,"month");var s,i=[];for(s=0;s<12;s++)i[s]=gn(e,s,n,"month");return i}function pn(e,t,n,s){t=("boolean"==typeof e?h(t)&&(n=t,t=void 0):(t=e,e=!1,h(n=t)&&(n=t,t=void 0)),t||"");var i,r=ht(),a=e?r._week.dow:0;if(null!=n)return gn(t,(n+a)%7,s,"day");var o=[];for(i=0;i<7;i++)o[i]=gn(t,(i+a)%7,s,"day");return o}yn.calendar=function(e,t,n){var s=this._calendar[e]||this._calendar.sameElse;return b(s)?s.call(t,n):s},yn.longDateFormat=function(e){var t=this._longDateFormat[e],n=this._longDateFormat[e.toUpperCase()];return t||!n?t:(this._longDateFormat[e]=n.replace(/MMMM|MM|DD|dddd/g,function(e){return e.slice(1)}),this._longDateFormat[e])},yn.invalidDate=function(){return this._invalidDate},yn.ordinal=function(e){return this._ordinal.replace("%d",e)},yn.preparse=_n,yn.postformat=_n,yn.relativeTime=function(e,t,n,s){var i=this._relativeTime[n];return b(i)?i(e,t,n,s):i.replace(/%d/i,e)},yn.pastFuture=function(e,t){var n=this._relativeTime[0<e?"future":"past"];return b(n)?n(t):n.replace(/%s/i,t)},yn.set=function(e){var t,n;for(n in e)b(t=e[n])?this[n]=t:this["_"+n]=t;this._config=e,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},yn.months=function(e,t){return e?o(this._months)?this._months[e.month()]:this._months[(this._months.isFormat||We).test(t)?"format":"standalone"][e.month()]:o(this._months)?this._months:this._months.standalone},yn.monthsShort=function(e,t){return e?o(this._monthsShort)?this._monthsShort[e.month()]:this._monthsShort[We.test(t)?"format":"standalone"][e.month()]:o(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},yn.monthsParse=function(e,t,n){var s,i,r;if(this._monthsParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],s=0;s<12;++s)r=y([2e3,s]),this._shortMonthsParse[s]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[s]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===t?-1!==(i=Ye.call(this._shortMonthsParse,a))?i:null:-1!==(i=Ye.call(this._longMonthsParse,a))?i:null:"MMM"===t?-1!==(i=Ye.call(this._shortMonthsParse,a))?i:-1!==(i=Ye.call(this._longMonthsParse,a))?i:null:-1!==(i=Ye.call(this._longMonthsParse,a))?i:-1!==(i=Ye.call(this._shortMonthsParse,a))?i:null}.call(this,e,t,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),s=0;s<12;s++){if(i=y([2e3,s]),n&&!this._longMonthsParse[s]&&(this._longMonthsParse[s]=new RegExp("^"+this.months(i,"").replace(".","")+"$","i"),this._shortMonthsParse[s]=new RegExp("^"+this.monthsShort(i,"").replace(".","")+"$","i")),n||this._monthsParse[s]||(r="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[s]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===t&&this._longMonthsParse[s].test(e))return s;if(n&&"MMM"===t&&this._shortMonthsParse[s].test(e))return s;if(!n&&this._monthsParse[s].test(e))return s}},yn.monthsRegex=function(e){return this._monthsParseExact?(m(this,"_monthsRegex")||Ne.call(this),e?this._monthsStrictRegex:this._monthsRegex):(m(this,"_monthsRegex")||(this._monthsRegex=Le),this._monthsStrictRegex&&e?this._monthsStrictRegex:this._monthsRegex)},yn.monthsShortRegex=function(e){return this._monthsParseExact?(m(this,"_monthsRegex")||Ne.call(this),e?this._monthsShortStrictRegex:this._monthsShortRegex):(m(this,"_monthsShortRegex")||(this._monthsShortRegex=Fe),this._monthsShortStrictRegex&&e?this._monthsShortStrictRegex:this._monthsShortRegex)},yn.week=function(e){return Ie(e,this._week.dow,this._week.doy).week},yn.firstDayOfYear=function(){return this._week.doy},yn.firstDayOfWeek=function(){return this._week.dow},yn.weekdays=function(e,t){var n=o(this._weekdays)?this._weekdays:this._weekdays[e&&!0!==e&&this._weekdays.isFormat.test(t)?"format":"standalone"];return!0===e?je(n,this._week.dow):e?n[e.day()]:n},yn.weekdaysMin=function(e){return!0===e?je(this._weekdaysMin,this._week.dow):e?this._weekdaysMin[e.day()]:this._weekdaysMin},yn.weekdaysShort=function(e){return!0===e?je(this._weekdaysShort,this._week.dow):e?this._weekdaysShort[e.day()]:this._weekdaysShort},yn.weekdaysParse=function(e,t,n){var s,i,r;if(this._weekdaysParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],s=0;s<7;++s)r=y([2e3,1]).day(s),this._minWeekdaysParse[s]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[s]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[s]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===t?-1!==(i=Ye.call(this._weekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:null:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:"dddd"===t?-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:null}.call(this,e,t,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),s=0;s<7;s++){if(i=y([2e3,1]).day(s),n&&!this._fullWeekdaysParse[s]&&(this._fullWeekdaysParse[s]=new RegExp("^"+this.weekdays(i,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[s]=new RegExp("^"+this.weekdaysShort(i,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[s]=new RegExp("^"+this.weekdaysMin(i,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[s]||(r="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[s]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===t&&this._fullWeekdaysParse[s].test(e))return s;if(n&&"ddd"===t&&this._shortWeekdaysParse[s].test(e))return s;if(n&&"dd"===t&&this._minWeekdaysParse[s].test(e))return s;if(!n&&this._weekdaysParse[s].test(e))return s}},yn.weekdaysRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Qe.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(m(this,"_weekdaysRegex")||(this._weekdaysRegex=qe),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)},yn.weekdaysShortRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Qe.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(m(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=Je),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},yn.weekdaysMinRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Qe.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(m(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Be),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},yn.isPM=function(e){return"p"===(e+"").toLowerCase().charAt(0)},yn.meridiem=function(e,t,n){return 11<e?n?"pm":"PM":n?"am":"AM"},ut("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10;return e+(1===D(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th")}}),c.lang=n("moment.lang is deprecated. Use moment.locale instead.",ut),c.langData=n("moment.langData is deprecated. Use moment.localeData instead.",ht);var wn=Math.abs;function Mn(e,t,n,s){var i=jt(t,n);return e._milliseconds+=s*i._milliseconds,e._days+=s*i._days,e._months+=s*i._months,e._bubble()}function kn(e){return e<0?Math.floor(e):Math.ceil(e)}function Sn(e){return 4800*e/146097}function Dn(e){return 146097*e/4800}function Yn(e){return function(){return this.as(e)}}var On=Yn("ms"),Tn=Yn("s"),bn=Yn("m"),xn=Yn("h"),Pn=Yn("d"),Wn=Yn("w"),Cn=Yn("M"),Hn=Yn("Q"),Rn=Yn("y");function Un(e){return function(){return this.isValid()?this._data[e]:NaN}}var Fn=Un("milliseconds"),Ln=Un("seconds"),Nn=Un("minutes"),Gn=Un("hours"),Vn=Un("days"),En=Un("months"),In=Un("years");var An=Math.round,jn={ss:44,s:45,m:45,h:22,d:26,M:11};var Zn=Math.abs;function zn(e){return(0<e)-(e<0)||+e}function $n(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n=Zn(this._milliseconds)/1e3,s=Zn(this._days),i=Zn(this._months);t=S((e=S(n/60))/60),n%=60,e%=60;var r=S(i/12),a=i%=12,o=s,u=t,l=e,h=n?n.toFixed(3).replace(/\.?0+$/,""):"",d=this.asSeconds();if(!d)return"P0D";var c=d<0?"-":"",f=zn(this._months)!==zn(d)?"-":"",m=zn(this._days)!==zn(d)?"-":"",_=zn(this._milliseconds)!==zn(d)?"-":"";return c+"P"+(r?f+r+"Y":"")+(a?f+a+"M":"")+(o?m+o+"D":"")+(u||l||h?"T":"")+(u?_+u+"H":"")+(l?_+l+"M":"")+(h?_+h+"S":"")}var qn=Ht.prototype;return qn.isValid=function(){return this._isValid},qn.abs=function(){var e=this._data;return this._milliseconds=wn(this._milliseconds),this._days=wn(this._days),this._months=wn(this._months),e.milliseconds=wn(e.milliseconds),e.seconds=wn(e.seconds),e.minutes=wn(e.minutes),e.hours=wn(e.hours),e.months=wn(e.months),e.years=wn(e.years),this},qn.add=function(e,t){return Mn(this,e,t,1)},qn.subtract=function(e,t){return Mn(this,e,t,-1)},qn.as=function(e){if(!this.isValid())return NaN;var t,n,s=this._milliseconds;if("month"===(e=H(e))||"quarter"===e||"year"===e)switch(t=this._days+s/864e5,n=this._months+Sn(t),e){case"month":return n;case"quarter":return n/3;case"year":return n/12}else switch(t=this._days+Math.round(Dn(this._months)),e){case"week":return t/7+s/6048e5;case"day":return t+s/864e5;case"hour":return 24*t+s/36e5;case"minute":return 1440*t+s/6e4;case"second":return 86400*t+s/1e3;case"millisecond":return Math.floor(864e5*t)+s;default:throw new Error("Unknown unit "+e)}},qn.asMilliseconds=On,qn.asSeconds=Tn,qn.asMinutes=bn,qn.asHours=xn,qn.asDays=Pn,qn.asWeeks=Wn,qn.asMonths=Cn,qn.asQuarters=Hn,qn.asYears=Rn,qn.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*D(this._months/12):NaN},qn._bubble=function(){var e,t,n,s,i,r=this._milliseconds,a=this._days,o=this._months,u=this._data;return 0<=r&&0<=a&&0<=o||r<=0&&a<=0&&o<=0||(r+=864e5*kn(Dn(o)+a),o=a=0),u.milliseconds=r%1e3,e=S(r/1e3),u.seconds=e%60,t=S(e/60),u.minutes=t%60,n=S(t/60),u.hours=n%24,o+=i=S(Sn(a+=S(n/24))),a-=kn(Dn(i)),s=S(o/12),o%=12,u.days=a,u.months=o,u.years=s,this},qn.clone=function(){return jt(this)},qn.get=function(e){return e=H(e),this.isValid()?this[e+"s"]():NaN},qn.milliseconds=Fn,qn.seconds=Ln,qn.minutes=Nn,qn.hours=Gn,qn.days=Vn,qn.weeks=function(){return S(this.days()/7)},qn.months=En,qn.years=In,qn.humanize=function(e){if(!this.isValid())return this.localeData().invalidDate();var t,n,s,i,r,a,o,u,l,h,d,c=this.localeData(),f=(n=!e,s=c,i=jt(t=this).abs(),r=An(i.as("s")),a=An(i.as("m")),o=An(i.as("h")),u=An(i.as("d")),l=An(i.as("M")),h=An(i.as("y")),(d=r<=jn.ss&&["s",r]||r<jn.s&&["ss",r]||a<=1&&["m"]||a<jn.m&&["mm",a]||o<=1&&["h"]||o<jn.h&&["hh",o]||u<=1&&["d"]||u<jn.d&&["dd",u]||l<=1&&["M"]||l<jn.M&&["MM",l]||h<=1&&["y"]||["yy",h])[2]=n,d[3]=0<+t,d[4]=s,function(e,t,n,s,i){return i.relativeTime(t||1,!!n,e,s)}.apply(null,d));return e&&(f=c.pastFuture(+this,f)),c.postformat(f)},qn.toISOString=$n,qn.toString=$n,qn.toJSON=$n,qn.locale=Xt,qn.localeData=en,qn.toIsoString=n("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",$n),qn.lang=Kt,I("X",0,0,"unix"),I("x",0,0,"valueOf"),ue("x",se),ue("X",/[+-]?\d+(\.\d{1,3})?/),ce("X",function(e,t,n){n._d=new Date(1e3*parseFloat(e,10))}),ce("x",function(e,t,n){n._d=new Date(D(e))}),c.version="2.24.0",e=bt,c.fn=mn,c.min=function(){return Wt("isBefore",[].slice.call(arguments,0))},c.max=function(){return Wt("isAfter",[].slice.call(arguments,0))},c.now=function(){return Date.now?Date.now():+new Date},c.utc=y,c.unix=function(e){return bt(1e3*e)},c.months=function(e,t){return vn(e,t,"months")},c.isDate=d,c.locale=ut,c.invalid=p,c.duration=jt,c.isMoment=k,c.weekdays=function(e,t,n){return pn(e,t,n,"weekdays")},c.parseZone=function(){return bt.apply(null,arguments).parseZone()},c.localeData=ht,c.isDuration=Rt,c.monthsShort=function(e,t){return vn(e,t,"monthsShort")},c.weekdaysMin=function(e,t,n){return pn(e,t,n,"weekdaysMin")},c.defineLocale=lt,c.updateLocale=function(e,t){if(null!=t){var n,s,i=st;null!=(s=ot(e))&&(i=s._config),(n=new P(t=x(i,t))).parentLocale=it[e],it[e]=n,ut(e)}else null!=it[e]&&(null!=it[e].parentLocale?it[e]=it[e].parentLocale:null!=it[e]&&delete it[e]);return it[e]},c.locales=function(){return s(it)},c.weekdaysShort=function(e,t,n){return pn(e,t,n,"weekdaysShort")},c.normalizeUnits=H,c.relativeTimeRounding=function(e){return void 0===e?An:"function"==typeof e&&(An=e,!0)},c.relativeTimeThreshold=function(e,t){return void 0!==jn[e]&&(void 0===t?jn[e]:(jn[e]=t,"s"===e&&(jn.ss=t-1),!0))},c.calendarFormat=function(e,t){var n=e.diff(t,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},c.prototype=mn,c.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},c});
2764
2765/*
2766 Copyright (C) Federico Zivolo 2018
2767 Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT).
2768 */(function(a,b){'object'==typeof exports&&'undefined'!=typeof module?module.exports=b(require('popper.js')):'function'==typeof define&&define.amd?define(['popper.js'],b):a.Tooltip=b(a.Popper)})(this,function(a){'use strict';function b(a){return a&&'[object Function]'==={}.toString.call(a)}a=a&&a.hasOwnProperty('default')?a['default']:a;var c=function(a,b){if(!(a instanceof b))throw new TypeError('Cannot call a class as a function')},d=function(){function a(a,b){for(var c,d=0;d<b.length;d++)c=b[d],c.enumerable=c.enumerable||!1,c.configurable=!0,'value'in c&&(c.writable=!0),Object.defineProperty(a,c.key,c)}return function(b,c,d){return c&&a(b.prototype,c),d&&a(b,d),b}}(),e=Object.assign||function(a){for(var b,c=1;c<arguments.length;c++)for(var d in b=arguments[c],b)Object.prototype.hasOwnProperty.call(b,d)&&(a[d]=b[d]);return a},f={container:!1,delay:0,html:!1,placement:'top',title:'',template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:'hover focus',offset:0,arrowSelector:'.tooltip-arrow, .tooltip__arrow',innerSelector:'.tooltip-inner, .tooltip__inner'},g=function(){function g(a,b){c(this,g),h.call(this),b=e({},f,b),a.jquery&&(a=a[0]),this.reference=a,this.options=b;var d='string'==typeof b.trigger?b.trigger.split(' ').filter(function(a){return-1!==['click','hover','focus'].indexOf(a)}):[];this._isOpen=!1,this._popperOptions={},this._setEventListeners(a,d,b)}return d(g,[{key:'_create',value:function(a,b,c,d){var e=window.document.createElement('div');e.innerHTML=b.trim();var f=e.childNodes[0];f.id='tooltip_'+Math.random().toString(36).substr(2,10),f.setAttribute('aria-hidden','false');var g=e.querySelector(this.options.innerSelector);return this._addTitleContent(a,c,d,g),f}},{key:'_addTitleContent',value:function(a,c,d,e){if(1===c.nodeType||11===c.nodeType)d&&e.appendChild(c);else if(b(c)){var f=c.call(a);d?e.innerHTML=f:e.textContent=f}else d?e.innerHTML=c:e.textContent=c}},{key:'_show',value:function(b,c){if(this._isOpen&&!this._isOpening)return this;if(this._isOpen=!0,this._tooltipNode)return this._tooltipNode.style.visibility='visible',this._tooltipNode.setAttribute('aria-hidden','false'),this.popperInstance.update(),this;var d=b.getAttribute('title')||c.title;if(!d)return this;var f=this._create(b,c.template,d,c.html);b.setAttribute('aria-describedby',f.id);var g=this._findContainer(c.container,b);return this._append(f,g),this._popperOptions=e({},c.popperOptions,{placement:c.placement}),this._popperOptions.modifiers=e({},this._popperOptions.modifiers,{arrow:{element:this.options.arrowSelector},offset:{offset:c.offset}}),c.boundariesElement&&(this._popperOptions.modifiers.preventOverflow={boundariesElement:c.boundariesElement}),this.popperInstance=new a(b,f,this._popperOptions),this._tooltipNode=f,this}},{key:'_hide',value:function(){return this._isOpen?(this._isOpen=!1,this._tooltipNode.style.visibility='hidden',this._tooltipNode.setAttribute('aria-hidden','true'),this):this}},{key:'_dispose',value:function(){var a=this;return this._events.forEach(function(b){var c=b.func,d=b.event;a.reference.removeEventListener(d,c)}),this._events=[],this._tooltipNode&&(this._hide(),this.popperInstance.destroy(),!this.popperInstance.options.removeOnDestroy&&(this._tooltipNode.parentNode.removeChild(this._tooltipNode),this._tooltipNode=null)),this}},{key:'_findContainer',value:function(a,b){return'string'==typeof a?a=window.document.querySelector(a):!1===a&&(a=b.parentNode),a}},{key:'_append',value:function(a,b){b.appendChild(a)}},{key:'_setEventListeners',value:function(a,b,c){var d=this,e=[],f=[];b.forEach(function(a){'hover'===a?(e.push('mouseenter'),f.push('mouseleave')):'focus'===a?(e.push('focus'),f.push('blur')):'click'===a?(e.push('click'),f.push('click')):void 0}),e.forEach(function(b){var e=function(b){!0===d._isOpening||(b.usedByTooltip=!0,d._scheduleShow(a,c.delay,c,b))};d._events.push({event:b,func:e}),a.addEventListener(b,e)}),f.forEach(function(b){var f=function(b){!0===b.usedByTooltip||d._scheduleHide(a,c.delay,c,b)};d._events.push({event:b,func:f}),a.addEventListener(b,f),'click'===b&&c.closeOnClickOutside&&document.addEventListener('mousedown',function(b){if(d._isOpening){var c=d.popperInstance.popper;a.contains(b.target)||c.contains(b.target)||f(b)}},!0)})}},{key:'_scheduleShow',value:function(a,b,c){var d=this;this._isOpening=!0;var e=b&&b.show||b||0;this._showTimeout=window.setTimeout(function(){return d._show(a,c)},e)}},{key:'_scheduleHide',value:function(a,b,c,d){var e=this;this._isOpening=!1;var f=b&&b.hide||b||0;window.setTimeout(function(){if((window.clearTimeout(e._showTimeout),!1!==e._isOpen)&&document.body.contains(e._tooltipNode)){if('mouseleave'===d.type){var f=e._setTooltipNodeEvent(d,a,b,c);if(f)return}e._hide(a,c)}},f)}}
2768,{key:'_updateTitleContent',value:function(a){if('undefined'==typeof this._tooltipNode)return void('undefined'!=typeof this.options.title&&(this.options.title=a));var b=this._tooltipNode.parentNode.querySelector(this.options.innerSelector);this._clearTitleContent(b,this.options.html,this.reference.getAttribute('title')||this.options.title),this._addTitleContent(this.reference,a,this.options.html,b),this.options.title=a,this.popperInstance.update()}},{key:'_clearTitleContent',value:function(a,b,c){1===c.nodeType||11===c.nodeType?b&&a.removeChild(c):b?a.innerHTML='':a.textContent=''}}]),g}(),h=function(){var a=this;this.show=function(){return a._show(a.reference,a.options)},this.hide=function(){return a._hide()},this.dispose=function(){return a._dispose()},this.toggle=function(){return a._isOpen?a.hide():a.show()},this.updateTitleContent=function(b){return a._updateTitleContent(b)},this._events=[],this._setTooltipNodeEvent=function(b,c,d,e){var f=b.relatedreference||b.toElement||b.relatedTarget;return!!a._tooltipNode.contains(f)&&(a._tooltipNode.addEventListener(b.type,function d(f){var g=f.relatedreference||f.toElement||f.relatedTarget;a._tooltipNode.removeEventListener(b.type,d),c.contains(g)||a._scheduleHide(c,e.delay,e,f)}),!0)}};return g});
2769//# sourceMappingURL=tooltip.min.js.map
2770
2771/*!
2772 * perfect-scrollbar v1.4.0
2773 * (c) 2018 Hyunje Jun
2774 * @license MIT
2775 */
2776(function (global, factory) {
2777	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
2778	typeof define === 'function' && define.amd ? define(factory) :
2779	(global.PerfectScrollbar = factory());
2780}(this, (function () { 'use strict';
2781
2782function get(element) {
2783  return getComputedStyle(element);
2784}
2785
2786function set(element, obj) {
2787  for (var key in obj) {
2788    var val = obj[key];
2789    if (typeof val === 'number') {
2790      val = val + "px";
2791    }
2792    element.style[key] = val;
2793  }
2794  return element;
2795}
2796
2797function div(className) {
2798  var div = document.createElement('div');
2799  div.className = className;
2800  return div;
2801}
2802
2803var elMatches =
2804  typeof Element !== 'undefined' &&
2805  (Element.prototype.matches ||
2806    Element.prototype.webkitMatchesSelector ||
2807    Element.prototype.mozMatchesSelector ||
2808    Element.prototype.msMatchesSelector);
2809
2810function matches(element, query) {
2811  if (!elMatches) {
2812    throw new Error('No element matching method supported');
2813  }
2814
2815  return elMatches.call(element, query);
2816}
2817
2818function remove(element) {
2819  if (element.remove) {
2820    element.remove();
2821  } else {
2822    if (element.parentNode) {
2823      element.parentNode.removeChild(element);
2824    }
2825  }
2826}
2827
2828function queryChildren(element, selector) {
2829  return Array.prototype.filter.call(element.children, function (child) { return matches(child, selector); }
2830  );
2831}
2832
2833var cls = {
2834  main: 'ps',
2835  element: {
2836    thumb: function (x) { return ("ps__thumb-" + x); },
2837    rail: function (x) { return ("ps__rail-" + x); },
2838    consuming: 'ps__child--consume',
2839  },
2840  state: {
2841    focus: 'ps--focus',
2842    clicking: 'ps--clicking',
2843    active: function (x) { return ("ps--active-" + x); },
2844    scrolling: function (x) { return ("ps--scrolling-" + x); },
2845  },
2846};
2847
2848/*
2849 * Helper methods
2850 */
2851var scrollingClassTimeout = { x: null, y: null };
2852
2853function addScrollingClass(i, x) {
2854  var classList = i.element.classList;
2855  var className = cls.state.scrolling(x);
2856
2857  if (classList.contains(className)) {
2858    clearTimeout(scrollingClassTimeout[x]);
2859  } else {
2860    classList.add(className);
2861  }
2862}
2863
2864function removeScrollingClass(i, x) {
2865  scrollingClassTimeout[x] = setTimeout(
2866    function () { return i.isAlive && i.element.classList.remove(cls.state.scrolling(x)); },
2867    i.settings.scrollingThreshold
2868  );
2869}
2870
2871function setScrollingClassInstantly(i, x) {
2872  addScrollingClass(i, x);
2873  removeScrollingClass(i, x);
2874}
2875
2876var EventElement = function EventElement(element) {
2877  this.element = element;
2878  this.handlers = {};
2879};
2880
2881var prototypeAccessors = { isEmpty: { configurable: true } };
2882
2883EventElement.prototype.bind = function bind (eventName, handler) {
2884  if (typeof this.handlers[eventName] === 'undefined') {
2885    this.handlers[eventName] = [];
2886  }
2887  this.handlers[eventName].push(handler);
2888  this.element.addEventListener(eventName, handler, false);
2889};
2890
2891EventElement.prototype.unbind = function unbind (eventName, target) {
2892    var this$1 = this;
2893
2894  this.handlers[eventName] = this.handlers[eventName].filter(function (handler) {
2895    if (target && handler !== target) {
2896      return true;
2897    }
2898    this$1.element.removeEventListener(eventName, handler, false);
2899    return false;
vendor: 5,047 bytes, lines 2900-3105
2900  });
2901};
2902
2903EventElement.prototype.unbindAll = function unbindAll () {
2904    var this$1 = this;
2905
2906  for (var name in this$1.handlers) {
2907    this$1.unbind(name);
2908  }
2909};
2910
2911prototypeAccessors.isEmpty.get = function () {
2912    var this$1 = this;
2913
2914  return Object.keys(this.handlers).every(
2915    function (key) { return this$1.handlers[key].length === 0; }
2916  );
2917};
2918
2919Object.defineProperties( EventElement.prototype, prototypeAccessors );
2920
2921var EventManager = function EventManager() {
2922  this.eventElements = [];
2923};
2924
2925EventManager.prototype.eventElement = function eventElement (element) {
2926  var ee = this.eventElements.filter(function (ee) { return ee.element === element; })[0];
2927  if (!ee) {
2928    ee = new EventElement(element);
2929    this.eventElements.push(ee);
2930  }
2931  return ee;
2932};
2933
2934EventManager.prototype.bind = function bind (element, eventName, handler) {
2935  this.eventElement(element).bind(eventName, handler);
2936};
2937
2938EventManager.prototype.unbind = function unbind (element, eventName, handler) {
2939  var ee = this.eventElement(element);
2940  ee.unbind(eventName, handler);
2941
2942  if (ee.isEmpty) {
2943    // remove
2944    this.eventElements.splice(this.eventElements.indexOf(ee), 1);
2945  }
2946};
2947
2948EventManager.prototype.unbindAll = function unbindAll () {
2949  this.eventElements.forEach(function (e) { return e.unbindAll(); });
2950  this.eventElements = [];
2951};
2952
2953EventManager.prototype.once = function once (element, eventName, handler) {
2954  var ee = this.eventElement(element);
2955  var onceHandler = function (evt) {
2956    ee.unbind(eventName, onceHandler);
2957    handler(evt);
2958  };
2959  ee.bind(eventName, onceHandler);
2960};
2961
2962function createEvent(name) {
2963  if (typeof window.CustomEvent === 'function') {
2964    return new CustomEvent(name);
2965  } else {
2966    var evt = document.createEvent('CustomEvent');
2967    evt.initCustomEvent(name, false, false, undefined);
2968    return evt;
2969  }
2970}
2971
2972var processScrollDiff = function(
2973  i,
2974  axis,
2975  diff,
2976  useScrollingClass,
2977  forceFireReachEvent
2978) {
2979  if ( useScrollingClass === void 0 ) useScrollingClass = true;
2980  if ( forceFireReachEvent === void 0 ) forceFireReachEvent = false;
2981
2982  var fields;
2983  if (axis === 'top') {
2984    fields = [
2985      'contentHeight',
2986      'containerHeight',
2987      'scrollTop',
2988      'y',
2989      'up',
2990      'down' ];
2991  } else if (axis === 'left') {
2992    fields = [
2993      'contentWidth',
2994      'containerWidth',
2995      'scrollLeft',
2996      'x',
2997      'left',
2998      'right' ];
2999  } else {
3000    throw new Error('A proper axis should be provided');
3001  }
3002
3003  processScrollDiff$1(i, diff, fields, useScrollingClass, forceFireReachEvent);
3004};
3005
3006function processScrollDiff$1(
3007  i,
3008  diff,
3009  ref,
3010  useScrollingClass,
3011  forceFireReachEvent
3012) {
3013  var contentHeight = ref[0];
3014  var containerHeight = ref[1];
3015  var scrollTop = ref[2];
3016  var y = ref[3];
3017  var up = ref[4];
3018  var down = ref[5];
3019  if ( useScrollingClass === void 0 ) useScrollingClass = true;
3020  if ( forceFireReachEvent === void 0 ) forceFireReachEvent = false;
3021
3022  var element = i.element;
3023
3024  // reset reach
3025  i.reach[y] = null;
3026
3027  // 1 for subpixel rounding
3028  if (element[scrollTop] < 1) {
3029    i.reach[y] = 'start';
3030  }
3031
3032  // 1 for subpixel rounding
3033  if (element[scrollTop] > i[contentHeight] - i[containerHeight] - 1) {
3034    i.reach[y] = 'end';
3035  }
3036
3037  if (diff) {
3038    element.dispatchEvent(createEvent(("ps-scroll-" + y)));
3039
3040    if (diff < 0) {
3041      element.dispatchEvent(createEvent(("ps-scroll-" + up)));
3042    } else if (diff > 0) {
3043      element.dispatchEvent(createEvent(("ps-scroll-" + down)));
3044    }
3045
3046    if (useScrollingClass) {
3047      setScrollingClassInstantly(i, y);
3048    }
3049  }
3050
3051  if (i.reach[y] && (diff || forceFireReachEvent)) {
3052    element.dispatchEvent(createEvent(("ps-" + y + "-reach-" + (i.reach[y]))));
3053  }
3054}
3055
3056function toInt(x) {
3057  return parseInt(x, 10) || 0;
3058}
3059
3060function isEditable(el) {
3061  return (
3062    matches(el, 'input,[contenteditable]') ||
3063    matches(el, 'select,[contenteditable]') ||
3064    matches(el, 'textarea,[contenteditable]') ||
3065    matches(el, 'button,[contenteditable]')
3066  );
3067}
3068
3069function outerWidth(element) {
3070  var styles = get(element);
3071  return (
3072    toInt(styles.width) +
3073    toInt(styles.paddingLeft) +
3074    toInt(styles.paddingRight) +
3075    toInt(styles.borderLeftWidth) +
3076    toInt(styles.borderRightWidth)
3077  );
3078}
3079
3080var env = {
3081  isWebKit:
3082    typeof document !== 'undefined' &&
3083    'WebkitAppearance' in document.documentElement.style,
3084  supportsTouch:
3085    typeof window !== 'undefined' &&
3086    ('ontouchstart' in window ||
3087      (window.DocumentTouch && document instanceof window.DocumentTouch)),
3088  supportsIePointer:
3089    typeof navigator !== 'undefined' && navigator.msMaxTouchPoints,
3090  isChrome:
3091    typeof navigator !== 'undefined' &&
3092    /Chrome/i.test(navigator && navigator.userAgent),
3093};
3094
3095var updateGeometry = function(i) {
3096  var element = i.element;
3097  var roundedScrollTop = Math.floor(element.scrollTop);
3098
3099  i.containerWidth = element.clientWidth;
3100  i.containerHeight = element.clientHeight;
3101  i.contentWidth = element.scrollWidth;
3102  i.contentHeight = element.scrollHeight;
3103
3104  if (!element.contains(i.scrollbarXRail)) {
3105    // clean up and append
vendor: 4,424 bytes, lines 3106-3257
3106    queryChildren(element, cls.element.rail('x')).forEach(function (el) { return remove(el); }
3107    );
3108    element.appendChild(i.scrollbarXRail);
3109  }
3110  if (!element.contains(i.scrollbarYRail)) {
3111    // clean up and append
3112    queryChildren(element, cls.element.rail('y')).forEach(function (el) { return remove(el); }
3113    );
3114    element.appendChild(i.scrollbarYRail);
3115  }
3116
3117  if (
3118    !i.settings.suppressScrollX &&
3119    i.containerWidth + i.settings.scrollXMarginOffset < i.contentWidth
3120  ) {
3121    i.scrollbarXActive = true;
3122    i.railXWidth = i.containerWidth - i.railXMarginWidth;
3123    i.railXRatio = i.containerWidth / i.railXWidth;
3124    i.scrollbarXWidth = getThumbSize(
3125      i,
3126      toInt(i.railXWidth * i.containerWidth / i.contentWidth)
3127    );
3128    i.scrollbarXLeft = toInt(
3129      (i.negativeScrollAdjustment + element.scrollLeft) *
3130        (i.railXWidth - i.scrollbarXWidth) /
3131        (i.contentWidth - i.containerWidth)
3132    );
3133  } else {
3134    i.scrollbarXActive = false;
3135  }
3136
3137  if (
3138    !i.settings.suppressScrollY &&
3139    i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight
3140  ) {
3141    i.scrollbarYActive = true;
3142    i.railYHeight = i.containerHeight - i.railYMarginHeight;
3143    i.railYRatio = i.containerHeight / i.railYHeight;
3144    i.scrollbarYHeight = getThumbSize(
3145      i,
3146      toInt(i.railYHeight * i.containerHeight / i.contentHeight)
3147    );
3148    i.scrollbarYTop = toInt(
3149      roundedScrollTop *
3150        (i.railYHeight - i.scrollbarYHeight) /
3151        (i.contentHeight - i.containerHeight)
3152    );
3153  } else {
3154    i.scrollbarYActive = false;
3155  }
3156
3157  if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) {
3158    i.scrollbarXLeft = i.railXWidth - i.scrollbarXWidth;
3159  }
3160  if (i.scrollbarYTop >= i.railYHeight - i.scrollbarYHeight) {
3161    i.scrollbarYTop = i.railYHeight - i.scrollbarYHeight;
3162  }
3163
3164  updateCss(element, i);
3165
3166  if (i.scrollbarXActive) {
3167    element.classList.add(cls.state.active('x'));
3168  } else {
3169    element.classList.remove(cls.state.active('x'));
3170    i.scrollbarXWidth = 0;
3171    i.scrollbarXLeft = 0;
3172    element.scrollLeft = 0;
3173  }
3174  if (i.scrollbarYActive) {
3175    element.classList.add(cls.state.active('y'));
3176  } else {
3177    element.classList.remove(cls.state.active('y'));
3178    i.scrollbarYHeight = 0;
3179    i.scrollbarYTop = 0;
3180    element.scrollTop = 0;
3181  }
3182};
3183
3184function getThumbSize(i, thumbSize) {
3185  if (i.settings.minScrollbarLength) {
3186    thumbSize = Math.max(thumbSize, i.settings.minScrollbarLength);
3187  }
3188  if (i.settings.maxScrollbarLength) {
3189    thumbSize = Math.min(thumbSize, i.settings.maxScrollbarLength);
3190  }
3191  return thumbSize;
3192}
3193
3194function updateCss(element, i) {
3195  var xRailOffset = { width: i.railXWidth };
3196  var roundedScrollTop = Math.floor(element.scrollTop);
3197
3198  if (i.isRtl) {
3199    xRailOffset.left =
3200      i.negativeScrollAdjustment +
3201      element.scrollLeft +
3202      i.containerWidth -
3203      i.contentWidth;
3204  } else {
3205    xRailOffset.left = element.scrollLeft;
3206  }
3207  if (i.isScrollbarXUsingBottom) {
3208    xRailOffset.bottom = i.scrollbarXBottom - roundedScrollTop;
3209  } else {
3210    xRailOffset.top = i.scrollbarXTop + roundedScrollTop;
3211  }
3212  set(i.scrollbarXRail, xRailOffset);
3213
3214  var yRailOffset = { top: roundedScrollTop, height: i.railYHeight };
3215  if (i.isScrollbarYUsingRight) {
3216    if (i.isRtl) {
3217      yRailOffset.right =
3218        i.contentWidth -
3219        (i.negativeScrollAdjustment + element.scrollLeft) -
3220        i.scrollbarYRight -
3221        i.scrollbarYOuterWidth;
3222    } else {
3223      yRailOffset.right = i.scrollbarYRight - element.scrollLeft;
3224    }
3225  } else {
3226    if (i.isRtl) {
3227      yRailOffset.left =
3228        i.negativeScrollAdjustment +
3229        element.scrollLeft +
3230        i.containerWidth * 2 -
3231        i.contentWidth -
3232        i.scrollbarYLeft -
3233        i.scrollbarYOuterWidth;
3234    } else {
3235      yRailOffset.left = i.scrollbarYLeft + element.scrollLeft;
3236    }
3237  }
3238  set(i.scrollbarYRail, yRailOffset);
3239
3240  set(i.scrollbarX, {
3241    left: i.scrollbarXLeft,
3242    width: i.scrollbarXWidth - i.railBorderXWidth,
3243  });
3244  set(i.scrollbarY, {
3245    top: i.scrollbarYTop,
3246    height: i.scrollbarYHeight - i.railBorderYWidth,
3247  });
3248}
3249
3250var clickRail = function(i) {
3251  i.event.bind(i.scrollbarY, 'mousedown', function (e) { return e.stopPropagation(); });
3252  i.event.bind(i.scrollbarYRail, 'mousedown', function (e) {
3253    var positionTop =
3254      e.pageY -
3255      window.pageYOffset -
3256      i.scrollbarYRail.getBoundingClientRect().top;
3257    var direction = positionTop >
vendor: 17,708 bytes, lines 3257-3936
3257 i.scrollbarYTop ? 1 : -1;
3258
3259    i.element.scrollTop += direction * i.containerHeight;
3260    updateGeometry(i);
3261
3262    e.stopPropagation();
3263  });
3264
3265  i.event.bind(i.scrollbarX, 'mousedown', function (e) { return e.stopPropagation(); });
3266  i.event.bind(i.scrollbarXRail, 'mousedown', function (e) {
3267    var positionLeft =
3268      e.pageX -
3269      window.pageXOffset -
3270      i.scrollbarXRail.getBoundingClientRect().left;
3271    var direction = positionLeft > i.scrollbarXLeft ? 1 : -1;
3272
3273    i.element.scrollLeft += direction * i.containerWidth;
3274    updateGeometry(i);
3275
3276    e.stopPropagation();
3277  });
3278};
3279
3280var dragThumb = function(i) {
3281  bindMouseScrollHandler(i, [
3282    'containerWidth',
3283    'contentWidth',
3284    'pageX',
3285    'railXWidth',
3286    'scrollbarX',
3287    'scrollbarXWidth',
3288    'scrollLeft',
3289    'x',
3290    'scrollbarXRail' ]);
3291  bindMouseScrollHandler(i, [
3292    'containerHeight',
3293    'contentHeight',
3294    'pageY',
3295    'railYHeight',
3296    'scrollbarY',
3297    'scrollbarYHeight',
3298    'scrollTop',
3299    'y',
3300    'scrollbarYRail' ]);
3301};
3302
3303function bindMouseScrollHandler(
3304  i,
3305  ref
3306) {
3307  var containerHeight = ref[0];
3308  var contentHeight = ref[1];
3309  var pageY = ref[2];
3310  var railYHeight = ref[3];
3311  var scrollbarY = ref[4];
3312  var scrollbarYHeight = ref[5];
3313  var scrollTop = ref[6];
3314  var y = ref[7];
3315  var scrollbarYRail = ref[8];
3316
3317  var element = i.element;
3318
3319  var startingScrollTop = null;
3320  var startingMousePageY = null;
3321  var scrollBy = null;
3322
3323  function mouseMoveHandler(e) {
3324    element[scrollTop] =
3325      startingScrollTop + scrollBy * (e[pageY] - startingMousePageY);
3326    addScrollingClass(i, y);
3327    updateGeometry(i);
3328
3329    e.stopPropagation();
3330    e.preventDefault();
3331  }
3332
3333  function mouseUpHandler() {
3334    removeScrollingClass(i, y);
3335    i[scrollbarYRail].classList.remove(cls.state.clicking);
3336    i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
3337  }
3338
3339  i.event.bind(i[scrollbarY], 'mousedown', function (e) {
3340    startingScrollTop = element[scrollTop];
3341    startingMousePageY = e[pageY];
3342    scrollBy =
3343      (i[contentHeight] - i[containerHeight]) /
3344      (i[railYHeight] - i[scrollbarYHeight]);
3345
3346    i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
3347    i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
3348
3349    i[scrollbarYRail].classList.add(cls.state.clicking);
3350
3351    e.stopPropagation();
3352    e.preventDefault();
3353  });
3354}
3355
3356var keyboard = function(i) {
3357  var element = i.element;
3358
3359  var elementHovered = function () { return matches(element, ':hover'); };
3360  var scrollbarFocused = function () { return matches(i.scrollbarX, ':focus') || matches(i.scrollbarY, ':focus'); };
3361
3362  function shouldPreventDefault(deltaX, deltaY) {
3363    var scrollTop = Math.floor(element.scrollTop);
3364    if (deltaX === 0) {
3365      if (!i.scrollbarYActive) {
3366        return false;
3367      }
3368      if (
3369        (scrollTop === 0 && deltaY > 0) ||
3370        (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)
3371      ) {
3372        return !i.settings.wheelPropagation;
3373      }
3374    }
3375
3376    var scrollLeft = element.scrollLeft;
3377    if (deltaY === 0) {
3378      if (!i.scrollbarXActive) {
3379        return false;
3380      }
3381      if (
3382        (scrollLeft === 0 && deltaX < 0) ||
3383        (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)
3384      ) {
3385        return !i.settings.wheelPropagation;
3386      }
3387    }
3388    return true;
3389  }
3390
3391  i.event.bind(i.ownerDocument, 'keydown', function (e) {
3392    if (
3393      (e.isDefaultPrevented && e.isDefaultPrevented()) ||
3394      e.defaultPrevented
3395    ) {
3396      return;
3397    }
3398
3399    if (!elementHovered() && !scrollbarFocused()) {
3400      return;
3401    }
3402
3403    var activeElement = document.activeElement
3404      ? document.activeElement
3405      : i.ownerDocument.activeElement;
3406    if (activeElement) {
3407      if (activeElement.tagName === 'IFRAME') {
3408        activeElement = activeElement.contentDocument.activeElement;
3409      } else {
3410        // go deeper if element is a webcomponent
3411        while (activeElement.shadowRoot) {
3412          activeElement = activeElement.shadowRoot.activeElement;
3413        }
3414      }
3415      if (isEditable(activeElement)) {
3416        return;
3417      }
3418    }
3419
3420    var deltaX = 0;
3421    var deltaY = 0;
3422
3423    switch (e.which) {
3424      case 37: // left
3425        if (e.metaKey) {
3426          deltaX = -i.contentWidth;
3427        } else if (e.altKey) {
3428          deltaX = -i.containerWidth;
3429        } else {
3430          deltaX = -30;
3431        }
3432        break;
3433      case 38: // up
3434        if (e.metaKey) {
3435          deltaY = i.contentHeight;
3436        } else if (e.altKey) {
3437          deltaY = i.containerHeight;
3438        } else {
3439          deltaY = 30;
3440        }
3441        break;
3442      case 39: // right
3443        if (e.metaKey) {
3444          deltaX = i.contentWidth;
3445        } else if (e.altKey) {
3446          deltaX = i.containerWidth;
3447        } else {
3448          deltaX = 30;
3449        }
3450        break;
3451      case 40: // down
3452        if (e.metaKey) {
3453          deltaY = -i.contentHeight;
3454        } else if (e.altKey) {
3455          deltaY = -i.containerHeight;
3456        } else {
3457          deltaY = -30;
3458        }
3459        break;
3460      case 32: // space bar
3461        if (e.shiftKey) {
3462          deltaY = i.containerHeight;
3463        } else {
3464          deltaY = -i.containerHeight;
3465        }
3466        break;
3467      case 33: // page up
3468        deltaY = i.containerHeight;
3469        break;
3470      case 34: // page down
3471        deltaY = -i.containerHeight;
3472        break;
3473      case 36: // home
3474        deltaY = i.contentHeight;
3475        break;
3476      case 35: // end
3477        deltaY = -i.contentHeight;
3478        break;
3479      default:
3480        return;
3481    }
3482
3483    if (i.settings.suppressScrollX && deltaX !== 0) {
3484      return;
3485    }
3486    if (i.settings.suppressScrollY && deltaY !== 0) {
3487      return;
3488    }
3489
3490    element.scrollTop -= deltaY;
3491    element.scrollLeft += deltaX;
3492    updateGeometry(i);
3493
3494    if (shouldPreventDefault(deltaX, deltaY)) {
3495      e.preventDefault();
3496    }
3497  });
3498};
3499
3500var wheel = function(i) {
3501  var element = i.element;
3502
3503  function shouldPreventDefault(deltaX, deltaY) {
3504    var roundedScrollTop = Math.floor(element.scrollTop);
3505    var isTop = element.scrollTop === 0;
3506    var isBottom =
3507      roundedScrollTop + element.offsetHeight === element.scrollHeight;
3508    var isLeft = element.scrollLeft === 0;
3509    var isRight =
3510      element.scrollLeft + element.offsetWidth === element.scrollWidth;
3511
3512    var hitsBound;
3513
3514    // pick axis with primary direction
3515    if (Math.abs(deltaY) > Math.abs(deltaX)) {
3516      hitsBound = isTop || isBottom;
3517    } else {
3518      hitsBound = isLeft || isRight;
3519    }
3520
3521    return hitsBound ? !i.settings.wheelPropagation : true;
3522  }
3523
3524  function getDeltaFromEvent(e) {
3525    var deltaX = e.deltaX;
3526    var deltaY = -1 * e.deltaY;
3527
3528    if (typeof deltaX === 'undefined' || typeof deltaY === 'undefined') {
3529      // OS X Safari
3530      deltaX = -1 * e.wheelDeltaX / 6;
3531      deltaY = e.wheelDeltaY / 6;
3532    }
3533
3534    if (e.deltaMode && e.deltaMode === 1) {
3535      // Firefox in deltaMode 1: Line scrolling
3536      deltaX *= 10;
3537      deltaY *= 10;
3538    }
3539
3540    if (deltaX !== deltaX && deltaY !== deltaY /* NaN checks */) {
3541      // IE in some mouse drivers
3542      deltaX = 0;
3543      deltaY = e.wheelDelta;
3544    }
3545
3546    if (e.shiftKey) {
3547      // reverse axis with shift key
3548      return [-deltaY, -deltaX];
3549    }
3550    return [deltaX, deltaY];
3551  }
3552
3553  function shouldBeConsumedByChild(target, deltaX, deltaY) {
3554    // FIXME: this is a workaround for <select> issue in FF and IE #571
3555    if (!env.isWebKit && element.querySelector('select:focus')) {
3556      return true;
3557    }
3558
3559    if (!element.contains(target)) {
3560      return false;
3561    }
3562
3563    var cursor = target;
3564
3565    while (cursor && cursor !== element) {
3566      if (cursor.classList.contains(cls.element.consuming)) {
3567        return true;
3568      }
3569
3570      var style = get(cursor);
3571      var overflow = [style.overflow, style.overflowX, style.overflowY].join(
3572        ''
3573      );
3574
3575      // if scrollable
3576      if (overflow.match(/(scroll|auto)/)) {
3577        var maxScrollTop = cursor.scrollHeight - cursor.clientHeight;
3578        if (maxScrollTop > 0) {
3579          if (
3580            !(cursor.scrollTop === 0 && deltaY > 0) &&
3581            !(cursor.scrollTop === maxScrollTop && deltaY < 0)
3582          ) {
3583            return true;
3584          }
3585        }
3586        var maxScrollLeft = cursor.scrollWidth - cursor.clientWidth;
3587        if (maxScrollLeft > 0) {
3588          if (
3589            !(cursor.scrollLeft === 0 && deltaX < 0) &&
3590            !(cursor.scrollLeft === maxScrollLeft && deltaX > 0)
3591          ) {
3592            return true;
3593          }
3594        }
3595      }
3596
3597      cursor = cursor.parentNode;
3598    }
3599
3600    return false;
3601  }
3602
3603  function mousewheelHandler(e) {
3604    var ref = getDeltaFromEvent(e);
3605    var deltaX = ref[0];
3606    var deltaY = ref[1];
3607
3608    if (shouldBeConsumedByChild(e.target, deltaX, deltaY)) {
3609      return;
3610    }
3611
3612    var shouldPrevent = false;
3613    if (!i.settings.useBothWheelAxes) {
3614      // deltaX will only be used for horizontal scrolling and deltaY will
3615      // only be used for vertical scrolling - this is the default
3616      element.scrollTop -= deltaY * i.settings.wheelSpeed;
3617      element.scrollLeft += deltaX * i.settings.wheelSpeed;
3618    } else if (i.scrollbarYActive && !i.scrollbarXActive) {
3619      // only vertical scrollbar is active and useBothWheelAxes option is
3620      // active, so let's scroll vertical bar using both mouse wheel axes
3621      if (deltaY) {
3622        element.scrollTop -= deltaY * i.settings.wheelSpeed;
3623      } else {
3624        element.scrollTop += deltaX * i.settings.wheelSpeed;
3625      }
3626      shouldPrevent = true;
3627    } else if (i.scrollbarXActive && !i.scrollbarYActive) {
3628      // useBothWheelAxes and only horizontal bar is active, so use both
3629      // wheel axes for horizontal bar
3630      if (deltaX) {
3631        element.scrollLeft += deltaX * i.settings.wheelSpeed;
3632      } else {
3633        element.scrollLeft -= deltaY * i.settings.wheelSpeed;
3634      }
3635      shouldPrevent = true;
3636    }
3637
3638    updateGeometry(i);
3639
3640    shouldPrevent = shouldPrevent || shouldPreventDefault(deltaX, deltaY);
3641    if (shouldPrevent && !e.ctrlKey) {
3642      e.stopPropagation();
3643      e.preventDefault();
3644    }
3645  }
3646
3647  if (typeof window.onwheel !== 'undefined') {
3648    i.event.bind(element, 'wheel', mousewheelHandler);
3649  } else if (typeof window.onmousewheel !== 'undefined') {
3650    i.event.bind(element, 'mousewheel', mousewheelHandler);
3651  }
3652};
3653
3654var touch = function(i) {
3655  if (!env.supportsTouch && !env.supportsIePointer) {
3656    return;
3657  }
3658
3659  var element = i.element;
3660
3661  function shouldPrevent(deltaX, deltaY) {
3662    var scrollTop = Math.floor(element.scrollTop);
3663    var scrollLeft = element.scrollLeft;
3664    var magnitudeX = Math.abs(deltaX);
3665    var magnitudeY = Math.abs(deltaY);
3666
3667    if (magnitudeY > magnitudeX) {
3668      // user is perhaps trying to swipe up/down the page
3669
3670      if (
3671        (deltaY < 0 && scrollTop === i.contentHeight - i.containerHeight) ||
3672        (deltaY > 0 && scrollTop === 0)
3673      ) {
3674        // set prevent for mobile Chrome refresh
3675        return window.scrollY === 0 && deltaY > 0 && env.isChrome;
3676      }
3677    } else if (magnitudeX > magnitudeY) {
3678      // user is perhaps trying to swipe left/right across the page
3679
3680      if (
3681        (deltaX < 0 && scrollLeft === i.contentWidth - i.containerWidth) ||
3682        (deltaX > 0 && scrollLeft === 0)
3683      ) {
3684        return true;
3685      }
3686    }
3687
3688    return true;
3689  }
3690
3691  function applyTouchMove(differenceX, differenceY) {
3692    element.scrollTop -= differenceY;
3693    element.scrollLeft -= differenceX;
3694
3695    updateGeometry(i);
3696  }
3697
3698  var startOffset = {};
3699  var startTime = 0;
3700  var speed = {};
3701  var easingLoop = null;
3702
3703  function getTouch(e) {
3704    if (e.targetTouches) {
3705      return e.targetTouches[0];
3706    } else {
3707      // Maybe IE pointer
3708      return e;
3709    }
3710  }
3711
3712  function shouldHandle(e) {
3713    if (e.pointerType && e.pointerType === 'pen' && e.buttons === 0) {
3714      return false;
3715    }
3716    if (e.targetTouches && e.targetTouches.length === 1) {
3717      return true;
3718    }
3719    if (
3720      e.pointerType &&
3721      e.pointerType !== 'mouse' &&
3722      e.pointerType !== e.MSPOINTER_TYPE_MOUSE
3723    ) {
3724      return true;
3725    }
3726    return false;
3727  }
3728
3729  function touchStart(e) {
3730    if (!shouldHandle(e)) {
3731      return;
3732    }
3733
3734    var touch = getTouch(e);
3735
3736    startOffset.pageX = touch.pageX;
3737    startOffset.pageY = touch.pageY;
3738
3739    startTime = new Date().getTime();
3740
3741    if (easingLoop !== null) {
3742      clearInterval(easingLoop);
3743    }
3744  }
3745
3746  function shouldBeConsumedByChild(target, deltaX, deltaY) {
3747    if (!element.contains(target)) {
3748      return false;
3749    }
3750
3751    var cursor = target;
3752
3753    while (cursor && cursor !== element) {
3754      if (cursor.classList.contains(cls.element.consuming)) {
3755        return true;
3756      }
3757
3758      var style = get(cursor);
3759      var overflow = [style.overflow, style.overflowX, style.overflowY].join(
3760        ''
3761      );
3762
3763      // if scrollable
3764      if (overflow.match(/(scroll|auto)/)) {
3765        var maxScrollTop = cursor.scrollHeight - cursor.clientHeight;
3766        if (maxScrollTop > 0) {
3767          if (
3768            !(cursor.scrollTop === 0 && deltaY > 0) &&
3769            !(cursor.scrollTop === maxScrollTop && deltaY < 0)
3770          ) {
3771            return true;
3772          }
3773        }
3774        var maxScrollLeft = cursor.scrollLeft - cursor.clientWidth;
3775        if (maxScrollLeft > 0) {
3776          if (
3777            !(cursor.scrollLeft === 0 && deltaX < 0) &&
3778            !(cursor.scrollLeft === maxScrollLeft && deltaX > 0)
3779          ) {
3780            return true;
3781          }
3782        }
3783      }
3784
3785      cursor = cursor.parentNode;
3786    }
3787
3788    return false;
3789  }
3790
3791  function touchMove(e) {
3792    if (shouldHandle(e)) {
3793      var touch = getTouch(e);
3794
3795      var currentOffset = { pageX: touch.pageX, pageY: touch.pageY };
3796
3797      var differenceX = currentOffset.pageX - startOffset.pageX;
3798      var differenceY = currentOffset.pageY - startOffset.pageY;
3799
3800      if (shouldBeConsumedByChild(e.target, differenceX, differenceY)) {
3801        return;
3802      }
3803
3804      applyTouchMove(differenceX, differenceY);
3805      startOffset = currentOffset;
3806
3807      var currentTime = new Date().getTime();
3808
3809      var timeGap = currentTime - startTime;
3810      if (timeGap > 0) {
3811        speed.x = differenceX / timeGap;
3812        speed.y = differenceY / timeGap;
3813        startTime = currentTime;
3814      }
3815
3816      if (shouldPrevent(differenceX, differenceY)) {
3817        e.preventDefault();
3818      }
3819    }
3820  }
3821  function touchEnd() {
3822    if (i.settings.swipeEasing) {
3823      clearInterval(easingLoop);
3824      easingLoop = setInterval(function() {
3825        if (i.isInitialized) {
3826          clearInterval(easingLoop);
3827          return;
3828        }
3829
3830        if (!speed.x && !speed.y) {
3831          clearInterval(easingLoop);
3832          return;
3833        }
3834
3835        if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
3836          clearInterval(easingLoop);
3837          return;
3838        }
3839
3840        applyTouchMove(speed.x * 30, speed.y * 30);
3841
3842        speed.x *= 0.8;
3843        speed.y *= 0.8;
3844      }, 10);
3845    }
3846  }
3847
3848  if (env.supportsTouch) {
3849    i.event.bind(element, 'touchstart', touchStart);
3850    i.event.bind(element, 'touchmove', touchMove);
3851    i.event.bind(element, 'touchend', touchEnd);
3852  } else if (env.supportsIePointer) {
3853    if (window.PointerEvent) {
3854      i.event.bind(element, 'pointerdown', touchStart);
3855      i.event.bind(element, 'pointermove', touchMove);
3856      i.event.bind(element, 'pointerup', touchEnd);
3857    } else if (window.MSPointerEvent) {
3858      i.event.bind(element, 'MSPointerDown', touchStart);
3859      i.event.bind(element, 'MSPointerMove', touchMove);
3860      i.event.bind(element, 'MSPointerUp', touchEnd);
3861    }
3862  }
3863};
3864
3865var defaultSettings = function () { return ({
3866  handlers: ['click-rail', 'drag-thumb', 'keyboard', 'wheel', 'touch'],
3867  maxScrollbarLength: null,
3868  minScrollbarLength: null,
3869  scrollingThreshold: 1000,
3870  scrollXMarginOffset: 0,
3871  scrollYMarginOffset: 0,
3872  suppressScrollX: false,
3873  suppressScrollY: false,
3874  swipeEasing: true,
3875  useBothWheelAxes: false,
3876  wheelPropagation: true,
3877  wheelSpeed: 1,
3878}); };
3879
3880var handlers = {
3881  'click-rail': clickRail,
3882  'drag-thumb': dragThumb,
3883  keyboard: keyboard,
3884  wheel: wheel,
3885  touch: touch,
3886};
3887
3888var PerfectScrollbar = function PerfectScrollbar(element, userSettings) {
3889  var this$1 = this;
3890  if ( userSettings === void 0 ) userSettings = {};
3891
3892  if (typeof element === 'string') {
3893    element = document.querySelector(element);
3894  }
3895
3896  if (!element || !element.nodeName) {
3897    throw new Error('no element is specified to initialize PerfectScrollbar');
3898  }
3899
3900  this.element = element;
3901
3902  element.classList.add(cls.main);
3903
3904  this.settings = defaultSettings();
3905  for (var key in userSettings) {
3906    this$1.settings[key] = userSettings[key];
3907  }
3908
3909  this.containerWidth = null;
3910  this.containerHeight = null;
3911  this.contentWidth = null;
3912  this.contentHeight = null;
3913
3914  var focus = function () { return element.classList.add(cls.state.focus); };
3915  var blur = function () { return element.classList.remove(cls.state.focus); };
3916
3917  this.isRtl = get(element).direction === 'rtl';
3918  this.isNegativeScroll = (function () {
3919    var originalScrollLeft = element.scrollLeft;
3920    var result = null;
3921    element.scrollLeft = -1;
3922    result = element.scrollLeft < 0;
3923    element.scrollLeft = originalScrollLeft;
3924    return result;
3925  })();
3926  this.negativeScrollAdjustment = this.isNegativeScroll
3927    ? element.scrollWidth - element.clientWidth
3928    : 0;
3929  this.event = new EventManager();
3930  this.ownerDocument = element.ownerDocument || document;
3931
3932  this.scrollbarXRail = div(cls.element.rail('x'));
3933  element.appendChild(this.scrollbarXRail);
3934  this.scrollbarX = div(cls.element.thumb('x'));
3935  this.scrollbarXRail.appendChild(this.scrollbarX);
3936  this.scrollbarX.setAttribute('tabindex', 0);
vendor: 4,650 bytes, lines 3937-4082
3937  this.event.bind(this.scrollbarX, 'focus', focus);
3938  this.event.bind(this.scrollbarX, 'blur', blur);
3939  this.scrollbarXActive = null;
3940  this.scrollbarXWidth = null;
3941  this.scrollbarXLeft = null;
3942  var railXStyle = get(this.scrollbarXRail);
3943  this.scrollbarXBottom = parseInt(railXStyle.bottom, 10);
3944  if (isNaN(this.scrollbarXBottom)) {
3945    this.isScrollbarXUsingBottom = false;
3946    this.scrollbarXTop = toInt(railXStyle.top);
3947  } else {
3948    this.isScrollbarXUsingBottom = true;
3949  }
3950  this.railBorderXWidth =
3951    toInt(railXStyle.borderLeftWidth) + toInt(railXStyle.borderRightWidth);
3952  // Set rail to display:block to calculate margins
3953  set(this.scrollbarXRail, { display: 'block' });
3954  this.railXMarginWidth =
3955    toInt(railXStyle.marginLeft) + toInt(railXStyle.marginRight);
3956  set(this.scrollbarXRail, { display: '' });
3957  this.railXWidth = null;
3958  this.railXRatio = null;
3959
3960  this.scrollbarYRail = div(cls.element.rail('y'));
3961  element.appendChild(this.scrollbarYRail);
3962  this.scrollbarY = div(cls.element.thumb('y'));
3963  this.scrollbarYRail.appendChild(this.scrollbarY);
3964  this.scrollbarY.setAttribute('tabindex', 0);
3965  this.event.bind(this.scrollbarY, 'focus', focus);
3966  this.event.bind(this.scrollbarY, 'blur', blur);
3967  this.scrollbarYActive = null;
3968  this.scrollbarYHeight = null;
3969  this.scrollbarYTop = null;
3970  var railYStyle = get(this.scrollbarYRail);
3971  this.scrollbarYRight = parseInt(railYStyle.right, 10);
3972  if (isNaN(this.scrollbarYRight)) {
3973    this.isScrollbarYUsingRight = false;
3974    this.scrollbarYLeft = toInt(railYStyle.left);
3975  } else {
3976    this.isScrollbarYUsingRight = true;
3977  }
3978  this.scrollbarYOuterWidth = this.isRtl ? outerWidth(this.scrollbarY) : null;
3979  this.railBorderYWidth =
3980    toInt(railYStyle.borderTopWidth) + toInt(railYStyle.borderBottomWidth);
3981  set(this.scrollbarYRail, { display: 'block' });
3982  this.railYMarginHeight =
3983    toInt(railYStyle.marginTop) + toInt(railYStyle.marginBottom);
3984  set(this.scrollbarYRail, { display: '' });
3985  this.railYHeight = null;
3986  this.railYRatio = null;
3987
3988  this.reach = {
3989    x:
3990      element.scrollLeft <= 0
3991        ? 'start'
3992        : element.scrollLeft >= this.contentWidth - this.containerWidth
3993          ? 'end'
3994          : null,
3995    y:
3996      element.scrollTop <= 0
3997        ? 'start'
3998        : element.scrollTop >= this.contentHeight - this.containerHeight
3999          ? 'end'
4000          : null,
4001  };
4002
4003  this.isAlive = true;
4004
4005  this.settings.handlers.forEach(function (handlerName) { return handlers[handlerName](this$1); });
4006
4007  this.lastScrollTop = Math.floor(element.scrollTop); // for onScroll only
4008  this.lastScrollLeft = element.scrollLeft; // for onScroll only
4009  this.event.bind(this.element, 'scroll', function (e) { return this$1.onScroll(e); });
4010  updateGeometry(this);
4011};
4012
4013PerfectScrollbar.prototype.update = function update () {
4014  if (!this.isAlive) {
4015    return;
4016  }
4017
4018  // Recalcuate negative scrollLeft adjustment
4019  this.negativeScrollAdjustment = this.isNegativeScroll
4020    ? this.element.scrollWidth - this.element.clientWidth
4021    : 0;
4022
4023  // Recalculate rail margins
4024  set(this.scrollbarXRail, { display: 'block' });
4025  set(this.scrollbarYRail, { display: 'block' });
4026  this.railXMarginWidth =
4027    toInt(get(this.scrollbarXRail).marginLeft) +
4028    toInt(get(this.scrollbarXRail).marginRight);
4029  this.railYMarginHeight =
4030    toInt(get(this.scrollbarYRail).marginTop) +
4031    toInt(get(this.scrollbarYRail).marginBottom);
4032
4033  // Hide scrollbars not to affect scrollWidth and scrollHeight
4034  set(this.scrollbarXRail, { display: 'none' });
4035  set(this.scrollbarYRail, { display: 'none' });
4036
4037  updateGeometry(this);
4038
4039  processScrollDiff(this, 'top', 0, false, true);
4040  processScrollDiff(this, 'left', 0, false, true);
4041
4042  set(this.scrollbarXRail, { display: '' });
4043  set(this.scrollbarYRail, { display: '' });
4044};
4045
4046PerfectScrollbar.prototype.onScroll = function onScroll (e) {
4047  if (!this.isAlive) {
4048    return;
4049  }
4050
4051  updateGeometry(this);
4052  processScrollDiff(this, 'top', this.element.scrollTop - this.lastScrollTop);
4053  processScrollDiff(
4054    this,
4055    'left',
4056    this.element.scrollLeft - this.lastScrollLeft
4057  );
4058
4059  this.lastScrollTop = Math.floor(this.element.scrollTop);
4060  this.lastScrollLeft = this.element.scrollLeft;
4061};
4062
4063PerfectScrollbar.prototype.destroy = function destroy () {
4064  if (!this.isAlive) {
4065    return;
4066  }
4067
4068  this.event.unbindAll();
4069  remove(this.scrollbarX);
4070  remove(this.scrollbarY);
4071  remove(this.scrollbarXRail);
4072  remove(this.scrollbarYRail);
4073  this.removePsClasses();
4074
4075  // unset elements
4076  this.element = null;
4077  this.scrollbarX = null;
4078  this.scrollbarY = null;
4079  this.scrollbarXRail = null;
4080  this.scrollbarYRail = null;
4081
4082  this.isAlive = false;
vendor: 5,562 bytes, lines 4083-4299
4083};
4084
4085PerfectScrollbar.prototype.removePsClasses = function removePsClasses () {
4086  this.element.className = this.element.className
4087    .split(' ')
4088    .filter(function (name) { return !name.match(/^ps([-_].+|)$/); })
4089    .join(' ');
4090};
4091
4092return PerfectScrollbar;
4093
4094})));
4095
4096(function (factory) {
4097
4098    if ( typeof define === 'function' && define.amd ) {
4099
4100        // AMD. Register as an anonymous module.
4101        define([], factory);
4102
4103    } else if ( typeof exports === 'object' ) {
4104
4105        // Node/CommonJS
4106        module.exports = factory();
4107
4108    } else {
4109
4110        // Browser globals
4111        window.wNumb = factory();
4112    }
4113
4114}(function(){
4115
4116	'use strict';
4117
4118var FormatOptions = [
4119	'decimals',
4120	'thousand',
4121	'mark',
4122	'prefix',
4123	'suffix',
4124	'encoder',
4125	'decoder',
4126	'negativeBefore',
4127	'negative',
4128	'edit',
4129	'undo'
4130];
4131
4132// General
4133
4134	// Reverse a string
4135	function strReverse ( a ) {
4136		return a.split('').reverse().join('');
4137	}
4138
4139	// Check if a string starts with a specified prefix.
4140	function strStartsWith ( input, match ) {
4141		return input.substring(0, match.length) === match;
4142	}
4143
4144	// Check is a string ends in a specified suffix.
4145	function strEndsWith ( input, match ) {
4146		return input.slice(-1 * match.length) === match;
4147	}
4148
4149	// Throw an error if formatting options are incompatible.
4150	function throwEqualError( F, a, b ) {
4151		if ( (F[a] || F[b]) && (F[a] === F[b]) ) {
4152			throw new Error(a);
4153		}
4154	}
4155
4156	// Check if a number is finite and not NaN
4157	function isValidNumber ( input ) {
4158		return typeof input === 'number' && isFinite( input );
4159	}
4160
4161	// Provide rounding-accurate toFixed method.
4162	// Borrowed: http://stackoverflow.com/a/21323330/775265
4163	function toFixed ( value, exp ) {
4164		value = value.toString().split('e');
4165		value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));
4166		value = value.toString().split('e');
4167		return (+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp))).toFixed(exp);
4168	}
4169
4170
4171// Formatting
4172
4173	// Accept a number as input, output formatted string.
4174	function formatTo ( decimals, thousand, mark, prefix, suffix, encoder, decoder, negativeBefore, negative, edit, undo, input ) {
4175
4176		var originalInput = input, inputIsNegative, inputPieces, inputBase, inputDecimals = '', output = '';
4177
4178		// Apply user encoder to the input.
4179		// Expected outcome: number.
4180		if ( encoder ) {
4181			input = encoder(input);
4182		}
4183
4184		// Stop if no valid number was provided, the number is infinite or NaN.
4185		if ( !isValidNumber(input) ) {
4186			return false;
4187		}
4188
4189		// Rounding away decimals might cause a value of -0
4190		// when using very small ranges. Remove those cases.
4191		if ( decimals !== false && parseFloat(input.toFixed(decimals)) === 0 ) {
4192			input = 0;
4193		}
4194
4195		// Formatting is done on absolute numbers,
4196		// decorated by an optional negative symbol.
4197		if ( input < 0 ) {
4198			inputIsNegative = true;
4199			input = Math.abs(input);
4200		}
4201
4202		// Reduce the number of decimals to the specified option.
4203		if ( decimals !== false ) {
4204			input = toFixed( input, decimals );
4205		}
4206
4207		// Transform the number into a string, so it can be split.
4208		input = input.toString();
4209
4210		// Break the number on the decimal separator.
4211		if ( input.indexOf('.') !== -1 ) {
4212			inputPieces = input.split('.');
4213
4214			inputBase = inputPieces[0];
4215
4216			if ( mark ) {
4217				inputDecimals = mark + inputPieces[1];
4218			}
4219
4220		} else {
4221
4222		// If it isn't split, the entire number will do.
4223			inputBase = input;
4224		}
4225
4226		// Group numbers in sets of three.
4227		if ( thousand ) {
4228			inputBase = strReverse(inputBase).match(/.{1,3}/g);
4229			inputBase = strReverse(inputBase.join( strReverse( thousand ) ));
4230		}
4231
4232		// If the number is negative, prefix with negation symbol.
4233		if ( inputIsNegative && negativeBefore ) {
4234			output += negativeBefore;
4235		}
4236
4237		// Prefix the number
4238		if ( prefix ) {
4239			output += prefix;
4240		}
4241
4242		// Normal negative option comes after the prefix. Defaults to '-'.
4243		if ( inputIsNegative && negative ) {
4244			output += negative;
4245		}
4246
4247		// Append the actual number.
4248		output += inputBase;
4249		output += inputDecimals;
4250
4251		// Apply the suffix.
4252		if ( suffix ) {
4253			output += suffix;
4254		}
4255
4256		// Run the output through a user-specified post-formatter.
4257		if ( edit ) {
4258			output = edit ( output, originalInput );
4259		}
4260
4261		// All done.
4262		return output;
4263	}
4264
4265	// Accept a sting as input, output decoded number.
4266	function formatFrom ( decimals, thousand, mark, prefix, suffix, encoder, decoder, negativeBefore, negative, edit, undo, input ) {
4267
4268		var originalInput = input, inputIsNegative, output = '';
4269
4270		// User defined pre-decoder. Result must be a non empty string.
4271		if ( undo ) {
4272			input = undo(input);
4273		}
4274
4275		// Test the input. Can't be empty.
4276		if ( !input || typeof input !== 'string' ) {
4277			return false;
4278		}
4279
4280		// If the string starts with the negativeBefore value: remove it.
4281		// Remember is was there, the number is negative.
4282		if ( negativeBefore && strStartsWith(input, negativeBefore) ) {
4283			input = input.replace(negativeBefore, '');
4284			inputIsNegative = true;
4285		}
4286
4287		// Repeat the same procedure for the prefix.
4288		if ( prefix && strStartsWith(input, prefix) ) {
4289			input = input.replace(prefix, '');
4290		}
4291
4292		// And again for negative.
4293		if ( negative && strStartsWith(input, negative) ) {
4294			input = input.replace(negative, '');
4295			inputIsNegative = true;
4296		}
4297
4298		// Remove the suffix.
4299		// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice
4300		if ( suffix && strEndsWith(input, suffix) ) {
4301			input = input.slice(0, -1 * suffix.length);
4302		}
4303
4304		// Remove the thousand grouping.
4305		if ( thousand ) {
4306			input = input.split(thousand).join('');
4307		}
4308
4309		// Set the decimal separator back to period.
4310		if ( mark ) {
4311			input = input.replace(mark, '.');
4312		}
4313
4314		// Prepend the negative symbol.
4315		if ( inputIsNegative ) {
4316			output += '-';
4317		}
4318
4319		// Add the number
4320		output += input;
4321
4322		// Trim all non-numeric characters (allow '.' and '-');
4323		output = output.replace(/[^0-9\.\-.]/g, '');
4324
4325		// The value contains no parse-able number.
4326		if ( output === '' ) {
4327			return false;
4328		}
4329
4330		// Covert to number.
4331		output = Number(output);
4332
4333		// Run the user-specified post-decoder.
4334		if ( decoder ) {
4335			output = decoder(output);
4336		}
4337
4338		// Check is the output is valid, otherwise: return false.
4339		if ( !isValidNumber(output) ) {
4340			return false;
4341		}
4342
4343		return output;
4344	}
4345
4346
4347// Framework
4348
4349	// Validate formatting options
4350	function validate ( inputOptions ) {
4351
4352		var i, optionName, optionValue,
4353			filteredOptions = {};
4354
4355		if ( inputOptions['suffix'] === undefined ) {
4356			inputOptions['suffix'] = inputOptions['postfix'];
4357		}
4358
4359		for ( i = 0; i < FormatOptions.length; i+=1 ) {
4360
4361			optionName = FormatOptions[i];
4362			optionValue = inputOptions[optionName];
4363
4364			if ( optionValue === undefined ) {
4365
4366				// Only default if negativeBefore isn't set.
4367				if ( optionName === 'negative' && !filteredOptions.negativeBefore ) {
4368					filteredOptions[optionName] = '-';
4369				// Don't set a default for mark when 'thousand' is set.
4370				} else if ( optionName === 'mark' && filteredOptions.thousand !== '.' ) {
4371					filteredOptions[optionName] = '.';
4372				} else {
4373					filteredOptions[optionName] = false;
4374				}
4375
4376			// Floating points in JS are stable up to 7 decimals.
4377			} else if ( optionName === 'decimals' ) {
4378				if ( optionValue >= 0 && optionValue < 8 ) {
4379					filteredOptions[optionName] = optionValue;
4380				} else {
4381					throw new Error(optionName);
4382				}
4383
4384			// These options, when provided, must be functions.
4385			} else if ( optionName === 'encoder' || optionName === 'decoder' || optionName === 'edit' || optionName === 'undo' ) {
4386				if ( typeof optionValue === 'function' ) {
4387					filteredOptions[optionName] = optionValue;
4388				} else {
4389					throw new Error(optionName);
4390				}
4391
4392			// Other options are strings.
4393			} else {
4394
4395				if ( typeof optionValue === 'string' ) {
4396					filteredOptions[optionName] = optionValue;
4397				} else {
4398					throw new Error(optionName);
4399				}
4400			}
4401		}
4402
4403		// Some values can't be extracted from a
4404		// string if certain combinations are present.
4405		throwEqualError(filteredOptions, 'mark', 'thousand');
4406		throwEqualError(filteredOptions, 'prefix', 'negative');
4407		throwEqualError(filteredOptions, 'prefix', 'negativeBefore');
4408
4409		return filteredOptions;
4410	}
4411
4412	// Pass all options as function arguments
4413	function passAll ( options, method, input ) {
4414		var i, args = [];
4415
4416		// Add all options in order of FormatOptions
4417		for ( i = 0; i < FormatOptions.length; i+=1 ) {
4418			args.push(options[FormatOptions[i]]);
4419		}
4420
4421		// Append the input, then call the method, presenting all
4422		// options as arguments.
4423		args.push(input);
4424		return method.apply('', args);
4425	}
4426
4427	function wNumb ( options ) {
4428
4429		if ( !(this instanceof wNumb) ) {
4430			return new wNumb ( options );
4431		}
4432
4433		if ( typeof options !== "object" ) {
4434			return;
4435		}
4436
4437		options = validate(options);
4438
4439		// Call 'formatTo' with proper arguments.
4440		this.to = function ( input ) {
4441			return passAll(options, formatTo, input);
4442		};
4443
4444		// Call 'formatFrom' with proper arguments.
4445		this.from = function ( input ) {
4446			return passAll(options, formatFrom, input);
4447		};
4448	}
4449
4450	return wNumb;
4451
4452}));
4453
4454var identity = function (x) {
4455    return x;
4456};
4457
4458var isArray = function (value) {
4459    return $.isArray(value);
4460};
4461
4462var isObject = function (value) {
4463    return !isArray(value) && (value instanceof Object);
4464};
4465
4466var isNumber = function (value) {
4467    return value instanceof Number;
4468};
4469
4470var isFunction = function (value) {
4471    return value instanceof Function;
4472};
4473
4474var indexOf = function (object, value) {
4475    return $.inArray(value, object);
4476};
4477
4478var inArray = function (array, value) {
4479    return indexOf(array, value) !== -1;
4480};
4481
4482var foreach = function (collection, callback) {
4483    for(var i in collection) {
4484        if(collection.hasOwnProperty(i)) {
4485            callback(collection[i], i, collection);
4486        }
4487    }
4488};
4489
4490
4491var last = function (array) {
4492    return array[array.length - 1];
4493};
4494
4495var argumentsToArray = function (args) {
4496    return Array.prototype.slice.call(args);
4497};
4498
4499var extend = function () {
4500    var extended = {};
4501    foreach(argumentsToArray(arguments), function (o) {
4502        foreach(o, function (val, key) {
4503            extended[key] = val;
4504        });
4505    });
4506    return extended;
4507};
4508
4509var mapToArray = function (collection, callback) {
4510    var mapped = [];
4511    foreach(collection, function (value, key, coll) {
4512        mapped.push(callback(value, key, coll));
4513    });
4514    return mapped;
4515};
4516
4517var mapToObject = function (collection, callback, keyCallback) {
4518    var mapped = {};
4519    foreach(collection, function (value, key, coll) {
4520        key = keyCallback ? keyCallback(key, value) : key;
4521        mapped[key] = callback(value, key, coll);
4522    });
4523    return mapped;
4524};
4525
4526var map = function (collection, callback, keyCallback) {
4527    return isArray(collection) ?
4528        mapToArray(collection, callback) :
4529        mapToObject(collection, callback, keyCallback);
4530};
4531
4532var pluck = function (arrayOfObjects, key) {
4533    return map(arrayOfObjects, function (val) {
4534        return val[key];
4535    });
4536};
4537
4538var filter = function (collection, callback) {
4539    var filtered;
4540
4541    if(isArray(collection)) {
4542        filtered = [];
4543        foreach(collection, function (val, key, coll) {
4544            if(callback(val, key, coll)) {
4545                filtered.push(val);
4546            }
4547        });
4548    }
4549    else {
4550        filtered = {};
4551        foreach(collection, function (val, key, coll) {
4552            if(callback(val, key, coll)) {
4553                filtered[key] = val;
4554            }
4555        });
4556    }
4557
4558    return filtered;
4559};
4560
4561var call = function (collection, functionName, args) {
4562    return map(collection, function (object, name) {
4563        return object[functionName].apply(object, args || []);
4564    });
4565};
4566
4567//execute callback immediately and at most one time on the minimumInterval,
4568//ignore block attempts
4569var throttle = function (minimumInterval, callback) {
4570    var timeout = null;
4571    return function () {
4572        var that = this, args = arguments;
4573        if(timeout === null) {
4574            timeout = setTimeout(function () {
4575                timeout = null;
4576            }, minimumInterval);
4577            callback.apply(that, args);
4578        }
4579    };
4580};
4581
4582
4583var mixinPubSub = function (object) {
4584    object = object || {};
4585    var topics = {};
4586
4587    object.publish = function (topic, data) {
4588        foreach(topics[topic], function (callback) {
4589            callback(data);
4590        });
4591    };
4592
4593    object.subscribe = function (topic, callback) {
4594        topics[topic] = topics[topic] || [];
4595        topics[topic].push(callback);
4596    };
4597
4598    object.unsubscribe = function (callback) {
4599        foreach(topics, function (subscribers) {
4600            var index = indexOf(subscribers, callback);
4601            if(index !== -1) {
4602                subscribers.splice(index, 1);
4603            }
4604        });
4605    };
4606
4607    return object;
4608};
4609
4610// jquery.input version 0.0.0
4611// https://github.com/DubFriend/jquery.input
4612// (MIT) 09-04-2014
4613// Brian Detering <[email protected]> (http://www.briandetering.net/)
4614(function ($) {
4615'use strict';
4616
4617var createBaseInput = function (fig, my) {
4618    var self = mixinPubSub(),
4619        $self = fig.$;
4620
4621    self.getType = function () {
4622        throw 'implement me (return type. "text", "radio", etc.)';
4623    };
4624
4625    self.$ = function (selector) {
4626        return selector ? $self.find(selector) : $self;
4627    };
4628
4629    self.disable = function () {
4630        self.$().prop('disabled', true);
4631        self.publish('isEnabled', false);
4632    };
4633
4634    self.enable = function () {
4635        self.$().prop('disabled', false);
4636        self.publish('isEnabled', true);
4637    };
4638
4639    my.equalTo = function (a, b) {
4640        return a === b;
4641    };
4642
4643    my.publishChange = (function () {
4644        var oldValue;
4645        return function (e, domElement) {
4646            var newValue = self.get();
4647            if(!my.equalTo(newValue, oldValue)) {
4648                self.publish('change', { e: e, domElement: domElement });
4649            }
4650            oldValue = newValue;
4651        };
4652    }());
4653
4654    return self;
4655};
4656
4657
4658var createInput = function (fig, my) {
4659    var self = createBaseInput(fig, my);
4660
4661    self.get = function () {
4662        return self.$().val();
4663    };
4664
4665    self.set = function (newValue) {
4666        self.$().val(newValue);
4667    };
4668
4669    self.clear = function () {
4670        self.set('');
4671    };
4672
4673    my.buildSetter = function (callback) {
4674        return function (newValue) {
4675            callback.call(self, newValue);
4676        };
4677    };
4678
4679    return self;
4680};
4681
4682var inputEqualToArray = function (a, b) {
4683    a = isArray(a) ? a : [a];
4684    b = isArray(b) ? b : [b];
4685
4686    var isEqual = true;
4687    if(a.length !== b.length) {
4688        isEqual = false;
4689    }
4690    else {
4691        foreach(a, function (value) {
4692            if(!inArray(b, value)) {
4693                isEqual = false;
4694            }
4695        });
4696    }
4697
4698    return isEqual;
4699};
4700
4701var createInputButton = function (fig) {
4702    var my = {},
4703        self = createInput(fig, my);
4704
4705    self.getType = function () {
4706        return 'button';
4707    };
4708
4709    self.$().on('change', function (e) {
4710        my.publishChange(e, this);
4711    });
4712
4713    return self;
4714};
4715
4716var createInputCheckbox = function (fig) {
4717    var my = {},
4718        self = createInput(fig, my);
4719
4720    self.getType = function () {
4721        return 'checkbox';
4722    };
4723
4724    self.get = function () {
4725        var values = [];
4726        self.$().filter(':checked').each(function () {
4727            values.push($(this).val());
4728        });
4729        return values;
4730    };
4731
4732    self.set = function (newValues) {
4733        newValues = isArray(newValues) ? newValues : [newValues];
4734
4735        self.$().each(function () {
4736            $(this).prop('checked', false);
4737        });
4738
4739        foreach(newValues, function (value) {
4740            self.$().filter('[value="' + value + '"]')
4741                .prop('checked', true);
4742        });
4743    };
4744
4745    my.equalTo = inputEqualToArray;
4746
4747    self.$().change(function (e) {
4748        my.publishChange(e, this);
4749    });
4750
4751    return self;
4752};
4753
4754var createInputEmail = function (fig) {
4755    var my = {},
4756        self = createInputText(fig, my);
4757
4758    self.getType = function () {
4759        return 'email';
4760    };
4761
4762    return self;
4763};
4764
4765var createInputFile = function (fig) {
4766    var my = {},
4767        self = createBaseInput(fig, my);
4768
4769    self.getType = function () {
4770        return 'file';
4771    };
4772
4773    self.get = function () {
4774        return last(self.$().val().split('\\'));
4775    };
4776
4777    self.clear = function () {
4778        // http://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery
4779        this.$().each(function () {
4780            $(this).wrap('<form>').closest('form').get(0).reset();
4781            $(this).unwrap();
4782        });
4783    };
4784
4785    self.$().change(function (e) {
4786        my.publishChange(e, this);
4787        // self.publish('change', self);
4788    });
4789
4790    return self;
4791};
4792
4793var createInputHidden = function (fig) {
4794    var my = {},
4795        self = createInput(fig, my);
4796
4797    self.getType = function () {
4798        return 'hidden';
4799    };
4800
4801    self.$().change(function (e) {
4802        my.publishChange(e, this);
4803    });
4804
4805    return self;
4806};
4807var createInputMultipleFile = function (fig) {
4808    var my = {},
4809        self = createBaseInput(fig, my);
4810
4811    self.getType = function () {
4812        return 'file[multiple]';
4813    };
4814
4815    self.get = function () {
4816        // http://stackoverflow.com/questions/14035530/how-to-get-value-of-html-5-multiple-file-upload-variable-using-jquery
4817        var fileListObject = self.$().get(0).files || [],
4818            names = [], i;
4819
4820        for(i = 0; i < (fileListObject.length || 0); i += 1) {
4821            names.push(fileListObject[i].name);
4822        }
4823
4824        return names;
4825    };
4826
4827    self.clear = function () {
4828        // http://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery
4829        this.$().each(function () {
4830            $(this).wrap('<form>').closest('form').get(0).reset();
4831            $(this).unwrap();
4832        });
4833    };
4834
4835    self.$().change(function (e) {
4836        my.publishChange(e, this);
4837    });
4838
4839    return self;
4840};
4841
4842var createInputMultipleSelect = function (fig) {
4843    var my = {},
4844        self = createInput(fig, my);
4845
4846    self.getType = function () {
4847        return 'select[multiple]';
4848    };
4849
4850    self.get = function () {
4851        return self.$().val() || [];
4852    };
4853
4854    self.set = function (newValues) {
4855        self.$().val(
4856            newValues === '' ? [] : isArray(newValues) ? newValues : [newValues]
4857        );
4858    };
4859
4860    my.equalTo = inputEqualToArray;
4861
4862    self.$().change(function (e) {
4863        my.publishChange(e, this);
4864    });
4865
4866    return self;
4867};
4868
4869var createInputPassword = function (fig) {
4870    var my = {},
4871        self = createInputText(fig, my);
4872
4873    self.getType = function () {
4874        return 'password';
4875    };
4876
4877    return self;
4878};
4879
4880var createInputRadio = function (fig) {
4881    var my = {},
4882        self = createInput(fig, my);
4883
4884    self.getType = function () {
4885        return 'radio';
4886    };
4887
4888    self.get = function () {
4889        return self.$().filter(':checked').val() || null;
4890    };
4891
4892    self.set = function (newValue) {
4893        if(!newValue) {
4894            self.$().each(function () {
4895                $(this).prop('checked', false);
4896            });
4897        }
4898        else {
4899            self.$().filter('[value="' + newValue + '"]').prop('checked', true);
4900        }
4901    };
4902
4903    self.$().change(function (e) {
4904        my.publishChange(e, this);
4905    });
4906
4907    return self;
4908};
4909
4910var createInputRange = function (fig) {
4911    var my = {},
4912        self = createInput(fig, my);
4913
4914    self.getType = function () {
4915        return 'range';
4916    };
4917
4918    self.$().change(function (e) {
4919        my.publishChange(e, this);
4920    });
4921
4922    return self;
4923};
4924
4925var createInputSelect = function (fig) {
4926    var my = {},
4927        self = createInput(fig, my);
4928
4929    self.getType = function () {
4930        return 'select';
4931    };
4932
4933    self.$().change(function (e) {
4934        my.publishChange(e, this);
4935    });
4936
4937    return self;
4938};
4939
4940var createInputText = function (fig) {
4941    var my = {},
4942        self = createInput(fig, my);
4943
4944    self.getType = function () {
4945        return 'text';
4946    };
4947
4948    self.$().on('change keyup keydown', function (e) {
4949        my.publishChange(e, this);
4950    });
4951
4952    return self;
4953};
4954
4955var createInputTextarea = function (fig) {
4956    var my = {},
4957        self = createInput(fig, my);
4958
4959    self.getType = function () {
4960        return 'textarea';
4961    };
4962
4963    self.$().on('change keyup keydown', function (e) {
4964        my.publishChange(e, this);
4965    });
4966
4967    return self;
4968};
4969
4970var createInputURL = function (fig) {
4971    var my = {},
4972        self = createInputText(fig, my);
4973
4974    self.getType = function () {
4975        return 'url';
4976    };
4977
4978    return self;
4979};
4980
4981var buildFormInputs = function (fig) {
4982    var inputs = {},
4983        $self = fig.$;
4984
4985    var constructor = fig.constructorOverride || {
4986        button: createInputButton,
4987        text: createInputText,
4988        url: createInputURL,
4989        email: createInputEmail,
4990        password: createInputPassword,
4991        range: createInputRange,
4992        textarea: createInputTextarea,
4993        select: createInputSelect,
4994        'select[multiple]': createInputMultipleSelect,
4995        radio: createInputRadio,
4996        checkbox: createInputCheckbox,
4997        file: createInputFile,
4998        'file[multiple]': createInputMultipleFile,
4999        hidden: createInputHidden
5000    };
5001
5002    var addInputsBasic = function (type, selector) {
5003        var $input = isObject(selector) ? selector : $self.find(selector);
5004
5005        $input.each(function () {
5006            var name = $(this).attr('name');
5007            inputs[name] = constructor[type]({
5008                $: $(this)
5009            });
5010        });
5011    };
5012
5013    var addInputsGroup = function (type, selector) {
5014        var names = [],
5015            $input = isObject(selector) ? selector : $self.find(selector);
5016
5017        if(isObject(selector)) {
5018            inputs[$input.attr('name')] = constructor[type]({
5019                $: $input
5020            });
5021        }
5022        else {
5023            // group by name attribute
5024            $input.each(function () {
5025                if(indexOf(names, $(this).attr('name')) === -1) {
5026                    names.push($(this).attr('name'));
5027                }
5028            });
5029
5030            foreach(names, function (name) {
5031                inputs[name] = constructor[type]({
5032                    $: $self.find('input[name="' + name + '"]')
5033                });
5034            });
5035        }
5036    };
5037
5038
5039    if($self.is('input, select, textarea')) {
5040        if($self.is('input[type="button"], button, input[type="submit"]')) {
5041            addInputsBasic('button', $self);
5042        }
5043        else if($self.is('textarea')) {
5044            addInputsBasic('textarea', $self);
5045        }
5046        else if(
5047            $self.is('input[type="text"]') ||
5048            $self.is('input') && !$self.attr('type')
5049        ) {
5050            addInputsBasic('text', $self);
5051        }
5052        else if($self.is('input[type="password"]')) {
5053            addInputsBasic('password', $self);
5054        }
5055        else if($self.is('input[type="email"]')) {
5056            addInputsBasic('email', $self);
5057        }
5058        else if($self.is('input[type="url"]')) {
5059            addInputsBasic('url', $self);
5060        }
5061        else if($self.is('input[type="range"]')) {
5062            addInputsBasic('range', $self);
5063        }
5064        else if($self.is('select')) {
5065            if($self.is('[multiple]')) {
5066                addInputsBasic('select[multiple]', $self);
5067            }
5068            else {
5069                addInputsBasic('select', $self);
5070            }
5071        }
5072        else if($self.is('input[type="file"]')) {
5073            if($self.is('[multiple]')) {
5074                addInputsBasic('file[multiple]', $self);
5075            }
5076            else {
5077                addInputsBasic('file', $self);
5078            }
5079        }
5080        else if($self.is('input[type="hidden"]')) {
5081            addInputsBasic('hidden', $self);
5082        }
5083        else if($self.is('input[type="radio"]')) {
5084            addInputsGroup('radio', $self);
5085        }
5086        else if($self.is('input[type="checkbox"]')) {
5087            addInputsGroup('checkbox', $self);
5088        }
5089        else {
5090            //in all other cases default to a "text" input interface.
5091            addInputsBasic('text', $self);
5092        }
5093    }
5094    else {
5095        addInputsBasic('button', 'input[type="button"], button, input[type="submit"]');
5096        addInputsBasic('text', 'input[type="text"]');
5097        addInputsBasic('password', 'input[type="password"]');
5098        addInputsBasic('email', 'input[type="email"]');
5099        addInputsBasic('url', 'input[type="url"]');
5100        addInputsBasic('range', 'input[type="range"]');
5101        addInputsBasic('textarea', 'textarea');
5102        addInputsBasic('select', 'select:not([multiple])');
5103        addInputsBasic('select[multiple]', 'select[multiple]');
5104        addInputsBasic('file', 'input[type="file"]:not([multiple])');
5105        addInputsBasic('file[multiple]', 'input[type="file"][multiple]');
5106        addInputsBasic('hidden', 'input[type="hidden"]');
5107        addInputsGroup('radio', 'input[type="radio"]');
5108        addInputsGroup('checkbox', 'input[type="checkbox"]');
5109    }
5110
5111    return inputs;
5112};
5113
5114$.fn.inputVal = function (newValue) {
5115    var $self = $(this);
5116
5117    var inputs = buildFormInputs({ $: $self });
5118
5119    if($self.is('input, textarea, select')) {
5120        if(typeof newValue === 'undefined') {
5121            return inputs[$self.attr('name')].get();
5122        }
5123        else {
5124            inputs[$self.attr('name')].set(newValue);
5125            return $self;
5126        }
5127    }
5128    else {
5129        if(typeof newValue === 'undefined') {
5130            return call(inputs, 'get');
5131        }
5132        else {
5133            foreach(newValue, function (value, inputName) {
5134                inputs[inputName].set(value);
5135            });
5136            return $self;
5137        }
5138    }
5139};
5140
5141$.fn.inputOnChange = function (callback) {
5142    var $self = $(this);
5143    var inputs = buildFormInputs({ $: $self });
5144    foreach(inputs, function (input) {
5145        input.subscribe('change', function (data) {
5146            callback.call(data.domElement, data.e);
5147        });
5148    });
5149    return $self;
5150};
5151
5152$.fn.inputDisable = function () {
5153    var $self = $(this);
5154    call(buildFormInputs({ $: $self }), 'disable');
5155    return $self;
5156};
5157
5158$.fn.inputEnable = function () {
5159    var $self = $(this);
5160    call(buildFormInputs({ $: $self }), 'enable');
5161    return $self;
5162};
5163
5164$.fn.inputClear = function () {
5165    var $self = $(this);
5166    call(buildFormInputs({ $: $self }), 'clear');
5167    return $self;
5168};
5169
5170}(jQuery));
5171
5172$.fn.repeaterVal = function () {
5173    var parse = function (raw) {
5174        var parsed = [];
5175
5176        foreach(raw, function (val, key) {
5177            var parsedKey = [];
5178            if(key !== "undefined") {
5179                parsedKey.push(key.match(/^[^\[]*/)[0]);
5180                parsedKey = parsedKey.concat(map(
5181                    key.match(/\[[^\]]*\]/g),
5182                    function (bracketed) {
5183                        return bracketed.replace(/[\[\]]/g, '');
5184                    }
5185                ));
5186
5187                parsed.push({
5188                    val: val,
5189                    key: parsedKey
5190                });
5191            }
5192        });
5193
5194        return parsed;
5195    };
5196
5197    var build = function (parsed) {
5198        if(
5199            parsed.length === 1 &&
5200            (parsed[0].key.length === 0 || parsed[0].key.length === 1 && !parsed[0].key[0])
5201        ) {
5202            return parsed[0].val;
5203        }
5204
5205        foreach(parsed, function (p) {
5206            p.head = p.key.shift();
5207        });
5208
5209        var grouped = (function () {
5210            var grouped = {};
5211
5212            foreach(parsed, function (p) {
5213                if(!grouped[p.head]) {
5214                    grouped[p.head] = [];
5215                }
5216                grouped[p.head].push(p);
5217            });
5218
5219            return grouped;
5220        }());
5221
5222        var built;
5223
5224        if(/^[0-9]+$/.test(parsed[0].head)) {
5225            built = [];
5226            foreach(grouped, function (group) {
5227                built.push(build(group));
5228            });
5229        }
5230        else {
5231            built = {};
5232            foreach(grouped, function (group, key) {
5233                built[key] = build(group);
5234            });
5235        }
5236
5237        return built;
5238    };
5239
5240    return build(parse($(this).inputVal()));
5241};
5242
5243$.fn.repeater = function (fig) {
5244    fig = fig || {};
5245
5246    var setList;
5247
5248    $(this).each(function () {
5249
5250        var $self = $(this);
5251
5252        var show = fig.show || function () {
5253            $(this).show();
5254        };
5255
5256        var hide = fig.hide || function (removeElement) {
5257            removeElement();
5258        };
5259
5260        var $list = $self.find('[data-repeater-list]').first();
5261
5262        var $filterNested = function ($items, repeaters) {
5263            return $items.filter(function () {
5264                return repeaters ?
5265                    $(this).closest(
5266                        pluck(repeaters, 'selector').join(',')
5267                    ).length === 0 : true;
5268            });
5269        };
5270
5271        var $items = function () {
5272            return $filterNested($list.find('[data-repeater-item]'), fig.repeaters);
5273        };
5274
5275        var $itemTemplate = $list.find('[data-repeater-item]')
5276                                 .first().clone().hide();
5277
5278        var $firstDeleteButton = $filterNested(
5279            $filterNested($(this).find('[data-repeater-item]'), fig.repeaters)
5280            .first().find('[data-repeater-delete]'),
5281            fig.repeaters
5282        );
5283
5284        if(fig.isFirstItemUndeletable && $firstDeleteButton) {
5285            $firstDeleteButton.remove();
5286        }
5287
5288        var getGroupName = function () {
5289            var groupName = $list.data('repeater-list');
5290            return fig.$parent ?
5291                fig.$parent.data('item-name') + '[' + groupName + ']' :
5292                groupName;
5293        };
5294
5295        var initNested = function ($listItems) {
5296            if(fig.repeaters) {
5297                $listItems.each(function () {
5298                    var $item = $(this);
5299                    foreach(fig.repeaters, function (nestedFig) {
5300                        $item.find(nestedFig.selector).repeater(extend(
5301                            nestedFig, { $parent: $item }
5302                        ));
5303                    });
5304                });
5305            }
5306        };
5307
5308        var $foreachRepeaterInItem = function (repeaters, $item, cb) {
5309            if(repeaters) {
5310                foreach(repeaters, function (nestedFig) {
5311                    cb.call($item.find(nestedFig.selector)[0], nestedFig);
5312                });
5313            }
5314        };
5315
5316        var setIndexes = function ($items, groupName, repeaters) {
5317            $items.each(function (index) {
5318                var $item = $(this);
5319                $item.data('item-name', groupName + '[' + index + ']');
5320                $filterNested($item.find('[name]'), repeaters)
5321                .each(function () {
5322                    var $input = $(this);
5323                    // match non empty brackets (ex: "[foo]")
5324                    var matches = $input.attr('name').match(/\[[^\]]+\]/g);
5325
5326                    var name = matches ?
5327                        // strip "[" and "]" characters
5328                        last(matches).replace(/\[|\]/g, '') :
5329                        $input.attr('name');
5330
5331
5332                    var newName = groupName + '[' + index + '][' + name + ']' +
5333                        ($input.is(':checkbox') || $input.attr('multiple') ? '[]' : '');
5334
5335                    $input.attr('name', newName);
5336
5337                    $foreachRepeaterInItem(repeaters, $item, function (nestedFig) {
5338                        var $repeater = $(this);
5339                        setIndexes(
5340                            $filterNested($repeater.find('[data-repeater-item]'), nestedFig.repeaters || []),
5341                            groupName + '[' + index + ']' +
5342                                        '[' + $repeater.find('[data-repeater-list]').first().data('repeater-list') + ']',
5343                            nestedFig.repeaters
5344                        );
5345                    });
5346                });
5347            });
5348
5349            $list.find('input[name][checked]')
5350                .removeAttr('checked')
5351                .prop('checked', true);
5352        };
5353
5354        setIndexes($items(), getGroupName(), fig.repeaters);
5355        initNested($items());
5356        if(fig.initEmpty) {
5357            $items().remove();
5358        }
5359
5360        if(fig.ready) {
5361            fig.ready(function () {
5362                setIndexes($items(), getGroupName(), fig.repeaters);
5363            });
5364        }
5365
5366        var appendItem = (function () {
5367            var setItemsValues = function ($item, data, repeaters) {
5368                if(data || fig.defaultValues) {
5369                    var inputNames = {};
5370                    $filterNested($item.find('[name]'), repeaters).each(function () {
5371                        var key = $(this).attr('name').match(/\[([^\]]*)(\]|\]\[\])$/)[1];
5372                        inputNames[key] = $(this).attr('name');
5373                    });
5374
5375                    $item.inputVal(map(
5376                        filter(data || fig.defaultValues, function (val, name) {
5377                            return inputNames[name];
5378                        }),
5379                        identity,
5380                        function (name) {
5381                            return inputNames[name];
5382                        }
5383                    ));
5384                }
5385
5386
5387                $foreachRepeaterInItem(repeaters, $item, function (nestedFig) {
5388                    var $repeater = $(this);
5389                    $filterNested(
5390                        $repeater.find('[data-repeater-item]'),
5391                        nestedFig.repeaters
5392                    )
5393                    .each(function () {
5394                        var fieldName = $repeater.find('[data-repeater-list]').data('repeater-list');
5395                        if(data && data[fieldName]) {
5396                            var $template = $(this).clone();
5397                            $repeater.find('[data-repeater-item]').remove();
5398                            foreach(data[fieldName], function (data) {
5399                                var $item = $template.clone();
5400                                setItemsValues(
5401                                    $item,
5402                                    data,
5403                                    nestedFig.repeaters || []
5404                                );
5405                                $repeater.find('[data-repeater-list]').append($item);
5406                            });
5407                        }
5408                        else {
5409                            setItemsValues(
5410                                $(this),
5411                                nestedFig.defaultValues,
5412                                nestedFig.repeaters || []
5413                            );
5414                        }
5415                    });
5416                });
5417
5418            };
5419
5420            return function ($item, data) {
5421                $list.append($item);
5422                setIndexes($items(), getGroupName(), fig.repeaters);
5423                $item.find('[name]').each(function () {
5424                    $(this).inputClear();
5425                });
5426                setItemsValues($item, data || fig.defaultValues, fig.repeaters);
5427            };
5428        }());
5429
5430        var addItem = function (data) {
5431            var $item = $itemTemplate.clone();
5432            appendItem($item, data);
5433            if(fig.repeaters) {
5434                initNested($item);
5435            }
5436            show.call($item.get(0));
5437        };
5438
5439        setList = function (rows) {
5440            $items().remove();
5441            foreach(rows, addItem);
5442        };
5443
5444        $filterNested($self.find('[data-repeater-create]'), fig.repeaters).click(function () {
5445            addItem();
5446        });
5447
5448        $list.on('click', '[data-repeater-delete]', function () {
5449            var self = $(this).closest('[data-repeater-item]').get(0);
5450            hide.call(self, function () {
5451                $(self).remove();
5452                setIndexes($items(), getGroupName(), fig.repeaters);
5453            });
5454        });
5455    });
5456
5457    this.setList = setList;
5458
5459    return this;
5460};
5461
5462/*!
5463 * jQuery Form Plugin
5464 * version: 4.2.2
5465 * Requires jQuery v1.7.2 or later
5466 * Project repository: https://github.com/jquery-form/form
5467
5468 * Copyright 2017 Kevin Morris
5469 * Copyright 2006 M. Alsup
5470
5471 * Dual licensed under the LGPL-2.1+ or MIT licenses
5472 * https://github.com/jquery-form/form#license
5473
5474 * This library is free software; you can redistribute it and/or
5475 * modify it under the terms of the GNU Lesser General Public
5476 * License as published by the Free Software Foundation; either
5477 * version 2.1 of the License, or (at your option) any later version.
5478 * This library is distributed in the hope that it will be useful,
5479 * but WITHOUT ANY WARRANTY; without even the implied warranty of
5480 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
5481 * Lesser General Public License for more details.
5482 */
5483!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof module&&module.exports?module.exports=function(t,r){return void 0===r&&(r="undefined"!=typeof window?require("jquery"):require("jquery")(t)),e(r),r}:e(jQuery)}(function(e){"use strict";function t(t){var r=t.data;t.isDefaultPrevented()||(t.preventDefault(),e(t.target).closest("form").ajaxSubmit(r))}function r(t){var r=t.target,a=e(r);if(!a.is("[type=submit],[type=image]")){var n=a.closest("[type=submit]");if(0===n.length)return;r=n[0]}var i=r.form;if(i.clk=r,"image"===r.type)if(void 0!==t.offsetX)i.clk_x=t.offsetX,i.clk_y=t.offsetY;else if("function"==typeof e.fn.offset){var o=a.offset();i.clk_x=t.pageX-o.left,i.clk_y=t.pageY-o.top}else i.clk_x=t.pageX-r.offsetLeft,i.clk_y=t.pageY-r.offsetTop;setTimeout(function(){i.clk=i.clk_x=i.clk_y=null},100)}function a(){if(e.fn.ajaxSubmit.debug){var t="[jquery.form] "+Array.prototype.join.call(arguments,"");window.console&&window.console.log?window.console.log(t):window.opera&&window.opera.postError&&window.opera.postError(t)}}var n=/\r?\n/g,i={};i.fileapi=void 0!==e('<input type="file">').get(0).files,i.formdata=void 0!==window.FormData;var o=!!e.fn.prop;e.fn.attr2=function(){if(!o)return this.attr.apply(this,arguments);var e=this.prop.apply(this,arguments);return e&&e.jquery||"string"==typeof e?e:this.attr.apply(this,arguments)},e.fn.ajaxSubmit=function(t,r,n,s){function u(r){var a,n,i=e.param(r,t.traditional).split("&"),o=i.length,s=[];for(a=0;a<o;a++)i[a]=i[a].replace(/\+/g," "),n=i[a].split("="),s.push([decodeURIComponent(n[0]),decodeURIComponent(n[1])]);return s}function c(r){function n(e){var t=null;try{e.contentWindow&&(t=e.contentWindow.document)}catch(e){a("cannot get iframe.contentWindow document: "+e)}if(t)return t;try{t=e.contentDocument?e.contentDocument:e.document}catch(r){a("cannot get iframe.contentDocument: "+r),t=e.document}return t}function i(){function t(){try{var e=n(v).readyState;a("state = "+e),e&&"uninitialized"===e.toLowerCase()&&setTimeout(t,50)}catch(e){a("Server abort: ",e," (",e.name,")"),s(L),j&&clearTimeout(j),j=void 0}}
vendor: 5,845 bytes, line 5483
5483var r=p.attr2("target"),i=p.attr2("action"),o=p.attr("enctype")||p.attr("encoding")||"multipart/form-data";w.setAttribute("target",m),l&&!/post/i.test(l)||w.setAttribute("method","POST"),i!==f.url&&w.setAttribute("action",f.url),f.skipEncodingOverride||l&&!/post/i.test(l)||p.attr({encoding:"multipart/form-data",enctype:"multipart/form-data"}),f.timeout&&(j=setTimeout(function(){T=!0,s(A)},f.timeout));var u=[];try{if(f.extraData)for(var c in f.extraData)f.extraData.hasOwnProperty(c)&&(e.isPlainObject(f.extraData[c])&&f.extraData[c].hasOwnProperty("name")&&f.extraData[c].hasOwnProperty("value")?u.push(e('<input type="hidden" name="'+f.extraData[c].name+'">',k).val(f.extraData[c].value).appendTo(w)[0]):u.push(e('<input type="hidden" name="'+c+'">',k).val(f.extraData[c]).appendTo(w)[0]));f.iframeTarget||h.appendTo(D),v.attachEvent?v.attachEvent("onload",s):v.addEventListener("load",s,!1),setTimeout(t,15);try{w.submit()}catch(e){document.createElement("form").submit.apply(w)}}finally{w.setAttribute("action",i),w.setAttribute("enctype",o),r?w.setAttribute("target",r):p.removeAttr("target"),e(u).remove()}}function s(t){if(!x.aborted&&!X){if((O=n(v))||(a("cannot access response document"),t=L),t===A&&x)return x.abort("timeout"),void S.reject(x,"timeout");if(t===L&&x)return x.abort("server abort"),void S.reject(x,"error","server abort");if(O&&O.location.href!==f.iframeSrc||T){v.detachEvent?v.detachEvent("onload",s):v.removeEventListener("load",s,!1);var r,i="success";try{if(T)throw"timeout";var o="xml"===f.dataType||O.XMLDocument||e.isXMLDoc(O);if(a("isXml="+o),!o&&window.opera&&(null===O.body||!O.body.innerHTML)&&--C)return a("requeing onLoad callback, DOM not available"),void setTimeout(s,250);var u=O.body?O.body:O.documentElement;x.responseText=u?u.innerHTML:null,x.responseXML=O.XMLDocument?O.XMLDocument:O,o&&(f.dataType="xml"),x.getResponseHeader=function(e){return{"content-type":f.dataType}[e.toLowerCase()]},u&&(x.status=Number(u.getAttribute("status"))||x.status,x.statusText=u.getAttribute("statusText")||x.statusText);var c=(f.dataType||"").toLowerCase(),l=/(json|script|text)/.test(c);if(l||f.textarea){var p=O.getElementsByTagName("textarea")[0];if(p)x.responseText=p.value,x.status=Number(p.getAttribute("status"))||x.status,x.statusText=p.getAttribute("statusText")||x.statusText;else if(l){var m=O.getElementsByTagName("pre")[0],g=O.getElementsByTagName("body")[0];m?x.responseText=m.textContent?m.textContent:m.innerText:g&&(x.responseText=g.textContent?g.textContent:g.innerText)}}else"xml"===c&&!x.responseXML&&x.responseText&&(x.responseXML=q(x.responseText));try{M=N(x,c,f)}catch(e){i="parsererror",x.error=r=e||i}}catch(e){a("error caught: ",e),i="error",x.error=r=e||i}x.aborted&&(a("upload aborted"),i=null),x.status&&(i=x.status>=200&&x.status<300||304===x.status?"success":"error"),"success"===i?(f.success&&f.success.call(f.context,M,"success",x),S.resolve(x.responseText,"success",x),d&&e.event.trigger("ajaxSuccess",[x,f])):i&&(void 0===r&&(r=x.statusText),f.error&&f.error.call(f.context,x,i,r),S.reject(x,"error",r),d&&e.event.trigger("ajaxError",[x,f,r])),d&&e.event.trigger("ajaxComplete",[x,f]),d&&!--e.active&&e.event.trigger("ajaxStop"),f.complete&&f.complete.call(f.context,x,i),X=!0,f.timeout&&clearTimeout(j),setTimeout(function(){f.iframeTarget?h.attr("src",f.iframeSrc):h.remove(),x.responseXML=null},100)}}}var u,c,f,d,m,h,v,x,y,b,T,j,w=p[0],S=e.Deferred();if(S.abort=function(e){x.abort(e)},r)for(c=0;c<g.length;c++)u=e(g[c]),o?u.prop("disabled",!1):u.removeAttr("disabled");(f=e.extend(!0,{},e.ajaxSettings,t)).context=f.context||f,m="jqFormIO"+(new Date).getTime();var k=w.ownerDocument,D=p.closest("body");if(f.iframeTarget?(b=(h=e(f.iframeTarget,k)).attr2("name"))?m=b:h.attr2("name",m):(h=e('<iframe name="'+m+'" src="'+f.iframeSrc+'" />',k)).css({position:"absolute",top:"-1000px",left:"-1000px"}),v=h[0],x={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(t){var r="timeout"===t?"timeout":"aborted";a("aborting upload... "+r),this.aborted=1;try{v.contentWindow.document.execCommand&&v.contentWindow.document.execCommand("Stop")}catch(e){}h.attr("src",f.iframeSrc),x.error=r,f.error&&f.error.call(f.context,x,r,t),d&&e.event.trigger("ajaxError",[x,f,r]),f.complete&&f.complete.call(f.context,x,r)}},(d=f.global)&&0==e.active++&&e.event.trigger("ajaxStart"),d&&e.event.trigger("ajaxSend",[x,f]),f.beforeSend&&!1===f.beforeSend.call(f.context,x,f))return f.global&&e.active--,S.reject(),S;if(x.aborted)return S.reject(),S;(y=w.clk)&&(b=y.name)&&!y.disabled&&(f.extraData=f.extraData||{},f.extraData[b]=y.value,"image"===y.type&&(f.extraData[b+".x"]=w.clk_x,f.extraData[b+".y"]=w.clk_y));var A=1,L=2,F=e("meta[name=csrf-token]").attr("content"),E=e("meta[name=csrf-param]").attr("content");E&&F&&(f.extraData=f.extraData||{},f.extraData[E]=F),f.forceSync?i():setTimeout(i,10);var M,O,X,C=50,q=e.parseXML||function(e,t){return window.ActiveXObject?((t=new ActiveXObject("Microsoft.XMLDOM")).async="false",t.loadXML(e)):t=(new DOMParser).parseFromString(e,"text/xml"),t&&t.documentElement&&"parsererror"!==t.documentElement.nodeName?t:null},_=e.parseJSON||function(e){return window.eval("("+e+")")},N=function(t,r,a){var n=t.getResponseHeader("content-type")||"",i=("xml"===r||!r)&&n.indexOf("xml")>=0,o=i?t.responseXML:t.responseText;return i&&"parsererror"===o.documentElement.nodeName&&e.error&&e.error("parsererror"),a&&a.dataFilter&&(o=a.dataFilter(o,r)),"string"==typeof o&&(("json"===r||!r)&&n.indexOf("json")>=0?o=_(o):("script"===r||!r)&&n.indexOf("javascript")>=0&&e.globalEval(o)),o};return S}if(!this.length)return a("ajaxSubmit: skipping submit process - no element selected"),this;var l,f,d,p=this;"function"==typeof t?t={success:t}
5483:"string"==typeof t||!1===t&&arguments.length>0?(t={url:t,data:r,dataType:n},"function"==typeof s&&(t.success=s)):void 0===t&&(t={}),l=t.method||t.type||this.attr2("method"),(d=(d="string"==typeof(f=t.url||this.attr2("action"))?e.trim(f):"")||window.location.href||"")&&(d=(d.match(/^([^#]+)/)||[])[1]),t=e.extend(!0,{url:d,success:e.ajaxSettings.success,type:l||e.ajaxSettings.type,iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank"},t);var m={};if(this.trigger("form-pre-serialize",[this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-pre-serialize trigger"),this;if(t.beforeSerialize&&!1===t.beforeSerialize(this,t))return a("ajaxSubmit: submit aborted via beforeSerialize callback"),this;var h=t.traditional;void 0===h&&(h=e.ajaxSettings.traditional);var v,g=[],x=this.formToArray(t.semantic,g,t.filtering);if(t.data){var y=e.isFunction(t.data)?t.data(x):t.data;t.extraData=y,v=e.param(y,h)}if(t.beforeSubmit&&!1===t.beforeSubmit(x,this,t))return a("ajaxSubmit: submit aborted via beforeSubmit callback"),this;if(this.trigger("form-submit-validate",[x,this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-submit-validate trigger"),this;var b=e.param(x,h);v&&(b=b?b+"&"+v:v),"GET"===t.type.toUpperCase()?(t.url+=(t.url.indexOf("?")>=0?"&":"?")+b,t.data=null):t.data=b;var T=[];
vendor: 5,675 bytes, line 5483
5483if(t.resetForm&&T.push(function(){p.resetForm()}),t.clearForm&&T.push(function(){p.clearForm(t.includeHidden)}),!t.dataType&&t.target){var j=t.success||function(){};T.push(function(r,a,n){var i=arguments,o=t.replaceTarget?"replaceWith":"html";e(t.target)[o](r).each(function(){j.apply(this,i)})})}else t.success&&(e.isArray(t.success)?e.merge(T,t.success):T.push(t.success));if(t.success=function(e,r,a){for(var n=t.context||this,i=0,o=T.length;i<o;i++)T[i].apply(n,[e,r,a||p,p])},t.error){var w=t.error;t.error=function(e,r,a){var n=t.context||this;w.apply(n,[e,r,a,p])}}if(t.complete){var S=t.complete;t.complete=function(e,r){var a=t.context||this;S.apply(a,[e,r,p])}}var k=e("input[type=file]:enabled",this).filter(function(){return""!==e(this).val()}).length>0,D="multipart/form-data",A=p.attr("enctype")===D||p.attr("encoding")===D,L=i.fileapi&&i.formdata;a("fileAPI :"+L);var F,E=(k||A)&&!L;!1!==t.iframe&&(t.iframe||E)?t.closeKeepAlive?e.get(t.closeKeepAlive,function(){F=c(x)}):F=c(x):F=(k||A)&&L?function(r){for(var a=new FormData,n=0;n<r.length;n++)a.append(r[n].name,r[n].value);if(t.extraData){var i=u(t.extraData);for(n=0;n<i.length;n++)i[n]&&a.append(i[n][0],i[n][1])}t.data=null;var o=e.extend(!0,{},e.ajaxSettings,t,{contentType:!1,processData:!1,cache:!1,type:l||"POST"});t.uploadProgress&&(o.xhr=function(){var r=e.ajaxSettings.xhr();return r.upload&&r.upload.addEventListener("progress",function(e){var r=0,a=e.loaded||e.position,n=e.total;e.lengthComputable&&(r=Math.ceil(a/n*100)),t.uploadProgress(e,a,n,r)},!1),r}),o.data=null;var s=o.beforeSend;return o.beforeSend=function(e,r){t.formData?r.data=t.formData:r.data=a,s&&s.call(this,e,r)},e.ajax(o)}(x):e.ajax(t),p.removeData("jqxhr").data("jqxhr",F);for(var M=0;M<g.length;M++)g[M]=null;return this.trigger("form-submit-notify",[this,t]),this},e.fn.ajaxForm=function(n,i,o,s){if(("string"==typeof n||!1===n&&arguments.length>0)&&(n={url:n,data:i,dataType:o},"function"==typeof s&&(n.success=s)),n=n||{},n.delegation=n.delegation&&e.isFunction(e.fn.on),!n.delegation&&0===this.length){var u={s:this.selector,c:this.context};return!e.isReady&&u.s?(a("DOM not ready, queuing ajaxForm"),e(function(){e(u.s,u.c).ajaxForm(n)}),this):(a("terminating; zero elements found by selector"+(e.isReady?"":" (DOM not ready)")),this)}return n.delegation?(e(document).off("submit.form-plugin",this.selector,t).off("click.form-plugin",this.selector,r).on("submit.form-plugin",this.selector,n,t).on("click.form-plugin",this.selector,n,r),this):this.ajaxFormUnbind().on("submit.form-plugin",n,t).on("click.form-plugin",n,r)},e.fn.ajaxFormUnbind=function(){return this.off("submit.form-plugin click.form-plugin")},e.fn.formToArray=function(t,r,a){var n=[];if(0===this.length)return n;var o,s=this[0],u=this.attr("id"),c=t||void 0===s.elements?s.getElementsByTagName("*"):s.elements;if(c&&(c=e.makeArray(c)),u&&(t||/(Edge|Trident)\//.test(navigator.userAgent))&&(o=e(':input[form="'+u+'"]').get()).length&&(c=(c||[]).concat(o)),!c||!c.length)return n;e.isFunction(a)&&(c=e.map(c,a));var l,f,d,p,m,h,v;for(l=0,h=c.length;l<h;l++)if(m=c[l],(d=m.name)&&!m.disabled)if(t&&s.clk&&"image"===m.type)s.clk===m&&(n.push({name:d,value:e(m).val(),type:m.type}),n.push({name:d+".x",value:s.clk_x},{name:d+".y",value:s.clk_y}));else if((p=e.fieldValue(m,!0))&&p.constructor===Array)for(r&&r.push(m),f=0,v=p.length;f<v;f++)n.push({name:d,value:p[f]});else if(i.fileapi&&"file"===m.type){r&&r.push(m);var g=m.files;if(g.length)for(f=0;f<g.length;f++)n.push({name:d,value:g[f],type:m.type});else n.push({name:d,value:"",type:m.type})}else null!==p&&void 0!==p&&(r&&r.push(m),n.push({name:d,value:p,type:m.type,required:m.required}));if(!t&&s.clk){var x=e(s.clk),y=x[0];(d=y.name)&&!y.disabled&&"image"===y.type&&(n.push({name:d,value:x.val()}),n.push({name:d+".x",value:s.clk_x},{name:d+".y",value:s.clk_y}))}return n},e.fn.formSerialize=function(t){return e.param(this.formToArray(t))},e.fn.fieldSerialize=function(t){var r=[];return this.each(function(){var a=this.name;if(a){var n=e.fieldValue(this,t);if(n&&n.constructor===Array)for(var i=0,o=n.length;i<o;i++)r.push({name:a,value:n[i]});else null!==n&&void 0!==n&&r.push({name:this.name,value:n})}}),e.param(r)},e.fn.fieldValue=function(t){for(var r=[],a=0,n=this.length;a<n;a++){var i=this[a],o=e.fieldValue(i,t);null===o||void 0===o||o.constructor===Array&&!o.length||(o.constructor===Array?e.merge(r,o):r.push(o))}return r},e.fieldValue=function(t,r){var a=t.name,i=t.type,o=t.tagName.toLowerCase();if(void 0===r&&(r=!0),r&&(!a||t.disabled||"reset"===i||"button"===i||("checkbox"===i||"radio"===i)&&!t.checked||("submit"===i||"image"===i)&&t.form&&t.form.clk!==t||"select"===o&&-1===t.selectedIndex))return null;if("select"===o){var s=t.selectedIndex;if(s<0)return null;for(var u=[],c=t.options,l="select-one"===i,f=l?s+1:c.length,d=l?s:0;d<f;d++){var p=c[d];if(p.selected&&!p.disabled){var m=p.value;if(m||(m=p.attributes&&p.attributes.value&&!p.attributes.value.specified?p.text:p.value),l)return m;u.push(m)}}return u}return e(t).val().replace(n,"\r\n")},e.fn.clearForm=function(t){return this.each(function(){e("input,select,textarea",this).clearFields(t)})},e.fn.clearFields=e.fn.clearInputs=function(t){var r=/^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i;return this.each(function(){var a=this.type,n=this.tagName.toLowerCase();r.test(a)||"textarea"===n?this.value="":"checkbox"===a||"radio"===a?this.checked=!1:"select"===n?this.selectedIndex=-1:"file"===a?/MSIE/.test(navigator.userAgent)?e(this).replaceWith(e(this).clone(!0)):e(this).val(""):t&&(!0===t&&/hidden/.test(a)||"string"==typeof t&&e(this).is(t))&&(this.value="")}
5483)},e.fn.resetForm=function(){return this.each(function(){var t=e(this),r=this.tagName.toLowerCase();switch(r){case"input":this.checked=this.defaultChecked;case"textarea":return this.value=this.defaultValue,!0;case"option":case"optgroup":var a=t.parents("select");return a.length&&a[0].multiple?"option"===r?this.selected=this.defaultSelected:t.find("option").resetForm():a.resetForm(),!0;case"select":return t.find("option").each(function(e){if(this.selected=this.defaultSelected,this.defaultSelected&&!t[0].multiple)return t[0].selectedIndex=e,!1}),!0;case"label":var n=e(t.attr("for")),i=t.find("input,select,textarea");return n[0]&&i.unshift(n[0]),i.resetForm(),!0;case"form":return("function"==typeof this.reset||"object"==typeof this.reset&&!this.reset.nodeType)&&this.reset(),!0;default:return t.find("form,input,label,select,textarea").resetForm(),!0}})},e.fn.enable=function(e){return void 0===e&&(e=!0),this.each(function(){this.disabled=!e})},e.fn.selected=function(t){return void 0===t&&(t=!0),this.each(function(){var r=this.type;if("checkbox"===r||"radio"===r)this.checked=t;else if("option"===this.tagName.toLowerCase()){var a=e(this).parent("select");t&&a[0]&&"select-one"===a[0].type&&a.find("option").selected(!1),this.selected=t}})},e.fn.ajaxSubmit.debug=!1});
5484//# sourceMappingURL=jquery.form.min.js.map
5485
vendor: 10,224 bytes, lines 5486-5784
5486/*!
5487 * jQuery blockUI plugin
5488 * Version 2.70.0-2014.11.23
5489 * Requires jQuery v1.7 or later
5490 *
5491 * Examples at: http://malsup.com/jquery/block/
5492 * Copyright (c) 2007-2013 M. Alsup
5493 * Dual licensed under the MIT and GPL licenses:
5494 * http://www.opensource.org/licenses/mit-license.php
5495 * http://www.gnu.org/licenses/gpl.html
5496 *
5497 * Thanks to Amir-Hossein Sobhi for some excellent contributions!
5498 */
5499
5500;(function() {
5501/*jshint eqeqeq:false curly:false latedef:false */
5502"use strict";
5503
5504	function setup($) {
5505		$.fn._fadeIn = $.fn.fadeIn;
5506
5507		var noOp = $.noop || function() {};
5508
5509		// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
5510		// confusing userAgent strings on Vista)
5511		var msie = /MSIE/.test(navigator.userAgent);
5512		var ie6  = /MSIE 6.0/.test(navigator.userAgent) && ! /MSIE 8.0/.test(navigator.userAgent);
5513		var mode = document.documentMode || 0;
5514		var setExpr = $.isFunction( document.createElement('div').style.setExpression );
5515
5516		// global $ methods for blocking/unblocking the entire page
5517		$.blockUI   = function(opts) { install(window, opts); };
5518		$.unblockUI = function(opts) { remove(window, opts); };
5519
5520		// convenience method for quick growl-like notifications  (http://www.google.com/search?q=growl)
5521		$.growlUI = function(title, message, timeout, onClose) {
5522			var $m = $('<div class="growlUI"></div>');
5523			if (title) $m.append('<h1>'+title+'</h1>');
5524			if (message) $m.append('<h2>'+message+'</h2>');
5525			if (timeout === undefined) timeout = 3000;
5526
5527			// Added by konapun: Set timeout to 30 seconds if this growl is moused over, like normal toast notifications
5528			var callBlock = function(opts) {
5529				opts = opts || {};
5530
5531				$.blockUI({
5532					message: $m,
5533					fadeIn : typeof opts.fadeIn  !== 'undefined' ? opts.fadeIn  : 700,
5534					fadeOut: typeof opts.fadeOut !== 'undefined' ? opts.fadeOut : 1000,
5535					timeout: typeof opts.timeout !== 'undefined' ? opts.timeout : timeout,
5536					centerY: false,
5537					showOverlay: false,
5538					onUnblock: onClose,
5539					css: $.blockUI.defaults.growlCSS
5540				});
5541			};
5542
5543			callBlock();
5544			var nonmousedOpacity = $m.css('opacity');
5545			$m.mouseover(function() {
5546				callBlock({
5547					fadeIn: 0,
5548					timeout: 30000
5549				});
5550
5551				var displayBlock = $('.blockMsg');
5552				displayBlock.stop(); // cancel fadeout if it has started
5553				displayBlock.fadeTo(300, 1); // make it easier to read the message by removing transparency
5554			}).mouseout(function() {
5555				$('.blockMsg').fadeOut(1000);
5556			});
5557			// End konapun additions
5558		};
5559
5560		// plugin method for blocking element content
5561		$.fn.block = function(opts) {
5562			if ( this[0] === window ) {
5563				$.blockUI( opts );
5564				return this;
5565			}
5566			var fullOpts = $.extend({}, $.blockUI.defaults, opts || {});
5567			this.each(function() {
5568				var $el = $(this);
5569				if (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked'))
5570					return;
5571				$el.unblock({ fadeOut: 0 });
5572			});
5573
5574			return this.each(function() {
5575				if ($.css(this,'position') == 'static') {
5576					this.style.position = 'relative';
5577					$(this).data('blockUI.static', true);
5578				}
5579				this.style.zoom = 1; // force 'hasLayout' in ie
5580				install(this, opts);
5581			});
5582		};
5583
5584		// plugin method for unblocking element content
5585		$.fn.unblock = function(opts) {
5586			if ( this[0] === window ) {
5587				$.unblockUI( opts );
5588				return this;
5589			}
5590			return this.each(function() {
5591				remove(this, opts);
5592			});
5593		};
5594
5595		$.blockUI.version = 2.70; // 2nd generation blocking at no extra cost!
5596
5597		// override these in your code to change the default behavior and style
5598		$.blockUI.defaults = {
5599			// message displayed when blocking (use null for no message)
5600			message:  '<h1>Please wait...</h1>',
5601
5602			title: null,		// title string; only used when theme == true
5603			draggable: true,	// only used when theme == true (requires jquery-ui.js to be loaded)
5604
5605			theme: false, // set to true to use with jQuery UI themes
5606
5607			// styles for the message when blocking; if you wish to disable
5608			// these and use an external stylesheet then do this in your code:
5609			// $.blockUI.defaults.css = {};
5610			css: {
5611				padding:	0,
5612				margin:		0,
5613				width:		'30%',
5614				top:		'40%',
5615				left:		'35%',
5616				textAlign:	'center',
5617				color:		'#000',
5618				border:		'3px solid #aaa',
5619				backgroundColor:'#fff',
5620				cursor:		'wait'
5621			},
5622
5623			// minimal style set used when themes are used
5624			themedCSS: {
5625				width:	'30%',
5626				top:	'40%',
5627				left:	'35%'
5628			},
5629
5630			// styles for the overlay
5631			overlayCSS:  {
5632				backgroundColor:	'#000',
5633				opacity:			0.6,
5634				cursor:				'wait'
5635			},
5636
5637			// style to replace wait cursor before unblocking to correct issue
5638			// of lingering wait cursor
5639			cursorReset: 'default',
5640
5641			// styles applied when using $.growlUI
5642			growlCSS: {
5643				width:		'350px',
5644				top:		'10px',
5645				left:		'',
5646				right:		'10px',
5647				border:		'none',
5648				padding:	'5px',
5649				opacity:	0.6,
5650				cursor:		'default',
5651				color:		'#fff',
5652				backgroundColor: '#000',
5653				'-webkit-border-radius':'10px',
5654				'-moz-border-radius':	'10px',
5655				'border-radius':		'10px'
5656			},
5657
5658			// IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
5659			// (hat tip to Jorge H. N. de Vasconcelos)
5660			/*jshint scripturl:true */
5661			iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',
5662
5663			// force usage of iframe in non-IE browsers (handy for blocking applets)
5664			forceIframe: false,
5665
5666			// z-index for the blocking overlay
5667			baseZ: 1000,
5668
5669			// set these to true to have the message automatically centered
5670			centerX: true, // <-- only effects element blocking (page block controlled via css above)
5671			centerY: true,
5672
5673			// allow body element to be stetched in ie6; this makes blocking look better
5674			// on "short" pages.  disable if you wish to prevent changes to the body height
5675			allowBodyStretch: true,
5676
5677			// enable if you want key and mouse events to be disabled for content that is blocked
5678			bindEvents: true,
5679
5680			// be default blockUI will supress tab navigation from leaving blocking content
5681			// (if bindEvents is true)
5682			constrainTabKey: true,
5683
5684			// fadeIn time in millis; set to 0 to disable fadeIn on block
5685			fadeIn:  200,
5686
5687			// fadeOut time in millis; set to 0 to disable fadeOut on unblock
5688			fadeOut:  400,
5689
5690			// time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
5691			timeout: 0,
5692
5693			// disable if you don't want to show the overlay
5694			showOverlay: true,
5695
5696			// if true, focus will be placed in the first available input field when
5697			// page blocking
5698			focusInput: true,
5699
5700            // elements that can receive focus
5701            focusableElements: ':input:enabled:visible',
5702
5703			// suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
5704			// no longer needed in 2012
5705			// applyPlatformOpacityRules: true,
5706
5707			// callback method invoked when fadeIn has completed and blocking message is visible
5708			onBlock: null,
5709
5710			// callback method invoked when unblocking has completed; the callback is
5711			// passed the element that has been unblocked (which is the window object for page
5712			// blocks) and the options that were passed to the unblock call:
5713			//	onUnblock(element, options)
5714			onUnblock: null,
5715
5716			// callback method invoked when the overlay area is clicked.
5717			// setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used.
5718			onOverlayClick: null,
5719
5720			// don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
5721			quirksmodeOffsetHack: 4,
5722
5723			// class name of the message block
5724			blockMsgClass: 'blockMsg',
5725
5726			// if it is already blocked, then ignore it (don't unblock and reblock)
5727			ignoreIfBlocked: false
5728		};
5729
5730		// private data and functions follow...
5731
5732		var pageBlock = null;
5733		var pageBlockEls = [];
5734
5735		function install(el, opts) {
5736			var css, themedCSS;
5737			var full = (el == window);
5738			var msg = (opts && opts.message !== undefined ? opts.message : undefined);
5739			opts = $.extend({}, $.blockUI.defaults, opts || {});
5740
5741			if (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked'))
5742				return;
5743
5744			opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
5745			css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
5746			if (opts.onOverlayClick)
5747				opts.overlayCSS.cursor = 'pointer';
5748
5749			themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});
5750			msg = msg === undefined ? opts.message : msg;
5751
5752			// remove the current block (if there is one)
5753			if (full && pageBlock)
5754				remove(window, {fadeOut:0});
5755
5756			// if an existing element is being used as the blocking content then we capture
5757			// its current place in the DOM (and current display style) so we can restore
5758			// it when we unblock
5759			if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
5760				var node = msg.jquery ? msg[0] : msg;
5761				var data = {};
5762				$(el).data('blockUI.history', data);
5763				data.el = node;
5764				data.parent = node.parentNode;
5765				data.display = node.style.display;
5766				data.position = node.style.position;
5767				if (data.parent)
5768					data.parent.removeChild(node);
5769			}
5770
5771			$(el).data('blockUI.onUnblock', opts.onUnblock);
5772			var z = opts.baseZ;
5773
5774			// blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
5775			// layer1 is the iframe layer which is used to supress bleed through of underlying content
5776			// layer2 is the overlay layer which has opacity and a wait cursor (by default)
5777			// layer3 is the message content that is displayed while blocking
5778			var lyr1, lyr2, lyr3, s;
5779			if (msie || opts.forceIframe)
5780				lyr1 = $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>');
5781			else
5782				lyr1 = $('<div class="blockUI" style="display:none"></div>');
5783
5784			if (opts.theme)
vendor: 10,500 bytes, lines 5785-6110
5785				lyr2 = $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z++) +';display:none"></div>');
5786			else
5787				lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
5788
5789			if (opts.theme && full) {
5790				s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:fixed">';
5791				if ( opts.title ) {
5792					s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || '&nbsp;')+'</div>';
5793				}
5794				s += '<div class="ui-widget-content ui-dialog-content"></div>';
5795				s += '</div>';
5796			}
5797			else if (opts.theme) {
5798				s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:absolute">';
5799				if ( opts.title ) {
5800					s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || '&nbsp;')+'</div>';
5801				}
5802				s += '<div class="ui-widget-content ui-dialog-content"></div>';
5803				s += '</div>';
5804			}
5805			else if (full) {
5806				s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>';
5807			}
5808			else {
5809				s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>';
5810			}
5811			lyr3 = $(s);
5812
5813			// if we have a message, style it
5814			if (msg) {
5815				if (opts.theme) {
5816					lyr3.css(themedCSS);
5817					lyr3.addClass('ui-widget-content');
5818				}
5819				else
5820					lyr3.css(css);
5821			}
5822
5823			// style the overlay
5824			if (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/)
5825				lyr2.css(opts.overlayCSS);
5826			lyr2.css('position', full ? 'fixed' : 'absolute');
5827
5828			// make iframe layer transparent in IE
5829			if (msie || opts.forceIframe)
5830				lyr1.css('opacity',0.0);
5831
5832			//$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
5833			var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);
5834			$.each(layers, function() {
5835				this.appendTo($par);
5836			});
5837
5838			if (opts.theme && opts.draggable && $.fn.draggable) {
5839				lyr3.draggable({
5840					handle: '.ui-dialog-titlebar',
5841					cancel: 'li'
5842				});
5843			}
5844
5845			// ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
5846			var expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0);
5847			if (ie6 || expr) {
5848				// give body 100% height
5849				if (full && opts.allowBodyStretch && $.support.boxModel)
5850					$('html,body').css('height','100%');
5851
5852				// fix ie6 issue when blocked element has a border width
5853				if ((ie6 || !$.support.boxModel) && !full) {
5854					var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
5855					var fixT = t ? '(0 - '+t+')' : 0;
5856					var fixL = l ? '(0 - '+l+')' : 0;
5857				}
5858
5859				// simulate fixed position
5860				$.each(layers, function(i,o) {
5861					var s = o[0].style;
5862					s.position = 'absolute';
5863					if (i < 2) {
5864						if (full)
5865							s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"');
5866						else
5867							s.setExpression('height','this.parentNode.offsetHeight + "px"');
5868						if (full)
5869							s.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"');
5870						else
5871							s.setExpression('width','this.parentNode.offsetWidth + "px"');
5872						if (fixL) s.setExpression('left', fixL);
5873						if (fixT) s.setExpression('top', fixT);
5874					}
5875					else if (opts.centerY) {
5876						if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
5877						s.marginTop = 0;
5878					}
5879					else if (!opts.centerY && full) {
5880						var top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0;
5881						var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
5882						s.setExpression('top',expression);
5883					}
5884				});
5885			}
5886
5887			// show the message
5888			if (msg) {
5889				if (opts.theme)
5890					lyr3.find('.ui-widget-content').append(msg);
5891				else
5892					lyr3.append(msg);
5893				if (msg.jquery || msg.nodeType)
5894					$(msg).show();
5895			}
5896
5897			if ((msie || opts.forceIframe) && opts.showOverlay)
5898				lyr1.show(); // opacity is zero
5899			if (opts.fadeIn) {
5900				var cb = opts.onBlock ? opts.onBlock : noOp;
5901				var cb1 = (opts.showOverlay && !msg) ? cb : noOp;
5902				var cb2 = msg ? cb : noOp;
5903				if (opts.showOverlay)
5904					lyr2._fadeIn(opts.fadeIn, cb1);
5905				if (msg)
5906					lyr3._fadeIn(opts.fadeIn, cb2);
5907			}
5908			else {
5909				if (opts.showOverlay)
5910					lyr2.show();
5911				if (msg)
5912					lyr3.show();
5913				if (opts.onBlock)
5914					opts.onBlock.bind(lyr3)();
5915			}
5916
5917			// bind key and mouse events
5918			bind(1, el, opts);
5919
5920			if (full) {
5921				pageBlock = lyr3[0];
5922				pageBlockEls = $(opts.focusableElements,pageBlock);
5923				if (opts.focusInput)
5924					setTimeout(focus, 20);
5925			}
5926			else
5927				center(lyr3[0], opts.centerX, opts.centerY);
5928
5929			if (opts.timeout) {
5930				// auto-unblock
5931				var to = setTimeout(function() {
5932					if (full)
5933						$.unblockUI(opts);
5934					else
5935						$(el).unblock(opts);
5936				}, opts.timeout);
5937				$(el).data('blockUI.timeout', to);
5938			}
5939		}
5940
5941		// remove the block
5942		function remove(el, opts) {
5943			var count;
5944			var full = (el == window);
5945			var $el = $(el);
5946			var data = $el.data('blockUI.history');
5947			var to = $el.data('blockUI.timeout');
5948			if (to) {
5949				clearTimeout(to);
5950				$el.removeData('blockUI.timeout');
5951			}
5952			opts = $.extend({}, $.blockUI.defaults, opts || {});
5953			bind(0, el, opts); // unbind events
5954
5955			if (opts.onUnblock === null) {
5956				opts.onUnblock = $el.data('blockUI.onUnblock');
5957				$el.removeData('blockUI.onUnblock');
5958			}
5959
5960			var els;
5961			if (full) // crazy selector to handle odd field errors in ie6/7
5962				els = $('body').children().filter('.blockUI').add('body > .blockUI');
5963			else
5964				els = $el.find('>.blockUI');
5965
5966			// fix cursor issue
5967			if ( opts.cursorReset ) {
5968				if ( els.length > 1 )
5969					els[1].style.cursor = opts.cursorReset;
5970				if ( els.length > 2 )
5971					els[2].style.cursor = opts.cursorReset;
5972			}
5973
5974			if (full)
5975				pageBlock = pageBlockEls = null;
5976
5977			if (opts.fadeOut) {
5978				count = els.length;
5979				els.stop().fadeOut(opts.fadeOut, function() {
5980					if ( --count === 0)
5981						reset(els,data,opts,el);
5982				});
5983			}
5984			else
5985				reset(els, data, opts, el);
5986		}
5987
5988		// move blocking element back into the DOM where it started
5989		function reset(els,data,opts,el) {
5990			var $el = $(el);
5991			if ( $el.data('blockUI.isBlocked') )
5992				return;
5993
5994			els.each(function(i,o) {
5995				// remove via DOM calls so we don't lose event handlers
5996				if (this.parentNode)
5997					this.parentNode.removeChild(this);
5998			});
5999
6000			if (data && data.el) {
6001				data.el.style.display = data.display;
6002				data.el.style.position = data.position;
6003				data.el.style.cursor = 'default'; // #59
6004				if (data.parent)
6005					data.parent.appendChild(data.el);
6006				$el.removeData('blockUI.history');
6007			}
6008
6009			if ($el.data('blockUI.static')) {
6010				$el.css('position', 'static'); // #22
6011			}
6012
6013			if (typeof opts.onUnblock == 'function')
6014				opts.onUnblock(el,opts);
6015
6016			// fix issue in Safari 6 where block artifacts remain until reflow
6017			var body = $(document.body), w = body.width(), cssW = body[0].style.width;
6018			body.width(w-1).width(w);
6019			body[0].style.width = cssW;
6020		}
6021
6022		// bind/unbind the handler
6023		function bind(b, el, opts) {
6024			var full = el == window, $el = $(el);
6025
6026			// don't bother unbinding if there is nothing to unbind
6027			if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
6028				return;
6029
6030			$el.data('blockUI.isBlocked', b);
6031
6032			// don't bind events when overlay is not in use or if bindEvents is false
6033			if (!full || !opts.bindEvents || (b && !opts.showOverlay))
6034				return;
6035
6036			// bind anchors and inputs for mouse and key events
6037			var events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove';
6038			if (b)
6039				$(document).bind(events, opts, handler);
6040			else
6041				$(document).unbind(events, handler);
6042
6043		// former impl...
6044		//		var $e = $('a,:input');
6045		//		b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
6046		}
6047
6048		// event handler to suppress keyboard/mouse events when blocking
6049		function handler(e) {
6050			// allow tab navigation (conditionally)
6051			if (e.type === 'keydown' && e.keyCode && e.keyCode == 9) {
6052				if (pageBlock && e.data.constrainTabKey) {
6053					var els = pageBlockEls;
6054					var fwd = !e.shiftKey && e.target === els[els.length-1];
6055					var back = e.shiftKey && e.target === els[0];
6056					if (fwd || back) {
6057						setTimeout(function(){focus(back);},10);
6058						return false;
6059					}
6060				}
6061			}
6062			var opts = e.data;
6063			var target = $(e.target);
6064			if (target.hasClass('blockOverlay') && opts.onOverlayClick)
6065				opts.onOverlayClick(e);
6066
6067			// allow events within the message content
6068			if (target.parents('div.' + opts.blockMsgClass).length > 0)
6069				return true;
6070
6071			// allow events for content that is not being blocked
6072			return target.parents().children().filter('div.blockUI').length === 0;
6073		}
6074
6075		function focus(back) {
6076			if (!pageBlockEls)
6077				return;
6078			var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
6079			if (e)
6080				e.focus();
6081		}
6082
6083		function center(el, x, y) {
6084			var p = el.parentNode, s = el.style;
6085			var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
6086			var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
6087			if (x) s.left = l > 0 ? (l+'px') : '0';
6088			if (y) s.top  = t > 0 ? (t+'px') : '0';
6089		}
6090
6091		function sz(el, p) {
6092			return parseInt($.css(el,p),10)||0;
6093		}
6094
6095	}
6096
6097
6098	/*global define:true */
6099	if (typeof define === 'function' && define.amd) {
6100		// AMD. Register as an anonymous module.
6101		define(['jquery'], setup);
6102	} else if (typeof exports === 'object') {
6103		// Node/CommonJS
6104		setup(require('jquery'));
6105	} else {
6106		// Browser globals
6107		setup(jQuery);
6108	}
6109
6110})();
vendor: 16,416 bytes, lines 6111-6118
6111
6112/*!
6113 * Datepicker for Bootstrap v1.8.0 (https://github.com/uxsolutions/bootstrap-datepicker)
6114 *
6115 * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
6116 */
6117
6118!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a,b){function c(){return new Date(Date.UTC.apply(Date,arguments))}function d(){var a=new Date;return c(a.getFullYear(),a.getMonth(),a.getDate())}function e(a,b){return a.getUTCFullYear()===b.getUTCFullYear()&&a.getUTCMonth()===b.getUTCMonth()&&a.getUTCDate()===b.getUTCDate()}function f(c,d){return function(){return d!==b&&a.fn.datepicker.deprecated(d),this[c].apply(this,arguments)}}function g(a){return a&&!isNaN(a.getTime())}function h(b,c){function d(a,b){return b.toLowerCase()}var e,f=a(b).data(),g={},h=new RegExp("^"+c.toLowerCase()+"([A-Z])");c=new RegExp("^"+c.toLowerCase());for(var i in f)c.test(i)&&(e=i.replace(h,d),g[e]=f[i]);return g}function i(b){var c={};if(q[b]||(b=b.split("-")[0],q[b])){var d=q[b];return a.each(p,function(a,b){b in d&&(c[b]=d[b])}),c}}var j=function(){var b={get:function(a){return this.slice(a)[0]},contains:function(a){for(var b=a&&a.valueOf(),c=0,d=this.length;c<d;c++)if(0<=this[c].valueOf()-b&&this[c].valueOf()-b<864e5)return c;return-1},remove:function(a){this.splice(a,1)},replace:function(b){b&&(a.isArray(b)||(b=[b]),this.clear(),this.push.apply(this,b))},clear:function(){this.length=0},copy:function(){var a=new j;return a.replace(this),a}};return function(){var c=[];return c.push.apply(c,arguments),a.extend(c,b),c}}(),k=function(b,c){a.data(b,"datepicker",this),this._process_options(c),this.dates=new j,this.viewDate=this.o.defaultViewDate,this.focusDate=null,this.element=a(b),this.isInput=this.element.is("input"),this.inputField=this.isInput?this.element:this.element.find("input"),this.component=!!this.element.hasClass("date")&&this.element.find(".add-on, .input-group-addon, .btn"),this.component&&0===this.component.length&&(this.component=!1),this.isInline=!this.component&&this.element.is("div"),this.picker=a(r.template),this._check_template(this.o.templates.leftArrow)&&this.picker.find(".prev").html(this.o.templates.leftArrow),this._check_template(this.o.templates.rightArrow)&&this.picker.find(".next").html(this.o.templates.rightArrow),this._buildEvents(),this._attachEvents(),this.isInline?this.picker.addClass("datepicker-inline").appendTo(this.element):this.picker.addClass("datepicker-dropdown dropdown-menu"),this.o.rtl&&this.picker.addClass("datepicker-rtl"),this.o.calendarWeeks&&this.picker.find(".datepicker-days .datepicker-switch, thead .datepicker-title, tfoot .today, tfoot .clear").attr("colspan",function(a,b){return Number(b)+1}),this._process_options({startDate:this._o.startDate,endDate:this._o.endDate,daysOfWeekDisabled:this.o.daysOfWeekDisabled,daysOfWeekHighlighted:this.o.daysOfWeekHighlighted,datesDisabled:this.o.datesDisabled}),this._allow_update=!1,this.setViewMode(this.o.startView),this._allow_update=!0,this.fillDow(),this.fillMonths(),this.update(),this.isInline&&this.show()};k.prototype={constructor:k,_resolveViewName:function(b){return a.each(r.viewModes,function(c,d){if(b===c||a.inArray(b,d.names)!==-1)return b=c,!1}),b},_resolveDaysOfWeek:function(b){return a.isArray(b)||(b=b.split(/[,\s]*/)),a.map(b,Number)},_check_template:function(c){try{if(c===b||""===c)return!1;if((c.match(/[<>]/g)||[]).length<=0)return!0;var d=a(c);return d.length>0}catch(a){return!1}},_process_options:function(b){this._o=a.extend({},this._o,b);var e=this.o=a.extend({},this._o),f=e.language;q[f]||(f=f.split("-")[0],q[f]||(f=o.language)),e.language=f,e.startView=this._resolveViewName(e.startView),e.minViewMode=this._resolveViewName(e.minViewMode),e.maxViewMode=this._resolveViewName(e.maxViewMode),e.startView=Math.max(this.o.minViewMode,Math.min(this.o.maxViewMode,e.startView)),e.multidate!==!0&&(e.multidate=Number(e.multidate)||!1,e.multidate!==!1&&(e.multidate=Math.max(0,e.multidate))),e.multidateSeparator=String(e.multidateSeparator),e.weekStart%=7,e.weekEnd=(e.weekStart+6)%7;var g=r.parseFormat(e.format);e.startDate!==-(1/0)&&(e.startDate?e.startDate instanceof Date?e.startDate=this._local_to_utc(this._zero_time(e.startDate)):e.startDate=r.parseDate(e.startDate,g,e.language,e.assumeNearbyYear):e.startDate=-(1/0)),e.endDate!==1/0&&(e.endDate?e.endDate instanceof Date?e.endDate=this._local_to_utc(this._zero_time(e.endDate)):e.endDate=r.parseDate(e.endDate,g,e.language,e.assumeNearbyYear):e.endDate=1/0),e.daysOfWeekDisabled=this._resolveDaysOfWeek(e.daysOfWeekDisabled||[]),e.daysOfWeekHighlighted=this._resolveDaysOfWeek(e.daysOfWeekHighlighted||[]),e.datesDisabled=e.datesDisabled||[],a.isArray(e.datesDisabled)||(e.datesDisabled=e.datesDisabled.split(",")),e.datesDisabled=a.map(e.datesDisabled,function(a){return r.parseDate(a,g,e.language,e.assumeNearbyYear)});var h=String(e.orientation).toLowerCase().split(/\s+/g),i=e.orientation.toLowerCase();if(h=a.grep(h,function(a){return/^auto|left|right|top|bottom$/.test(a)}),e.orientation={x:"auto",y:"auto"},i&&"auto"!==i)if(1===h.length)switch(h[0]){case"top":case"bottom":e.orientation.y=h[0];break;case"left":case"right":e.orientation.x=h[0]}else i=a.grep(h,function(a){return/^left|right$/.test(a)}),e.orientation.x=i[0]||"auto",i=a.grep(h,function(a){return/^top|bottom$/.test(a)}),e.orientation.y=i[0]||"auto";else;if(e.defaultViewDate instanceof Date||"string"==typeof e.defaultViewDate)e.defaultViewDate=r.parseDate(e.defaultViewDate,g,e.language,e.assumeNearbyYear);else if(e.defaultViewDate){var j=e.defaultViewDate.year||(new Date).getFullYear(),k=e.defaultViewDate.month||0,l=e.defaultViewDate.day||1;e.defaultViewDate=c(j,k,l)}else e.defaultViewDate=d()},_events:[],_secondaryEvents:[],_applyEvents:function(a){for(var c,d,e,f=0;f<a.length;f++)c=a[f][0],2===a[f].length?(d=b,e=a[f][1]):3===a[f].length&&(d=a[f][1],e=a[f][2]),c.on(e,d)},_unapplyEvents:function(a){for(var c,d,e,f=0;f<a.length;f++)c=a[f][0],2===a[f].length?(e=b,d=a[f][1]):3===a[f].length&&(e=a[f][1],d=a[f][2]),c.off(d,e)},_buildEvents:function(){var b={keyup:a.proxy(function(b){a.inArray(b.keyCode,[27,37,39,38,40,32,13,9])===-1&&this.update()},this),keydown:a.proxy(this.keydown,this),paste:a.proxy(this.paste,this)};this.o.showOnFocus===!0&&(b.focus=a.proxy(this.show,this)),this.isInput?this._events=[[this.element,b]]:this.component&&this.inputField.length?this._events=[[this.inputField,b],[this.component,{click:a.proxy(this.show,this)}]]:this._events=[[this.element,{click:a.proxy(this.show,this),keydown:a.proxy(this.keydown,this)}]],this._events.push([this.element,"*",{blur:a.proxy(function(a){this._focused_from=a.target},this)}],[this.element,{blur:a.proxy(function(a){this._focused_from=a.target},this)}]),this.o.immediateUpdates&&this._events.push([this.element,{"changeYear changeMonth":a.proxy(function(a){this.update(a.date)},this)}]),this._secondaryEvents=[[this.picker,{click:a.proxy(this.click,this)}],[this.picker,".prev, .next",{click:a.proxy(this.navArrowsClick,this)}],[this.picker,".day:not(.disabled)",{click:a.proxy(this.dayCellClick,this)}],[a(window),{resize:a.proxy(this.place,this)}],[a(document),{"mousedown touchstart":a.proxy(function(a){this.element.is(a.target)||this.element.find(a.target).length||this.picker.is(a.target)||this.picker.find(a.target).length||this.isInline||this.hide()},this)}]]},_attachEvents:function(){this._detachEvents(),this._applyEvents(this._events)},_detachEvents:function(){this._unapplyEvents(this._events)},_attachSecondaryEvents:function(){this._detachSecondaryEvents(),this._applyEvents(this._secondaryEvents)},_detachSecondaryEvents:function(){this._unapplyEvents(this._secondaryEvents)},_trigger:function(b,c){var d=c||this.dates.get(-1),e=this._utc_to_local(d);this.element.trigger({type:b,date:e,viewMode:this.viewMode,dates:a.map(this.dates,this._utc_to_local),format:a.proxy(function(a,b){0===arguments.length?(a=this.dates.length-1,b=this.o.format):"string"==typeof a&&(b=a,a=this.dates.length-1),b=b||this.o.format;var c=this.dates.get(a);return r.formatDate(c,b,this.o.language)},this)})},show:function(){if(!(this.inputField.prop("disabled")||this.inputField.prop("readonly")&&this.o.enableOnReadonly===!1))return this.isInline||this.picker.appendTo(this.o.container),this.place(),this.picker.show(),this._attachSecondaryEvents(),this._trigger("show"),(window.navigator.msMaxTouchPoints||"ontouchstart"in document)&&this.o.disableTouchKeyboard&&a(this.element).blur(),this},hide:function(){return this.isInline||!this.picker.is(":visible")?this:(this.focusDate=null,this.picker.hide().detach(),this._detachSecondaryEvents(),this.setViewMode(this.o.startView),this.o.forceParse&&this.inputField.val()&&this.setValue(),this._trigger("hide"),this)},destroy:function(){return this.hide(),this._detachEvents(),this._detachSecondaryEvents(),this.picker.remove(),delete this.element.data().datepicker,this.isInput||delete this.element.data().date,this},paste:function(b){var c;if(b.originalEvent.clipboardData&&b.originalEvent.clipboardData.types&&a.inArray("text/plain",b.originalEvent.clipboardData.types)!==-1)c=b.originalEvent.clipboardData.getData("text/plain");else{if(!window.clipboardData)return;c=window.clipboardData.getData("Text")}this.setDate(c),this.update(),b.preventDefault()},_utc_to_local:function(a){if(!a)return a;var b=new Date(a.getTime()+6e4*a.getTimezoneOffset());return b.getTimezoneOffset()!==a.getTimezoneOffset()&&(b=new Date(a.getTime()+6e4*b.getTimezoneOffset())),b},_local_to_utc:function(a){return a&&new Date(a.getTime()-6e4*a.getTimezoneOffset())},_zero_time:function(a){return a&&new Date(a.getFullYear(),a.getMonth(),a.getDate())},_zero_utc_time:function(a){return a&&c(a.getUTCFullYear(),a.getUTCMonth(),a.getUTCDate())},getDates:function(){return a.map(this.dates,this._utc_to_local)},getUTCDates:function(){return a.map(this.dates,function(a){return new Date(a)})},getDate:function(){return this._utc_to_local(this.getUTCDate())},getUTCDate:function(){var a=this.dates.get(-1);return a!==b?new Date(a):null},clearDates:function(){this.inputField.val(""),this.update(),this._trigger("changeDate"),this.o.autoclose&&this.hide()},setDates:function(){var b=a.isArray(arguments[0])?arguments[0]:arguments;return this.update.apply(this,b),this._trigger("changeDate"),this.setValue(),this},setUTCDates:function(){var b=a.isArray(arguments[0])?arguments[0]:arguments;return this.setDates.apply(this,a.map(b,this._utc_to_local)),this},setDate:f("setDates"),setUTCDate:f("setUTCDates"),remove:f("destroy","Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead"),setValue:function(){var a=this.getFormattedDate();return this.inputField.val(a),this},getFormattedDate:function(c){c===b&&(c=this.o.format);var d=this.o.language;return a.map(this.dates,function(a){return r.formatDate(a,c,d)}).join(this.o.multidateSeparator)},getStartDate:function(){return this.o.startDate},setStartDate:function(a){return this._process_options({startDate:a}),this.update(),this.updateNavArrows(),this},getEndDate:function(){return this.o.endDate},setEndDate:function(a){return this._process_options({endDate:a}),this.update(),this.updateNavArrows(),this},setDaysOfWeekDisabled:function(a){return this._process_options({daysOfWeekDisabled:a}),this.update(),this},setDaysOfWeekHighlighted:function(a){return this._process_options({daysOfWeekHighlighted:a}),this.update(),this},setDatesDisabled:function(a){return this._process_options({datesDisabled:a}),this.update(),this},place:function(){if(this.isInline)return this;var b=this.picker.outerWidth(),c=this.picker.outerHeight(),d=10,e=a(this.o.container),f=e.width(),g="body"===this.o.container?a(document).scrollTop():e.scrollTop(),h=e.offset(),i=[0];this.element.parents().each(function(){var b=a(this).css("z-index");"auto"!==b&&0!==Number(b)&&i.push(Number(b))});var j=Math.max.apply(Math,i)+this.o.zIndexOffset,k=this.component?this.component.parent().offset():this.element.offset(),l=this.component?this.component.outerHeight(!0):this.element.outerHeight(!1),m=this.component?this.component.outerWidth(!0):this.element.outerWidth(!1),n=k.left-h.left,o=k.top-h.top;"body"!==this.o.container&&(o+=g),this.picker.removeClass("datepicker-orient-top datepicker-orient-bottom datepicker-orient-right datepicker-orient-left"),"auto"!==this.o.orientation.x?(this.picker.addClass("datepicker-orient-"+this.o.orientation.x),"right"===this.o.orientation.x&&(n-=b-m)):k.left<0?(this.picker.addClass("datepicker-orient-left"),n-=k.left-d):n+b>f?(this.picker.addClass("datepicker-orient-right"),n+=m-b):this.o.rtl?this.picker.addClass("datepicker-orient-right"):this.picker.addClass("datepicker-orient-left");var p,q=this.o.orientation.y;if("auto"===q&&(p=-g+o-c,q=p<0?"bottom":"top"),this.picker.addClass("datepicker-orient-"+q),"top"===q?o-=c+parseInt(this.picker.css("padding-top")):o+=l,this.o.rtl){var r=f-(n+m);this.picker.css({top:o,right:r,zIndex:j})}else this.picker.css({top:o,left:n,zIndex:j});return this},_allow_update:!0,update:function(){if(!this._allow_update)return this;var b=this.dates.copy(),c=[],d=!1;return arguments.length?(a.each(arguments,a.proxy(function(a,b){b instanceof Date&&(b=this._local_to_utc(b)),c.push(b)},this)),d=!0):(c=this.isInput?this.element.val():this.element.data("date")||this.inputField.val(),c=c&&this.o.multidate?c.split(this.o.multidateSeparator):[c],delete this.element.data().date),c=a.map(c,a.proxy(function(a){return r.parseDate(a,this.o.format,this.o.language,this.o.assumeNearbyYear)},this)),c=a.grep(c,a.proxy(function(a){return!this.dateWithinRange(a)||!a},this),!0),this.dates.replace(c),this.o.updateViewDate&&(this.dates.length?this.viewDate=new Date(this.dates.get(-1)):this.viewDate<this.o.startDate?this.viewDate=new Date(this.o.startDate):this.viewDate>this.o.endDate?this.viewDate=new Date(this.o.endDate):this.viewDate=this.o.defaultViewDate),d?(this.setValue(),this.element.change()):this.dates.length&&String(b)!==String(this.dates)&&d&&(this._trigger("changeDate"),this.element.change()),!this.dates.length&&b.length&&(this._trigger("clearDate"),this.element.change()),this.fill(),this},fillDow:function(){if(this.o.showWeekDays){var b=this.o.weekStart,c="<tr>";for(this.o.calendarWeeks&&(c+='<th class="cw">&#160;</th>');b<this.o.weekStart+7;)c+='<th class="dow',a.inArray(b,this.o.daysOfWeekDisabled)!==-1&&(c+=" disabled"),c+='">'+q[this.o.language].daysMin[b++%7]+"</th>";c+="</tr>",this.picker.find(".datepicker-days thead").append(c)}},fillMonths:function(){for(var a,b=this._utc_to_local(this.viewDate),c="",d=0;d<12;d++)a=b&&b.getMonth()===d?" focused":"",c+='<span class="month'+a+'">'+q[this.o.language].monthsShort[d]+"</span>";this.picker.find(".datepicker-months td").html(c)},setRange:function(b){b&&b.length?this.range=a.map(b,function(a){return a.valueOf()}):delete this.range,this.fill()},getClassNames:function(b){var c=[],f=this.viewDate.getUTCFullYear(),g=this.viewDate.getUTCMonth(),h=d();return b.getUTCFullYear()<f||b.getUTCFullYear()===f&&b.getUTCMonth()<g?c.push("old"):(b.getUTCFullYear()>f||b.getUTCFullYear()===f&&b.getUTCMonth()>g)&&c.push("new"),this.focusDate&&b.valueOf()===this.focusDate.valueOf()&&c.push("focused"),this.o.todayHighlight&&e(b,h)&&c.push("today"),this.dates.contains(b)!==-1&&c.push("active"),this.dateWithinRange(b)||c.push("disabled"),this.dateIsDisabled(b)&&c.push("disabled","disabled-date"),a.inArray(b.getUTCDay(),this.o.daysOfWeekHighlighted)!==-1&&c.push("highlighted"),this.range&&(b>this.range[0]&&b<this.range[this.range.length-1]&&c.push("range"),a.inArray(b.valueOf(),this.range)!==-1&&c.push("selected"),b.valueOf()===this.range[0]&&c.push("range-start"),b.valueOf()===this.range[this.range.length-1]&&c.push("range-end")),c},_fill_yearsView:function(c,d,e,f,g,h,i){for(var j,k,l,m="",n=e/10,o=this.picker.find(c),p=Math.floor(f/e)*e,q=p+9*n,r=Math.floor(this.viewDate.getFullYear()/n)*n,s=a.map(this.dates,function(a){return Math.floor(a.getUTCFullYear()/n)*n}),t=p-n;t<=q+n;t+=n)j=[d],k=null,t===p-n?j.push("old"):t===q+n&&j.push("new"),a.inArray(t,s)!==-1&&j.push("active"),(t<g||t>h)&&j.push("disabled"),t===r&&j.push("focused"),i!==a.noop&&(l=i(new Date(t,0,1)),l===b?l={}:"boolean"==typeof l?l={enabled:l}:"string"==typeof l&&(l={classes:l}),l.enabled===!1&&j.push("disabled"),l.classes&&(j=j.concat(l.classes.split(/\s+/))),l.tooltip&&(k=l.tooltip)),m+='<sp
6118an class="'+j.join(" ")+'"'+(k?' title="'+k+'"':"")+">"+t+"</span>";o.find(".datepicker-switch").text(p+"-"+q),o.find("td").html(m)},fill:function(){var d,e,f=new Date(this.viewDate),g=f.getUTCFullYear(),h=f.getUTCMonth(),i=this.o.startDate!==-(1/0)?this.o.startDate.getUTCFullYear():-(1/0),j=this.o.startDate!==-(1/0)?this.o.startDate.getUTCMonth():-(1/0),k=this.o.endDate!==1/0?this.o.endDate.getUTCFullYear():1/0,l=this.o.endDate!==1/0?this.o.endDate.getUTCMonth():1/0,m=q[this.o.language].today||q.en.today||"",n=q[this.o.language].clear||q.en.clear||"",o=q[this.o.language].titleFormat||q.en.titleFormat;if(!isNaN(g)&&!isNaN(h)){this.picker.find(".datepicker-days .datepicker-switch").text(r.formatDate(f,o,this.o.language)),this.picker.find("tfoot .today").text(m).css("display",this.o.todayBtn===!0||"linked"===this.o.todayBtn?"table-cell":"none"),this.picker.find("tfoot .clear").text(n).css("display",this.o.clearBtn===!0?"table-cell":"none"),this.picker.find("thead .datepicker-title").text(this.o.title).css("display","string"==typeof this.o.title&&""!==this.o.title?"table-cell":"none"),this.updateNavArrows(),this.fillMonths();var p=c(g,h,0),s=p.getUTCDate();p.setUTCDate(s-(p.getUTCDay()-this.o.weekStart+7)%7);var t=new Date(p);p.getUTCFullYear()<100&&t.setUTCFullYear(p.getUTCFullYear()),t.setUTCDate(t.getUTCDate()+42),t=t.valueOf();for(var u,v,w=[];p.valueOf()<t;){if(u=p.getUTCDay(),u===this.o.weekStart&&(w.push("<tr>"),this.o.calendarWeeks)){var x=new Date(+p+(this.o.weekStart-u-7)%7*864e5),y=new Date(Number(x)+(11-x.getUTCDay())%7*864e5),z=new Date(Number(z=c(y.getUTCFullYear(),0,1))+(11-z.getUTCDay())%7*864e5),A=(y-z)/864e5/7+1;w.push('<td class="cw">'+A+"</td>")}v=this.getClassNames(p),v.push("day");var B=p.getUTCDate();this.o.beforeShowDay!==a.noop&&(e=this.o.beforeShowDay(this._utc_to_local(p)),e===b?e={}:"boolean"==typeof e?e={enabled:e}:"string"==typeof e&&(e={classes:e}),e.enabled===!1&&v.push("disabled"),e.classes&&(v=v.concat(e.classes.split(/\s+/))),e.tooltip&&(d=e.tooltip),e.content&&(B=e.content)),v=a.isFunction(a.uniqueSort)?a.uniqueSort(v):a.unique(v),w.push('<td class="'+v.join(" ")+'"'+(d?' title="'+d+'"':"")+' data-date="'+p.getTime().toString()+'">'+B+"</td>"),d=null,u===this.o.weekEnd&&w.push("</tr>"),p.setUTCDate(p.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").html(w.join(""));var C=q[this.o.language].monthsTitle||q.en.monthsTitle||"Months",D=this.picker.find(".datepicker-months").find(".datepicker-switch").text(this.o.maxViewMode<2?C:g).end().find("tbody span").removeClass("active");if(a.each(this.dates,function(a,b){b.getUTCFullYear()===g&&D.eq(b.getUTCMonth()).addClass("active")}),(g<i||g>k)&&D.addClass("disabled"),g===i&&D.slice(0,j).addClass("disabled"),g===k&&D.slice(l+1).addClass("disabled"),this.o.beforeShowMonth!==a.noop){var E=this;a.each(D,function(c,d){var e=new Date(g,c,1),f=E.o.beforeShowMonth(e);f===b?f={}:"boolean"==typeof f?f={enabled:f}:"string"==typeof f&&(f={classes:f}),f.enabled!==!1||a(d).hasClass("disabled")||a(d).addClass("disabled"),f.classes&&a(d).addClass(f.classes),f.tooltip&&a(d).prop("title",f.tooltip)})}this._fill_yearsView(".datepicker-years","year",10,g,i,k,this.o.beforeShowYear),this._fill_yearsView(".datepicker-decades","decade",100,g,i,k,this.o.beforeShowDecade),this._fill_yearsView(".datepicker-centuries","century",1e3,g,i,k,this.o.beforeShowCentury)}},updateNavArrows:function(){if(this._allow_update){var a,b,c=new Date(this.viewDate),d=c.getUTCFullYear(),e=c.getUTCMonth(),f=this.o.startDate!==-(1/0)?this.o.startDate.getUTCFullYear():-(1/0),g=this.o.startDate!==-(1/0)?this.o.startDate.getUTCMonth():-(1/0),h=this.o.endDate!==1/0?this.o.endDate.getUTCFullYear():1/0,i=this.o.endDate!==1/0?this.o.endDate.getUTCMonth():1/0,j=1;switch(this.viewMode){case 4:j*=10;case 3:j*=10;case 2:j*=10;case 1:a=Math.floor(d/j)*j<f,b=Math.floor(d/j)*j+j>h;break;case 0:a=d<=f&&e<g,b=d>=h&&e>i}this.picker.find(".prev").toggleClass("disabled",a),this.picker.find(".next").toggleClass("disabled",b)}},click:function(b){b.preventDefault(),b.stopPropagation();var e,f,g,h;e=a(b.target),e.hasClass("datepicker-switch")&&this.viewMode!==this.o.maxViewMode&&this.setViewMode(this.viewMode+1),e.hasClass("today")&&!e.hasClass("day")&&(this.setViewMode(0),this._setDate(d(),"linked"===this.o.todayBtn?null:"view")),e.hasClass("clear")&&this.clearDates(),e.hasClass("disabled")||(e.hasClass("month")||e.hasClass("year")||e.hasClass("decade")||e.hasClass("century"))&&(this.viewDate.setUTCDate(1),f=1,1===this.viewMode?(h=e.parent().find("span").index(e),g=this.viewDate.getUTCFullYear(),this.viewDate.setUTCMonth(h)):(h=0,g=Number(e.text()),this.viewDate.setUTCFullYear(g)),this._trigger(r.viewModes[this.viewMode-1].e,this.viewDate),this.viewMode===this.o.minViewMode?this._setDate(c(g,h,f)):(this.setViewMode(this.viewMode-1),this.fill())),this.picker.is(":visible")&&this._focused_from&&this._focused_from.focus(),delete this._focused_from},dayCellClick:function(b){var c=a(b.currentTarget),d=c.data("date"),e=new Date(d);this.o.updateViewDate&&(e.getUTCFullYear()!==this.viewDate.getUTCFullYear()&&this._trigger("changeYear",this.viewDate),e.getUTCMonth()!==this.viewDate.getUTCMonth()&&this._trigger("changeMonth",this.viewDate)),this._setDate(e)},navArrowsClick:function(b){var c=a(b.currentTarget),d=c.hasClass("prev")?-1:1;0!==this.viewMode&&(d*=12*r.viewModes[this.viewMode].navStep),this.viewDate=this.moveMonth(this.viewDate,d),this._trigger(r.viewModes[this.viewMode].e,this.viewDate),this.fill()},_toggle_multidate:function(a){var b=this.dates.contains(a);if(a||this.dates.clear(),b!==-1?(this.o.multidate===!0||this.o.multidate>1||this.o.toggleActive)&&this.dates.remove(b):this.o.multidate===!1?(this.dates.clear(),this.dates.push(a)):this.dates.push(a),"number"==typeof this.o.multidate)for(;this.dates.length>this.o.multidate;)this.dates.remove(0)}
vendor: 6,439 bytes, line 6118
6118,_setDate:function(a,b){b&&"date"!==b||this._toggle_multidate(a&&new Date(a)),(!b&&this.o.updateViewDate||"view"===b)&&(this.viewDate=a&&new Date(a)),this.fill(),this.setValue(),b&&"view"===b||this._trigger("changeDate"),this.inputField.trigger("change"),!this.o.autoclose||b&&"date"!==b||this.hide()},moveDay:function(a,b){var c=new Date(a);return c.setUTCDate(a.getUTCDate()+b),c},moveWeek:function(a,b){return this.moveDay(a,7*b)},moveMonth:function(a,b){if(!g(a))return this.o.defaultViewDate;if(!b)return a;var c,d,e=new Date(a.valueOf()),f=e.getUTCDate(),h=e.getUTCMonth(),i=Math.abs(b);if(b=b>0?1:-1,1===i)d=b===-1?function(){return e.getUTCMonth()===h}:function(){return e.getUTCMonth()!==c},c=h+b,e.setUTCMonth(c),c=(c+12)%12;else{for(var j=0;j<i;j++)e=this.moveMonth(e,b);c=e.getUTCMonth(),e.setUTCDate(f),d=function(){return c!==e.getUTCMonth()}}for(;d();)e.setUTCDate(--f),e.setUTCMonth(c);return e},moveYear:function(a,b){return this.moveMonth(a,12*b)},moveAvailableDate:function(a,b,c){do{if(a=this[c](a,b),!this.dateWithinRange(a))return!1;c="moveDay"}while(this.dateIsDisabled(a));return a},weekOfDateIsDisabled:function(b){return a.inArray(b.getUTCDay(),this.o.daysOfWeekDisabled)!==-1},dateIsDisabled:function(b){return this.weekOfDateIsDisabled(b)||a.grep(this.o.datesDisabled,function(a){return e(b,a)}).length>0},dateWithinRange:function(a){return a>=this.o.startDate&&a<=this.o.endDate},keydown:function(a){if(!this.picker.is(":visible"))return void(40!==a.keyCode&&27!==a.keyCode||(this.show(),a.stopPropagation()));var b,c,d=!1,e=this.focusDate||this.viewDate;switch(a.keyCode){case 27:this.focusDate?(this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.fill()):this.hide(),a.preventDefault(),a.stopPropagation();break;case 37:case 38:case 39:case 40:if(!this.o.keyboardNavigation||7===this.o.daysOfWeekDisabled.length)break;b=37===a.keyCode||38===a.keyCode?-1:1,0===this.viewMode?a.ctrlKey?(c=this.moveAvailableDate(e,b,"moveYear"),c&&this._trigger("changeYear",this.viewDate)):a.shiftKey?(c=this.moveAvailableDate(e,b,"moveMonth"),c&&this._trigger("changeMonth",this.viewDate)):37===a.keyCode||39===a.keyCode?c=this.moveAvailableDate(e,b,"moveDay"):this.weekOfDateIsDisabled(e)||(c=this.moveAvailableDate(e,b,"moveWeek")):1===this.viewMode?(38!==a.keyCode&&40!==a.keyCode||(b*=4),c=this.moveAvailableDate(e,b,"moveMonth")):2===this.viewMode&&(38!==a.keyCode&&40!==a.keyCode||(b*=4),c=this.moveAvailableDate(e,b,"moveYear")),c&&(this.focusDate=this.viewDate=c,this.setValue(),this.fill(),a.preventDefault());break;case 13:if(!this.o.forceParse)break;e=this.focusDate||this.dates.get(-1)||this.viewDate,this.o.keyboardNavigation&&(this._toggle_multidate(e),d=!0),this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.setValue(),this.fill(),this.picker.is(":visible")&&(a.preventDefault(),a.stopPropagation(),this.o.autoclose&&this.hide());break;case 9:this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.fill(),this.hide()}d&&(this.dates.length?this._trigger("changeDate"):this._trigger("clearDate"),this.inputField.trigger("change"))},setViewMode:function(a){this.viewMode=a,this.picker.children("div").hide().filter(".datepicker-"+r.viewModes[this.viewMode].clsName).show(),this.updateNavArrows(),this._trigger("changeViewMode",new Date(this.viewDate))}};var l=function(b,c){a.data(b,"datepicker",this),this.element=a(b),this.inputs=a.map(c.inputs,function(a){return a.jquery?a[0]:a}),delete c.inputs,this.keepEmptyValues=c.keepEmptyValues,delete c.keepEmptyValues,n.call(a(this.inputs),c).on("changeDate",a.proxy(this.dateUpdated,this)),this.pickers=a.map(this.inputs,function(b){return a.data(b,"datepicker")}),this.updateDates()};l.prototype={updateDates:function(){this.dates=a.map(this.pickers,function(a){return a.getUTCDate()}),this.updateRanges()},updateRanges:function(){var b=a.map(this.dates,function(a){return a.valueOf()});a.each(this.pickers,function(a,c){c.setRange(b)})},clearDates:function(){a.each(this.pickers,function(a,b){b.clearDates()})},dateUpdated:function(c){if(!this.updating){this.updating=!0;var d=a.data(c.target,"datepicker");if(d!==b){var e=d.getUTCDate(),f=this.keepEmptyValues,g=a.inArray(c.target,this.inputs),h=g-1,i=g+1,j=this.inputs.length;if(g!==-1){if(a.each(this.pickers,function(a,b){b.getUTCDate()||b!==d&&f||b.setUTCDate(e)}),e<this.dates[h])for(;h>=0&&e<this.dates[h];)this.pickers[h--].setUTCDate(e);else if(e>this.dates[i])for(;i<j&&e>this.dates[i];)this.pickers[i++].setUTCDate(e);this.updateDates(),delete this.updating}}}},destroy:function(){a.map(this.pickers,function(a){a.destroy()}),a(this.inputs).off("changeDate",this.dateUpdated),delete this.element.data().datepicker},remove:f("destroy","Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead")};var m=a.fn.datepicker,n=function(c){var d=Array.apply(null,arguments);d.shift();var e;if(this.each(function(){var b=a(this),f=b.data("datepicker"),g="object"==typeof c&&c;if(!f){var j=h(this,"date"),m=a.extend({},o,j,g),n=i(m.language),p=a.extend({},o,n,j,g);b.hasClass("input-daterange")||p.inputs?(a.extend(p,{inputs:p.inputs||b.find("input").toArray()}),f=new l(this,p)):f=new k(this,p),b.data("datepicker",f)}"string"==typeof c&&"function"==typeof f[c]&&(e=f[c].apply(f,d))}),e===b||e instanceof k||e instanceof l)return this;if(this.length>1)throw new Error("Using only allowed for the collection of a single element ("+c+" function)");return e};a.fn.datepicker=n;var o=a.fn.datepicker.defaults={assumeNearbyYear:!1,autoclose:!1,beforeShowDay:a.noop,beforeShowMonth:a.noop,beforeShowYear:a.noop,beforeShowDecade:a.noop,beforeShowCentury:a.noop,calendarWeeks:!1,clearBtn:!1,toggleActive:!1,daysOfWeekDisabled:[],daysOfWeekHighlighted:[],datesDisabled:[],endDate:1/0,forceParse:!0,format:"mm/dd/yyyy",keepEmptyValues:!1,keyboardNavigation:!0,language:"en",minViewMode:0,maxViewMode:4,multidate:!1,multidateSeparator:",",orientation:"auto",rtl:!1,startDate:-(1/0),startView:0,todayBtn:!1,todayHighlight:!1,updateViewDate:!0,weekStart:0,disableTouchKeyboard:!1,enableOnReadonly:!0,showOnFocus:!0,zIndexOffset:10,container:"body",immediateUpdates:!1,title:"",templates:{leftArrow:"&#x00AB;",rightArrow:"&#x00BB;"},showWeekDays:!0},p=a.fn.datepicker.locale_opts=["format","rtl","weekStart"];a.fn.datepicker.Constructor=k;var q=a.fn.datepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Frid
6118ay","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear",titleFormat:"MM yyyy"}},r={viewModes:[{names:["days","month"],clsName:"days",e:"changeMonth"},{names:["months","year"],clsName:"months",e:"changeYear",navStep:1},{names:["years","decade"],clsName:"years",e:"changeDecade",navStep:10},{names:["decades","century"],clsName:"decades",e:"changeCentury",navStep:100},{names:["centuries","millennium"],clsName:"centuries",e:"changeMillennium",navStep:1e3}],validParts:/dd?|DD?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g,parseFormat:function(a){if("function"==typeof a.toValue&&"function"==typeof a.toDisplay)return a;var b=a.replace(this.validParts,"\0").split("\0"),c=a.match(this.validParts);if(!b||!b.length||!c||0===c.length)throw new Error("Invalid date format.");return{separators:b,parts:c}},parseDate:function(c,e,f,g){function h(a,b){return b===!0&&(b=10),a<100&&(a+=2e3,a>(new Date).getFullYear()+b&&(a-=100)),a}function i(){var a=this.slice(0,j[n].length),b=j[n].slice(0,a.length);return a.toLowerCase()===b.toLowerCase()}if(!c)return b;if(c instanceof Date)return c;if("string"==typeof e&&(e=r.parseFormat(e)),e.toValue)return e.toValue(c,e,f);var j,l,m,n,o,p={d:"moveDay",m:"moveMonth",w:"moveWeek",y:"moveYear"},s={yesterday:"-1d",today:"+0d",tomorrow:"+1d"};if(c in s&&(c=s[c]),/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/i.test(c)){for(j=c.match(/([\-+]\d+)([dmwy])/gi),c=new Date,n=0;n<j.length;n++)l=j[n].match(/([\-+]\d+)([dmwy])/i),m=Number(l[1]),o=p[l[2].toLowerCase()],c=k.prototype[o](c,m);return k.prototype._zero_utc_time(c)}j=c&&c.match(this.nonpunctuation)||[];var t,u,v={},w=["yyyy","yy","M","MM","m","mm","d","dd"],x={yyyy:function(a,b){return a.setUTCFullYear(g?h(b,g):b)},m:function(a,b){if(isNaN(a))return a;for(b-=1;b<0;)b+=12;for(b%=12,a.setUTCMonth(b);a.getUTCMonth()!==b;)a.setUTCDate(a.getUTCDate()-1);return a},d:function(a,b){return a.setUTCDate(b)}};x.yy=x.yyyy,x.M=x.MM=x.mm=x.m,x.dd=x.d,c=d();var y=e.parts.slice();if(j.length!==y.length&&(y=a(y).filter(function(b,c){return a.inArray(c,w)!==-1}).toArray()),j.length===y.length){var z;for(n=0,z=y.length;n<z;n++){if(t=parseInt(j[n],10),l=y[n],isNaN(t))switch(l){case"MM":u=a(q[f].months).filter(i),t=a.inArray(u[0],q[f].months)+1;break;case"M":u=a(q[f].monthsShort).filter(i),t=a.inArray(u[0],q[f].monthsShort)+1}v[l]=t}var A,B;for(n=0;n<w.length;n++)B=w[n],B in v&&!isNaN(v[B])&&(A=new Date(c),x[B](A,v[B]),isNaN(A)||(c=A))}return c},formatDate:function(b,c,d){if(!b)return"";if("string"==typeof c&&(c=r.parseFormat(c)),c.toDisplay)return c.toDisplay(b,c,d);var e={d:b.getUTCDate(),D:q[d].daysShort[b.getUTCDay()],DD:q[d].days[b.getUTCDay()],m:b.getUTCMonth()+1,M:q[d].monthsShort[b.getUTCMonth()],MM:q[d].months[b.getUTCMonth()],yy:b.getUTCFullYear().toString().substring(2),yyyy:b.getUTCFullYear()};e.dd=(e.d<10?"0":"")+e.d,e.mm=(e.m<10?"0":"")+e.m,b=[];for(var f=a.extend([],c.separators),g=0,h=c.parts.length;g<=h;g++)f.length&&b.push(f.shift()),b.push(e[c.parts[g]]);return b.join("")},headTemplate:'<thead><tr><th colspan="7" class="datepicker-title"></th></tr><tr><th class="prev">'+o.templates.leftArrow+'</th><th colspan="5" class="datepicker-switch"></th><th class="next">'+o.templates.rightArrow+"</th></tr></thead>",
6119contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};r.template='<div class="datepicker"><div class="datepicker-days"><table class="table-condensed">'+r.headTemplate+"<tbody></tbody>"+r.footTemplate+'</table></div><div class="datepicker-months"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+'</table></div><div class="datepicker-years"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+'</table></div><div class="datepicker-decades"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+'</table></div><div class="datepicker-centuries"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+"</table></div></div>",a.fn.datepicker.DPGlobal=r,a.fn.datepicker.noConflict=function(){return a.fn.datepicker=m,this},a.fn.datepicker.version="1.8.0",a.fn.datepicker.deprecated=function(a){var b=window.console;b&&b.warn&&b.warn("DEPRECATED: "+a)},a(document).on("focus.datepicker.data-api click.datepicker.data-api",'[data-provide="datepicker"]',function(b){var c=a(this);c.data("datepicker")||(b.preventDefault(),n.call(c,"show"))}),a(function(){n.call(a('[data-provide="datepicker-inline"]'))})});
6120$.fn.datepicker.defaults.zIndexOffset = 10;
6121(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{if(typeof exports==="object"){a(require("jquery"))}else{a(jQuery)}}}(function(d,f){if(!("indexOf" in Array.prototype)){Array.prototype.indexOf=function(k,j){if(j===f){j=0}if(j<0){j+=this.length}if(j<0){j=0}for(var l=this.length;j<l;j++){if(j in this&&this[j]===k){return j}}return -1}}function a(){var q,k,p,l,j,n,m,o;k=(new Date()).toString();p=((m=k.split("(")[1])!=null?m.slice(0,-1):0)||k.split(" ");if(p instanceof Array){n=[];for(var l=0,j=p.length;l<j;l++){o=p[l];if((q=(m=o.match(/\b[A-Z]+\b/))!==null)?m[0]:0){n.push(q)}}p=n.pop()}return p}function h(){return new Date(Date.UTC.apply(Date,arguments))}var g=function(k,j){var m=this;this.element=d(k);this.container=j.container||"body";this.language=j.language||this.element.data("date-language")||"en";this.language=this.language in e?this.language:this.language.split("-")[0];this.language=this.language in e?this.language:"en";this.isRTL=e[this.language].rtl||false;this.formatType=j.formatType||this.element.data("format-type")||"standard";this.format=c.parseFormat(j.format||this.element.data("date-format")||e[this.language].format||c.getDefaultFormat(this.formatType,"input"),this.formatType);this.isInline=false;this.isVisible=false;this.isInput=this.element.is("input");this.fontAwesome=j.fontAwesome||this.element.data("font-awesome")||false;this.bootcssVer=j.bootcssVer||(this.isInput?(this.element.is(".form-control")?3:2):(this.bootcssVer=this.element.is(".input-group")?3:2));this.component=this.element.is(".date")?(this.bootcssVer===3?this.element.find(".input-group-addon .glyphicon-th, .input-group-addon .glyphicon-time, .input-group-addon .glyphicon-remove, .input-group-addon .glyphicon-calendar, .input-group-addon .fa-calendar, .input-group-addon .fa-clock-o").parent():this.element.find(".add-on .icon-th, .add-on .icon-time, .add-on .icon-calendar, .add-on .fa-calendar, .add-on .fa-clock-o").parent()):false;this.componentReset=this.element.is(".date")?(this.bootcssVer===3?this.element.find(".input-group-addon .glyphicon-remove, .input-group-addon .fa-times").parent():this.element.find(".add-on .icon-remove, .add-on .fa-times").parent()):false;this.hasInput=this.component&&this.element.find("input").length;if(this.component&&this.component.length===0){this.component=false}this.linkField=j.linkField||this.element.data("link-field")||false;this.linkFormat=c.parseFormat(j.linkFormat||this.element.data("link-format")||c.getDefaultFormat(this.formatType,"link"),this.formatType);this.minuteStep=j.minuteStep||this.element.data("minute-step")||5;this.pickerPosition=j.pickerPosition||this.element.data("picker-position")||"bottom-right";this.showMeridian=j.showMeridian||this.element.data("show-meridian")||false;this.initialDate=j.initialDate||new Date();this.zIndex=j.zIndex||this.element.data("z-index")||f;this.title=typeof j.title==="undefined"?false:j.title;this.timezone=j.timezone||a();this.icons={leftArrow:this.fontAwesome?"fa-arrow-left":(this.bootcssVer===3?"glyphicon-arrow-left":"icon-arrow-left"),rightArrow:this.fontAwesome?"fa-arrow-right":(this.bootcssVer===3?"glyphicon-arrow-right":"icon-arrow-right")};this.icontype=this.fontAwesome?"fa":"glyphicon";this._attachEvents();this.clickedOutside=function(n){if(d(n.target).closest(".datetimepicker").length===0){m.hide()}};this.formatViewType="datetime";if("formatViewType" in j){this.formatViewType=j.formatViewType}else{if("formatViewType" in this.element.data()){this.formatViewType=this.element.data("formatViewType")}}this.minView=0;if("minView" in j){this.minView=j.minView}else{if("minView" in this.element.data()){this.minView=this.element.data("min-view")}}this.minView=c.convertViewMode(this.minView);this.maxView=c.modes.length-1;if("maxView" in j){this.maxView=j.maxView}else{if("maxView" in this.element.data()){this.maxView=this.element.data("max-view")}}this.maxView=c.convertViewMode(this.maxView);this.wheelViewModeNavigation=false;if("wheelViewModeNavigation" in j){this.wheelViewModeNavigation=j.wheelViewModeNavigation}else{if("wheelViewModeNavigation" in this.element.data()){this.wheelViewModeNavigation=this.element.data("view-mode-wheel-navigation")}}this.wheelViewModeNavigationInverseDirection=false;if("wheelViewModeNavigationInverseDirection" in j){this.wheelViewModeNavigationInverseDirection=j.wheelViewModeNavigationInverseDirection}else{if("wheelViewModeNavigationInverseDirection" in this.element.data()){this.wheelViewModeNavigationInverseDirection=this.element.data("view-mode-wheel-navigation-inverse-dir")}}this.wheelViewModeNavigationDelay=100;if("wheelViewModeNavigationDelay" in j){this.wheelViewModeNavigationDelay=j.wheelViewModeNavigationDelay}else{if("wheelViewModeNavigationDelay" in this.element.data()){this.wheelViewModeNavigationDelay=this.element.data("view-mode-wheel-navigation-delay")}}this.startViewMode=2;if("startView" in j){this.startViewMode=j.startView}else{if("startView" in this.element.data()){this.startViewMode=this.element.data("start-view")}}this.startViewMode=c.convertViewMode(this.startViewMode);this.viewMode=this.startViewMode;this.viewSelect=this.minView;if("viewSelect" in j){this.viewSelect=j.viewSelect}else{if("viewSelect" in this.element.data()){this.viewSelect=this.element.data("view-select")}}this.viewSelect=c.convertViewMode(this.viewSelect);this.forceParse=true;if("forceParse" in j){this.forceParse=j.forceParse}else{if("dateForceParse" in this.element.data()){this.forceParse=this.element.data("date-force-parse")}}var l=this.bootcssVer===3?c.templateV3:c.template;while(l.indexOf("{iconType}")!==-1){l=l.replace("{iconType}",this.icontype)}while(l.indexOf("{leftArrow}")!==-1){l=l.replace("{leftArrow}",this.icons.leftArrow)}while(l.indexOf("{rightArrow}")!==-1){l=l.replace("{rightArrow}",this.icons.rightArrow)}this.picker=d(l).appendTo(this.isInline?this.element:this.container).on({click:d.proxy(this.click,this),mousedown:d.proxy(this.mousedown,this)});if(this.wheelViewModeNavigation){if(d.fn.mousewheel){this.picker.on({mousewheel:d.proxy(this.mousewheel,this)})}else{console.log("Mouse Wheel event is not supported. Please include the jQuery Mouse Wheel plugin before enabling this option")}}if(this.isInline){this.picker.addClass("datetimepicker-inline")}else{this.picker.addClass("datetimepicker-dropdown-"+this.pickerPosition+" dropdown-menu")}if(this.isRTL){this.picker.addClass("datetimepicker-rtl");var i=this.bootcssVer===3?".prev span, .next span":".prev i, .next i";this.picker.find(i).toggleClass(this.icons.leftArrow+" "+this.icons.rightArrow)}d(document).on("mousedown touchend",this.clickedOutside);this.autoclose=false;if("autoclose" in j){this.autoclose=j.autoclose}else{if("dateAutoclose" in this.element.data()){this.autoclose=this.element.data("date-autoclose")}}this.keyboardNavigation=true;if("keyboardNavigation" in j){this.keyboardNavigation=j.keyboardNavigation}else{if("dateKeyboardNavigation" in this.element.data()){this.keyboardNavigation=this.element.data("date-keyboard-navigation")}}this.todayBtn=(j.todayBtn||this.element.data("date-today-btn")||false);this.clearBtn=(j.clearBtn||this.element.data("date-clear-btn")||false);this.todayHighlight=(j.todayHighlight||this.element.data("date-today-highlight")||false);this.weekStart=0;if(typeof j.weekStart!=="undefined"){this.weekStart=j.weekStart}else{if(typeof this.element.data("date-weekstart")!=="undefined"){this.weekStart=this.element.data("date-weekstart")}else{if(typeof e[this.language].weekStart!=="undefined"){this.weekStart=e[this.language].weekStart}}}this.weekStart=this.weekStart%7;this.weekEnd=((this.weekStart+6)%7);this.onRenderDay=function(n){var p=(j.onRenderDay||function(){return[]})(n);if(typeof p==="string"){p=[p]}var o=["day"];return o.concat((p?p:[]))};this.onRenderHour=function(n){var p=(j.onRenderHour||function(){return[]})(n);var o=["hour"];if(typeof p==="string"){p=[p]}return o.concat((p?p:[]))};this.onRenderMinute=function(n){var p=(j.onRenderMinute||function(){return[]})(n);var o=["minute"];if(typeof p==="string"){p=[p]}if(n<this.startDate||n>this.endDate){o.push("disabled")}else{if(Math.floor(this.date.getUTCMinutes()/this.minuteStep)===Math.floor(n.getUTCMinutes()/this.minuteStep)){o.push("active")}}return o.concat((p?p:[]))};this.onRenderYear=function(o){var q=(j.onRenderYear||function(){return[]})(o);var p=["year"];if(typeof q==="string"){q=[q]}if(this.date.getUTCFullYear()===o.getUTCFullYear()){p.push("active")}var n=o.getUTCFullYear();var r=this.endDate.getUTCFullYear();if(o<this.startDate||n>r){p.push("disabled")}return p.concat((q?q:[]))};this.onRenderMonth=function(n){var p=(j.onRenderMonth||function(){return[]})(n);var o=["month"];if(typeof p==="string"){p=[p]}return o.concat((p?p:[]))};this.startDate=new Date(-8639968443048000);this.endDate=new Date(8639968443048000);this.datesDisabled=[];this.daysOfWeekDisabled=[];this.setStartDate(j.startDate||this.element.data("date-startdate"));this.setEndDate(j.endDate||this.element.data("date-enddate"));this.setDatesDisabled(j.datesDisabled||this.element.data("date-dates-disabled"));this.setDaysOfWeekDisabled(j.daysOfWeekDisabled||this.element.data("date-days-of-week-disabled"));this.setMinutesDisabled(j.minutesDisabled||this.element.data("date-minute-disabled"));this.setHoursDisabled(j.hoursDisabled||this.element.data("date-hour-disabled"));this.fillDow();this.fillMonths();this.update();this.showMode();if(this.isInline){this.show()}};g.prototype={constructor:g,_events:[],_attachEvents:function(){this._detachEvents();if(this.isInput){this._events=[[this.element,{focus:d.proxy(this.show,this),keyup:d.proxy(this.update,this),keydown:d.proxy(this.keydown,this)}]]}else{if(this.component&&this.hasInput){this._events=[[this.element.find("input"),{focus:d.proxy(this.show,this),keyup:d.proxy(this.update,this),keydown:d.proxy(this.keydown,this)}],[this.component,{click:d.proxy(this.show,this)}]];if(this.componentReset){this._events.push([this.componentReset,{click:d.proxy(this.reset,this)}])}}else{if(this.element.is("div")){this.isInline=true}else{this._events=[[this.element,{click:d.proxy(this.show,this)}]]}}}for(var j=0,k,l;j<this._events.length;j++){k=this._events[j][0];l=this._events[j][1];k.on(l)}},_detachEvents:function(){for(var j=0,k,l;j<this._events.length;j++){k=this._events[j][0];l=this._events[j][1];k.off(l)}this._events=[]},show:function(i){this.picker.show();this.height=this.component?this.component.outerHeight():this.element.outerHeight();if(this.forceParse){this.update()}this.place();d(window).on("resize",d.proxy(this.place,this));if(i){i.stopPropagation();i.preventDefault()}this.isVisible=true;this.element.trigger({type:"show",date:this.date})},hide:function(){if(!this.isVisible){return}if(this.isInline){return}this.picker.hide();d(window).off("resize",this.place);this.viewMode=this.startViewMode;this.showMode();if(!this.isInput){d(document).off("mousedown",this.hide)}if(this.forceParse&&(this.isInput&&this.element.val()||this.hasInput&&this.element.find("input").val())){this.setValue()}this.isVisible=false;this.element.trigger({type:"hide",date:this.date})},remove:function(){this._detachEvents();d(document).off("mousedown",this.clickedOutside);this.picker.remove();delete this.picker;delete this.element.data().datetimepicker},getDate:function(){var i=this.getUTCDate();if(i===null){return null}return new Date(i.getTime()+(i.getTimezoneOffset()*60000))},getUTCDate:function(){return this.date},getInitialDate:function(){return this.initialDate},setInitialDate:function(i){this.initialDate=i},setDate:function(i){this.setUTCDate(new Date(i.getTime()-(i.getTimezoneOffset()*60000)))},setUTCDate:function(i){if(i>=this.startDate&&i<=this.endDate){this.date=i;this.setValue();this.viewDate=this.date;this.fill()}else{this.element.trigger({type:"outOfRange",date:i,startDate:this.startDate,endD
6121ate:this.endDate})}},setFormat:function(j){this.format=c.parseFormat(j,this.formatType);var i;if(this.isInput){i=this.element}else{if(this.component){i=this.element.find("input")}}if(i&&i.val()){this.setValue()}},setValue:function(){var i=this.getFormattedDate();if(!this.isInput){if(this.component){this.element.find("input").val(i)}this.element.data("date",i)}else{this.element.val(i)}if(this.linkField){d("#"+this.linkField).val(this.getFormattedDate(this.linkFormat))}},getFormattedDate:function(i){i=i||this.format;return c.formatDate(this.date,i,this.language,this.formatType,this.timezone)},setStartDate:function(i){this.startDate=i||this.startDate;if(this.startDate.valueOf()!==8639968443048000){this.startDate=c.parseDate(this.startDate,this.format,this.language,this.formatType,this.timezone)}this.update();this.updateNavArrows()},setEndDate:function(i){this.endDate=i||this.endDate;if(this.endDate.valueOf()!==8639968443048000){this.endDate=c.parseDate(this.endDate,this.format,this.language,this.formatType,this.timezone)}this.update();this.updateNavArrows()},setDatesDisabled:function(j){this.datesDisabled=j||[];if(!d.isArray(this.datesDisabled)){this.datesDisabled=this.datesDisabled.split(/,\s*/)}var i=this;this.datesDisabled=d.map(this.datesDisabled,function(k){return c.parseDate(k,i.format,i.language,i.formatType,i.timezone).toDateString()});this.update();this.updateNavArrows()},setTitle:function(i,j){return this.picker.find(i).find("th:eq(1)").text(this.title===false?j:this.title)},setDaysOfWeekDisabled:function(i){this.daysOfWeekDisabled=i||[];if(!d.isArray(this.daysOfWeekDisabled)){this.daysOfWeekDisabled=this.daysOfWeekDisabled.split(/,\s*/)}this.daysOfWeekDisabled=d.map(this.daysOfWeekDisabled,function(j){return parseInt(j,10)});this.update();this.updateNavArrows()},setMinutesDisabled:function(i){this.minutesDisabled=i||[];if(!d.isArray(this.minutesDisabled)){this.minutesDisabled=this.minutesDisabled.split(/,\s*/)}this.minutesDisabled=d.map(this.minutesDisabled,function(j){return parseInt(j,10)});this.update();this.updateNavArrows()},setHoursDisabled:function(i){this.hoursDisabled=i||[];if(!d.isArray(this.hoursDisabled)){this.hoursDisabled=this.hoursDisabled.split(/,\s*/)}this.hoursDisabled=d.map(this.hoursDisabled,function(j){return parseInt(j,10)});this.update();this.updateNavArrows()},place:function(){if(this.isInline){return}if(!this.zIndex){var j=0;d("div").each(function(){var o=parseInt(d(this).css("zIndex"),10);if(o>j){j=o}});this.zIndex=j+10}var n,m,l,k;if(this.container instanceof d){k=this.container.offset()}else{k=d(this.container).offset()}if(this.component){n=this.component.offset();l=n.left;if(this.pickerPosition==="bottom-left"||this.pickerPosition==="top-left"){l+=this.component.outerWidth()-this.picker.outerWidth()}}else{n=this.element.offset();l=n.left;if(this.pickerPosition==="bottom-left"||this.pickerPosition==="top-left"){l+=this.element.outerWidth()-this.picker.outerWidth()}}var i=document.body.clientWidth||window.innerWidth;if(l+220>i){l=i-220}if(this.pickerPosition==="top-left"||this.pickerPosition==="top-right"){m=n.top-this.picker.outerHeight()}else{m=n.top+this.height}m=m-k.top;l=l-k.left;this.picker.css({top:m,left:l,zIndex:this.zIndex})},hour_minute:"^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]",update:function(){var i,j=false;if(arguments&&arguments.length&&(typeof arguments[0]==="string"||arguments[0] instanceof Date)){i=arguments[0];j=true}else{i=(this.isInput?this.element.val():this.element.find("input").val())||this.element.data("date")||this.initialDate;if(typeof i==="string"){i=i.replace(/^\s+|\s+$/g,"")}}if(!i){i=new Date();j=false}if(typeof i==="string"){if(new RegExp(this.hour_minute).test(i)||new RegExp(this.hour_minute+":[0-5][0-9]").test(i)){i=this.getDate()}}this.date=c.parseDate(i,this.format,this.language,this.formatType,this.timezone);if(j){this.setValue()}if(this.date<this.startDate){this.viewDate=new Date(this.startDate)}else{if(this.date>this.endDate){this.viewDate=new Date(this.endDate)}else{this.viewDate=new Date(this.date)}}this.fill()},fillDow:function(){var i=this.weekStart,j="<tr>";while(i<this.weekStart+7){j+='<th class="dow">'+e[this.language].daysMin[(i++)%7]+"</th>"}j+="</tr>";this.picker.find(".datetimepicker-days thead").append(j)},fillMonths:function(){var l="";var m=new Date(this.viewDate);for(var k=0;k<12;k++){m.setUTCMonth(k);var j=this.onRenderMonth(m);l+='<span class="'+j.join(" ")+'">'+e[this.language].monthsShort[k]+"</span>"}this.picker.find(".datetimepicker-months td").html(l)},fill:function(){if(!this.date||!this.viewDate){return}var E=new Date(this.viewDate),t=E.getUTCFullYear(),G=E.getUTCMonth(),n=E.getUTCDate(),A=E.getUTCHours(),w=this.startDate.getUTCFullYear(),B=this.startDate.getUTCMonth(),p=this.endDate.getUTCFullYear(),x=this.endDate.getUTCMonth()+1,q=(new h(this.date.getUTCFullYear(),this.date.getUTCMonth(),this.date.getUTCDate())).valueOf(),D=new Date();this.setTitle(".datetimepicker-days",e[this.language].months[G]+" "+t);if(this.formatViewType==="time"){var k=this.getFormattedDate();this.setTitle(".datetimepicker-hours",k);this.setTitle(".datetimepicker-minutes",k)}else{this.setTitle(".datetimepicker-hours",n+" "+e[this.language].months[G]+" "+t);this.setTitle(".datetimepicker-minutes",n+" "+e[this.language].months[G]+" "+t)}this.picker.find("tfoot th.today").text(e[this.language].today||e.en.today).toggle(this.todayBtn!==false);this.picker.find("tfoot th.clear").text(e[this.language].clear||e.en.clear).toggle(this.clearBtn!==false);this.updateNavArrows();this.fillMonths();var I=h(t,G-1,28,0,0,0,0),z=c.getDaysInMonth(I.getUTCFullYear(),I.getUTCMonth());I.setUTCDate(z);I.setUTCDate(z-(I.getUTCDay()-this.weekStart+7)%7);var j=new Date(I);j.setUTCDate(j.getUTCDate()+42);j=j.valueOf();var r=[];var F;
6121while(I.valueOf()<j){if(I.getUTCDay()===this.weekStart){r.push("<tr>")}F=this.onRenderDay(I);if(I.getUTCFullYear()<t||(I.getUTCFullYear()===t&&I.getUTCMonth()<G)){F.push("old")}else{if(I.getUTCFullYear()>t||(I.getUTCFullYear()===t&&I.getUTCMonth()>G)){F.push("new")}}if(this.todayHighlight&&I.getUTCFullYear()===D.getFullYear()&&I.getUTCMonth()===D.getMonth()&&I.getUTCDate()===D.getDate()){F.push("today")}if(I.valueOf()===q){F.push("active")}if((I.valueOf()+86400000)<=this.startDate||I.valueOf()>this.endDate||d.inArray(I.getUTCDay(),this.daysOfWeekDisabled)!==-1||d.inArray(I.toDateString(),this.datesDisabled)!==-1){F.push("disabled")}r.push('<td class="'+F.join(" ")+'">'+I.getUTCDate()+"</td>");if(I.getUTCDay()===this.weekEnd){r.push("</tr>")}I.setUTCDate(I.getUTCDate()+1)}this.picker.find(".datetimepicker-days tbody").empty().append(r.join(""));r=[];var u="",C="",s="";var l=this.hoursDisabled||[];E=new Date(this.viewDate);for(var y=0;y<24;y++){E.setUTCHours(y);F=this.onRenderHour(E);if(l.indexOf(y)!==-1){F.push("disabled")}var v=h(t,G,n,y);if((v.valueOf()+3600000)<=this.startDate||v.valueOf()>this.endDate){F.push("disabled")}else{if(A===y){F.push("active")}}if(this.showMeridian&&e[this.language].meridiem.length===2){C=(y<12?e[this.language].meridiem[0]:e[this.language].meridiem[1]);if(C!==s){if(s!==""){r.push("</fieldset>")}r.push('<fieldset class="hour"><legend>'+C.toUpperCase()+"</legend>")}s=C;u=(y%12?y%12:12);if(y<12){F.push("hour_am")}else{F.push("hour_pm")}r.push('<span class="'+F.join(" ")+'">'+u+"</span>");if(y===23){r.push("</fieldset>")}}else{u=y+":00";r.push('<span class="'+F.join(" ")+'">'+u+"</span>")}}this.picker.find(".datetimepicker-hours td").html(r.join(""));r=[];u="";C="";s="";var m=this.minutesDisabled||[];E=new Date(this.viewDate);for(var y=0;y<60;y+=this.minuteStep){if(m.indexOf(y)!==-1){continue}E.setUTCMinutes(y);E.setUTCSeconds(0);F=this.onRenderMinute(E);if(this.showMeridian&&e[this.language].meridiem.length===2){C=(A<12?e[this.language].meridiem[0]:e[this.language].meridiem[1]);if(C!==s){if(s!==""){r.push("</fieldset>")}r.push('<fieldset class="minute"><legend>'+C.toUpperCase()+"</legend>")}s=C;u=(A%12?A%12:12);r.push('<span class="'+F.join(" ")+'">'+u+":"+(y<10?"0"+y:y)+"</span>");if(y===59){r.push("</fieldset>")}}else{u=y+":00";r.push('<span class="'+F.join(" ")+'">'+A+":"+(y<10?"0"+y:y)+"</span>")}}this.picker.find(".datetimepicker-minutes td").html(r.join(""));var J=this.date.getUTCFullYear();var o=this.setTitle(".datetimepicker-months",t).end().find(".month").removeClass("active");if(J===t){o.eq(this.date.getUTCMonth()).addClass("active")}if(t<w||t>p){o.addClass("disabled")}if(t===w){o.slice(0,B).addClass("disabled")}if(t===p){o.slice(x).addClass("disabled")}r="";t=parseInt(t/10,10)*10;var H=this.setTitle(".datetimepicker-years",t+"-"+(t+9)).end().find("td");t-=1;E=new Date(this.viewDate);for(var y=-1;y<11;y++){E.setUTCFullYear(t);F=this.onRenderYear(E);if(y===-1||y===10){F.push(b)}r+='<span class="'+F.join(" ")+'">'+t+"</span>";t+=1}H.html(r);this.place()},updateNavArrows:function(){var m=new Date(this.viewDate),k=m.getUTCFullYear(),l=m.getUTCMonth(),j=m.getUTCDate(),i=m.getUTCHours();switch(this.viewMode){case 0:if(k<=this.startDate.getUTCFullYear()&&l<=this.startDate.getUTCMonth()&&j<=this.startDate.getUTCDate()&&i<=this.startDate.getUTCHours()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()&&l>=this.endDate.getUTCMonth()&&j>=this.endDate.getUTCDate()&&i>=this.endDate.getUTCHours()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 1:if(k<=this.startDate.getUTCFullYear()&&l<=this.startDate.getUTCMonth()&&j<=this.startDate.getUTCDate()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()&&l>=this.endDate.getUTCMonth()&&j>=this.endDate.getUTCDate()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 2:if(k<=this.startDate.getUTCFullYear()&&l<=this.startDate.getUTCMonth()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()&&l>=this.endDate.getUTCMonth()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 3:case 4:if(k<=this.startDate.getUTCFullYear()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break}},mousewheel:function(j){j.preventDefault();j.stopPropagation();if(this.wheelPause){return}this.wheelPause=true;var i=j.originalEvent;var l=i.wheelDelta;var k=l>0?1:(l===0)?0:-1;
6121if(this.wheelViewModeNavigationInverseDirection){k=-k}this.showMode(k);setTimeout(d.proxy(function(){this.wheelPause=false},this),this.wheelViewModeNavigationDelay)},click:function(m){m.stopPropagation();m.preventDefault();var n=d(m.target).closest("span, td, th, legend");if(n.is("."+this.icontype)){n=d(n).parent().closest("span, td, th, legend")}if(n.length===1){if(n.is(".disabled")){this.element.trigger({type:"outOfRange",date:this.viewDate,startDate:this.startDate,endDate:this.endDate});return}switch(n[0].nodeName.toLowerCase()){case"th":switch(n[0].className){case"switch":this.showMode(1);break;case"prev":case"next":var i=c.modes[this.viewMode].navStep*(n[0].className==="prev"?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveHour(this.viewDate,i);break;case 1:this.viewDate=this.moveDate(this.viewDate,i);break;case 2:this.viewDate=this.moveMonth(this.viewDate,i);break;case 3:case 4:this.viewDate=this.moveYear(this.viewDate,i);break}this.fill();this.element.trigger({type:n[0].className+":"+this.convertViewModeText(this.viewMode),date:this.viewDate,startDate:this.startDate,endDate:this.endDate});break;case"clear":this.reset();if(this.autoclose){this.hide()}break;case"today":var j=new Date();j=h(j.getFullYear(),j.getMonth(),j.getDate(),j.getHours(),j.getMinutes(),j.getSeconds(),0);if(j<this.startDate){j=this.startDate}else{if(j>this.endDate){j=this.endDate}}this.viewMode=this.startViewMode;this.showMode(0);this._setDate(j);this.fill();if(this.autoclose){this.hide()}break}break;case"span":if(!n.is(".disabled")){var p=this.viewDate.getUTCFullYear(),o=this.viewDate.getUTCMonth(),q=this.viewDate.getUTCDate(),r=this.viewDate.getUTCHours(),k=this.viewDate.getUTCMinutes(),s=this.viewDate.getUTCSeconds();if(n.is(".month")){this.viewDate.setUTCDate(1);o=n.parent().find("span").index(n);q=this.viewDate.getUTCDate();this.viewDate.setUTCMonth(o);this.element.trigger({type:"changeMonth",date:this.viewDate});if(this.viewSelect>=3){this._setDate(h(p,o,q,r,k,s,0))}}else{if(n.is(".year")){this.viewDate.setUTCDate(1);p=parseInt(n.text(),10)||0;this.viewDate.setUTCFullYear(p);this.element.trigger({type:"changeYear",date:this.viewDate});if(this.viewSelect>=4){this._setDate(h(p,o,q,r,k,s,0))}}else{if(n.is(".hour")){r=parseInt(n.text(),10)||0;if(n.hasClass("hour_am")||n.hasClass("hour_pm")){if(r===12&&n.hasClass("hour_am")){r=0}else{if(r!==12&&n.hasClass("hour_pm")){r+=12}}}this.viewDate.setUTCHours(r);this.element.trigger({type:"changeHour",date:this.viewDate});if(this.viewSelect>=1){this._setDate(h(p,o,q,r,k,s,0))}}else{if(n.is(".minute")){k=parseInt(n.text().substr(n.text().indexOf(":")+1),10)||0;this.viewDate.setUTCMinutes(k);this.element.trigger({type:"changeMinute",date:this.viewDate});if(this.viewSelect>=0){this._setDate(h(p,o,q,r,k,s,0))}}}}}if(this.viewMode!==0){var l=this.viewMode;this.showMode(-1);this.fill();if(l===this.viewMode&&this.autoclose){this.hide()}}else{this.fill();if(this.autoclose){this.hide()}}}break;case"td":if(n.is(".day")&&!n.is(".disabled")){var q=parseInt(n.text(),10)||1;var p=this.viewDate.getUTCFullYear(),o=this.viewDate.getUTCMonth(),r=this.viewDate.getUTCHours(),k=this.viewDate.getUTCMinutes(),s=this.viewDate.getUTCSeconds();if(n.is(".old")){if(o===0){o=11;p-=1}else{o-=1}}else{if(n.is(".new")){if(o===11){o=0;p+=1}else{o+=1}}}this.viewDate.setUTCFullYear(p);this.viewDate.setUTCMonth(o,q);this.element.trigger({type:"changeDay",date:this.viewDate});if(this.viewSelect>=2){this._setDate(h(p,o,q,r,k,s,0))}}var l=this.viewMode;this.showMode(-1);this.fill();if(l===this.viewMode&&this.autoclose){this.hide()}break}}},_setDate:function(i,k){if(!k||k==="date"){this.date=i}if(!k||k==="view"){this.viewDate=i}this.fill();this.setValue();var j;if(this.isInput){j=this.element}else{if(this.component){j=this.element.find("input")}}if(j){j.change()}this.element.trigger({type:"changeDate",date:this.getDate()});if(i===null){this.date=this.viewDate}},moveMinute:function(j,i){if(!i){return j}var k=new Date(j.valueOf());k.setUTCMinutes(k.getUTCMinutes()+(i*this.minuteStep));return k},moveHour:function(j,i){if(!i){return j}var k=new Date(j.valueOf());k.setUTCHours(k.getUTCHours()+i);return k}
6121,moveDate:function(j,i){if(!i){return j}var k=new Date(j.valueOf());k.setUTCDate(k.getUTCDate()+i);return k},moveMonth:function(j,k){if(!k){return j}var n=new Date(j.valueOf()),r=n.getUTCDate(),o=n.getUTCMonth(),m=Math.abs(k),q,p;k=k>0?1:-1;if(m===1){p=k===-1?function(){return n.getUTCMonth()===o}:function(){return n.getUTCMonth()!==q};q=o+k;n.setUTCMonth(q);if(q<0||q>11){q=(q+12)%12}}else{for(var l=0;l<m;l++){n=this.moveMonth(n,k)}q=n.getUTCMonth();n.setUTCDate(r);p=function(){return q!==n.getUTCMonth()}}while(p()){n.setUTCDate(--r);n.setUTCMonth(q)}return n},moveYear:function(j,i){return this.moveMonth(j,i*12)},dateWithinRange:function(i){return i>=this.startDate&&i<=this.endDate},keydown:function(o){if(this.picker.is(":not(:visible)")){if(o.keyCode===27){this.show()}return}var k=false,j,i,n;switch(o.keyCode){case 27:this.hide();o.preventDefault();break;case 37:case 39:if(!this.keyboardNavigation){break}j=o.keyCode===37?-1:1;var m=this.viewMode;if(o.ctrlKey){m+=2}else{if(o.shiftKey){m+=1}}if(m===4){i=this.moveYear(this.date,j);n=this.moveYear(this.viewDate,j)}else{if(m===3){i=this.moveMonth(this.date,j);n=this.moveMonth(this.viewDate,j)}else{if(m===2){i=this.moveDate(this.date,j);n=this.moveDate(this.viewDate,j)}else{if(m===1){i=this.moveHour(this.date,j);n=this.moveHour(this.viewDate,j)}else{if(m===0){i=this.moveMinute(this.date,j);n=this.moveMinute(this.viewDate,j)}}}}}if(this.dateWithinRange(i)){this.date=i;this.viewDate=n;this.setValue();this.update();o.preventDefault();k=true}break;case 38:case 40:if(!this.keyboardNavigation){break}j=o.keyCode===38?-1:1;m=this.viewMode;if(o.ctrlKey){m+=2}else{if(o.shiftKey){m+=1}}if(m===4){i=this.moveYear(this.date,j);n=this.moveYear(this.viewDate,j)}else{if(m===3){i=this.moveMonth(this.date,j);n=this.moveMonth(this.viewDate,j)}else{if(m===2){i=this.moveDate(this.date,j*7);n=this.moveDate(this.viewDate,j*7)}else{if(m===1){if(this.showMeridian){i=this.moveHour(this.date,j*6);n=this.moveHour(this.viewDate,j*6)}else{i=this.moveHour(this.date,j*4);n=this.moveHour(this.viewDate,j*4)}}else{if(m===0){i=this.moveMinute(this.date,j*4);n=this.moveMinute(this.viewDate,j*4)}}}}}if(this.dateWithinRange(i)){this.date=i;this.viewDate=n;this.setValue();this.update();o.preventDefault();k=true}break;case 13:if(this.viewMode!==0){var p=this.viewMode;this.showMode(-1);this.fill();if(p===this.viewMode&&this.autoclose){this.hide()}}else{this.fill();if(this.autoclose){this.hide()}}o.preventDefault();break;case 9:this.hide();break}if(k){var l;if(this.isInput){l=this.element}else{if(this.component){l=this.element.find("input")}}if(l){l.change()}this.element.trigger({type:"changeDate",date:this.getDate()})}},showMode:function(i){if(i){var j=Math.max(0,Math.min(c.modes.length-1,this.viewMode+i));if(j>=this.minView&&j<=this.maxView){this.element.trigger({type:"changeMode",date:this.viewDate,oldViewMode:this.viewMode,newViewMode:j});this.viewMode=j}}this.picker.find(">div").hide().filter(".datetimepicker-"+c.modes[this.viewMode].clsName).css("display","block");this.updateNavArrows()},reset:function(){this._setDate(null,"date")},convertViewModeText:function(i){switch(i){case 4:return"decade";case 3:return"year";case 2:return"month";case 1:return"day";case 0:return"hour"}}};var b=d.fn.datetimepicker;d.fn.datetimepicker=function(k){var i=Array.apply(null,arguments);i.shift();var j;this.each(function(){var n=d(this),m=n.data("datetimepicker"),l=typeof k==="object"&&k;if(!m){n.data("datetimepicker",(m=new g(this,d.extend({},d.fn.datetimepicker.defaults,l))))}if(typeof k==="string"&&typeof m[k]==="function"){j=m[k].apply(m,i);if(j!==f){return false}}});if(j!==f){return j}else{return this}};d.fn.datetimepicker.defaults={};d.fn.datetimepicker.Constructor=g;var e=d.fn.datetimepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],meridiem:["am","pm"],suffix:["st","nd","rd","th"],today:"Today",clear:"Clear"}};var c={modes:[{clsName:"minutes",navFnc:"Hours",navStep:1},{clsName:"hours",navFnc:"Date",navStep:1},{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(i){return(((i%4===0)&&(i%100!==0))||(i%400===0))},getDaysInMonth:function(i,j){return[31,(c.isLeapYear(i)?29:28),31,30,31,30,31,31,30,31,30,31][j]},getDefaultFormat:function(i,j){if(i==="standard"){if(j==="input"){return"yyyy-mm-dd hh:ii"}else{return"yyyy-mm-dd hh:ii:ss"}}else{if(i==="php"){if(j==="input"){return"Y-m-d H:i"}else{return"Y-m-d H:i:s"}}else{throw new Error("Invalid format type.")}}},validParts:function(i){if(i==="standard"){return/t|hh?|HH?|p|P|z|Z|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g}else{if(i==="php"){return/[dDjlNwzFmMnStyYaABgGhHis]/g}else{throw new Error("Invalid format type.")}}},nonpunctuation:/[^ -\/:-@\[-`{-~\t\n\rTZ]+/g,parseFormat:function(l,j){var i=l.replace(this.validParts(j),"\0").split("\0"),k=l.match(this.validParts(j));if(!i||!i.length||!k||k.length===0){throw new Error("Invalid date format.")}return{separators:i,parts:k}},parseDate:function(A,y,v,j,r){if(A instanceof Date){var u=new Date(A.valueOf()-A.getTimezoneOffset()*60000);u.setMilliseconds(0);return u}if(/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(A)){y=this.parseFormat("yyyy-mm-dd",j)}if(/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(A)){y=this.parseFormat("yyyy-mm-dd hh:ii",j)}if(/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(A)){y=this.parseFormat("yyyy-mm-dd hh:ii:ss",j)}if(/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(A)){var l=/([-+]\d+)([dmwy])/,q=A.match(/([-+]\d+)([dmwy])/g),t,p;A=new Date();for(var x=0;x<q.length;x++){t=l.exec(q[x]);p=parseInt(t[1]);switch(t[2]){case"d":A.setUTCDate(A.getUTCDate()+p);break;case"m":A=g.prototype.moveMonth.call(g.prototype,A,p);break;case"w":A.setUTCDate(A.getUTCDate()+p*7);break;case"y":A=g.prototype.moveYear.call(g.prototype,A,p);break}}return h(A.getUTCFullYear(),A.getUTCMonth(),A.getUTCDate(),A.getUTCHours(),A.getUTCMinutes(),A.getUTCSeconds(),0)}var q=A&&A.toString().match(this.nonpunctuation)||[],A=new Date(0,0,0,0,0,0,0),m={},z=["hh","h","ii","i","ss","s","yyyy","yy","M","MM","m","mm","D","DD","d","dd","H","HH","p","P","z","Z"],o={hh:function(s,i){return s.setUTCHours(i)},h:function(s,i){return s.setUTCHours(i)},HH:function(s,i){return s.setUTCHours(i===12?0:i)},H:function(s,i){return s.setUTCHours(i===12?0:i)},ii:function(s,i){return s.setUTCMinutes(i)},i:function(s,i){return s.setUTCMinutes(i)},ss:function(s,i){return s.setUTCSeconds(i)},s:function(s,i){return s.setUTCSeconds(i)},yyyy:function(s,i){return s.setUTCFullYear(i)},yy:function(s,i){return s.setUTCFullYear(2000+i)},m:function(s,i){i-=1;while(i<0){i+=12}i%=12;s.setUTCMonth(i);while(s.getUTCMonth()!==i){if(isNaN(s.getUTCMonth())){return s}else{s.setUTCDate(s.getUTCDate()-1)}}return s},d:function(s,i){return s.setUTCDate(i)},p:function(s,i){return s.setUTCHours(i===1?s.getUTCHours()+12:s.getUTCHours())},z:function(){return r}},B,k,t;o.M=o.MM=o.mm=o.m;o.dd=o.d;o.P=o.p;o.Z=o.z;A=h(A.getFullYear(),A.getMonth(),A.getDate(),A.getHours(),A.getMinutes(),A.getSeconds());if(q.length===y.parts.length){for(var x=0,w=y.parts.length;x<w;x++){B=parseInt(q[x],10);
6121t=y.parts[x];if(isNaN(B)){switch(t){case"MM":k=d(e[v].months).filter(function(){var i=this.slice(0,q[x].length),s=q[x].slice(0,i.length);return i===s});B=d.inArray(k[0],e[v].months)+1;break;case"M":k=d(e[v].monthsShort).filter(function(){var i=this.slice(0,q[x].length),s=q[x].slice(0,i.length);return i.toLowerCase()===s.toLowerCase()});B=d.inArray(k[0],e[v].monthsShort)+1;break;case"p":case"P":B=d.inArray(q[x].toLowerCase(),e[v].meridiem);break;case"z":case"Z":r;break}}m[t]=B}for(var x=0,n;x<z.length;x++){n=z[x];if(n in m&&!isNaN(m[n])){o[n](A,m[n])}}}return A},formatDate:function(l,q,m,p,o){if(l===null){return""}var k;if(p==="standard"){k={t:l.getTime(),yy:l.getUTCFullYear().toString().substring(2),yyyy:l.getUTCFullYear(),m:l.getUTCMonth()+1,M:e[m].monthsShort[l.getUTCMonth()],MM:e[m].months[l.getUTCMonth()],d:l.getUTCDate(),D:e[m].daysShort[l.getUTCDay()],DD:e[m].days[l.getUTCDay()],p:(e[m].meridiem.length===2?e[m].meridiem[l.getUTCHours()<12?0:1]:""),h:l.getUTCHours(),i:l.getUTCMinutes(),s:l.getUTCSeconds(),z:o};if(e[m].meridiem.length===2){k.H=(k.h%12===0?12:k.h%12)}else{k.H=k.h}k.HH=(k.H<10?"0":"")+k.H;k.P=k.p.toUpperCase();k.Z=k.z;k.hh=(k.h<10?"0":"")+k.h;k.ii=(k.i<10?"0":"")+k.i;k.ss=(k.s<10?"0":"")+k.s;k.dd=(k.d<10?"0":"")+k.d;k.mm=(k.m<10?"0":"")+k.m}else{if(p==="php"){k={y:l.getUTCFullYear().toString().substring(2),Y:l.getUTCFullYear(),F:e[m].months[l.getUTCMonth()],M:e[m].monthsShort[l.getUTCMonth()],n:l.getUTCMonth()+1,t:c.getDaysInMonth(l.getUTCFullYear(),l.getUTCMonth()),j:l.getUTCDate(),l:e[m].days[l.getUTCDay()],D:e[m].daysShort[l.getUTCDay()],w:l.getUTCDay(),N:(l.getUTCDay()===0?7:l.getUTCDay()),S:(l.getUTCDate()%10<=e[m].suffix.length?e[m].suffix[l.getUTCDate()%10-1]:""),a:(e[m].meridiem.length===2?e[m].meridiem[l.getUTCHours()<12?0:1]:""),g:(l.getUTCHours()%12===0?12:l.getUTCHours()%12),G:l.getUTCHours(),i:l.getUTCMinutes(),s:l.getUTCSeconds()};k.m=(k.n<10?"0":"")+k.n;k.d=(k.j<10?"0":"")+k.j;k.A=k.a.toString().toUpperCase();k.h=(k.g<10?"0":"")+k.g;k.H=(k.G<10?"0":"")+k.G;k.i=(k.i<10?"0":"")+k.i;k.s=(k.s<10?"0":"")+k.s}else{throw new Error("Invalid format type.")}}var l=[],r=d.extend([],q.separators);for(var n=0,j=q.parts.length;n<j;n++){if(r.length){l.push(r.shift())}l.push(k[q.parts[n]])}if(r.length){l.push(r.shift())}return l.join("")},convertViewMode:function(i){switch(i){case 4:case"decade":i=4;break;case 3:case"year":i=3;break;case 2:case"month":i=2;break;case 1:case"day":i=1;break;case 0:case"hour":i=0;break}return i},headTemplate:'<thead><tr><th class="prev"><i class="{iconType} {leftArrow}"/></th><th colspan="5" class="switch"></th><th class="next"><i class="{iconType} {rightArrow}"/></th></tr></thead>',headTemplateV3:'<thead><tr><th class="prev"><span class="{iconType} {leftArrow}"></span> </th><th colspan="5" class="switch"></th><th class="next"><span class="{iconType} {rightArrow}"></span> </th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};c.template='<div class="datetimepicker"><div class="datetimepicker-minutes"><table class=" table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-hours"><table class=" table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-days"><table class=" table-condensed">'+c.headTemplate+"<tbody></tbody>"+c.footTemplate+'</table></div><div class="datetimepicker-months"><table class="table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-years"><table class="table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+"</table></div></div>";c.templateV3='<div class="datetimepicker"><div class="datetimepicker-minutes"><table class=" table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-hours"><table class=" table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-days"><table class=" table-condensed">'+c.headTemplateV3+"<tbody></tbody>"+c.footTemplate+'</table></div><div class="datetimepicker-months"><table class="table-condensed">
6121'+c.headTemplateV3+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-years"><table class="table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+"</table></div></div>";d.fn.datetimepicker.DPGlobal=c;d.fn.datetimepicker.noConflict=function(){d.fn.datetimepicker=b;return this};d(document).on("focus.datetimepicker.data-api click.datetimepicker.data-api",'[data-provide="datetimepicker"]',function(j){var i=d(this);if(i.data("datetimepicker")){return}j.preventDefault();i.datetimepicker("show")});d(function(){d('[data-provide="datetimepicker-inline"]').datetimepicker()})}));
6122/*! bootstrap-timepicker v0.5.2 
6123* http://jdewit.github.com/bootstrap-timepicker 
6124* Copyright (c) 2016 Joris de Wit and bootstrap-timepicker contributors 
6125* MIT License 
6126*/!function(a,b,c){"use strict";var d=function(b,c){this.widget="",this.$element=a(b),this.defaultTime=c.defaultTime,this.disableFocus=c.disableFocus,this.disableMousewheel=c.disableMousewheel,this.isOpen=c.isOpen,this.minuteStep=c.minuteStep,this.modalBackdrop=c.modalBackdrop,this.orientation=c.orientation,this.secondStep=c.secondStep,this.snapToStep=c.snapToStep,this.showInputs=c.showInputs,this.showMeridian=c.showMeridian,this.showSeconds=c.showSeconds,this.template=c.template,this.appendWidgetTo=c.appendWidgetTo,this.showWidgetOnAddonClick=c.showWidgetOnAddonClick,this.icons=c.icons,this.maxHours=c.maxHours,this.explicitMode=c.explicitMode,this.handleDocumentClick=function(a){var b=a.data.scope;b.$element.parent().find(a.target).length||b.$widget.is(a.target)||b.$widget.find(a.target).length||b.hideWidget()},this._init()};d.prototype={constructor:d,_init:function(){var b=this;this.showWidgetOnAddonClick&&this.$element.parent().hasClass("input-group")&&this.$element.parent().hasClass("bootstrap-timepicker")?(this.$element.parent(".input-group.bootstrap-timepicker").find(".input-group-addon").on({"click.timepicker":a.proxy(this.showWidget,this)}),this.$element.on({"focus.timepicker":a.proxy(this.highlightUnit,this),"click.timepicker":a.proxy(this.highlightUnit,this),"keydown.timepicker":a.proxy(this.elementKeydown,this),"blur.timepicker":a.proxy(this.blurElement,this),"mousewheel.timepicker DOMMouseScroll.timepicker":a.proxy(this.mousewheel,this)})):this.template?this.$element.on({"focus.timepicker":a.proxy(this.showWidget,this),"click.timepicker":a.proxy(this.showWidget,this),"blur.timepicker":a.proxy(this.blurElement,this),"mousewheel.timepicker DOMMouseScroll.timepicker":a.proxy(this.mousewheel,this)}):this.$element.on({"focus.timepicker":a.proxy(this.highlightUnit,this),"click.timepicker":a.proxy(this.highlightUnit,this),"keydown.timepicker":a.proxy(this.elementKeydown,this),"blur.timepicker":a.proxy(this.blurElement,this),"mousewheel.timepicker DOMMouseScroll.timepicker":a.proxy(this.mousewheel,this)}),this.template!==!1?this.$widget=a(this.getTemplate()).on("click",a.proxy(this.widgetClick,this)):this.$widget=!1,this.showInputs&&this.$widget!==!1&&this.$widget.find("input").each(function(){a(this).on({"click.timepicker":function(){a(this).select()},"keydown.timepicker":a.proxy(b.widgetKeydown,b),"keyup.timepicker":a.proxy(b.widgetKeyup,b)})}),this.setDefaultTime(this.defaultTime)},blurElement:function(){this.highlightedUnit=null,this.updateFromElementVal()},clear:function(){this.hour="",this.minute="",this.second="",this.meridian="",this.$element.val("")},decrementHour:function(){if(this.showMeridian)if(1===this.hour)this.hour=12;else{if(12===this.hour)return this.hour--,this.toggleMeridian();if(0===this.hour)return this.hour=11,this.toggleMeridian();this.hour--}else this.hour<=0?this.hour=this.maxHours-1:this.hour--},decrementMinute:function(a){var b;b=a?this.minute-a:this.minute-this.minuteStep,0>b?(this.decrementHour(),this.minute=b+60):this.minute=b},decrementSecond:function(){var a=this.second-this.secondStep;0>a?(this.decrementMinute(!0),this.second=a+60):this.second=a},elementKeydown:function(a){switch(a.which){case 9:if(a.shiftKey){if("hour"===this.highlightedUnit){this.hideWidget();break}this.highlightPrevUnit()}else{if(this.showMeridian&&"meridian"===this.highlightedUnit||this.showSeconds&&"second"===this.highlightedUnit||!this.showMeridian&&!this.showSeconds&&"minute"===this.highlightedUnit){this.hideWidget();break}this.highlightNextUnit()}a.preventDefault(),this.updateFromElementVal();break;case 27:this.updateFromElementVal();break;case 37:a.preventDefault(),this.highlightPrevUnit(),this.updateFromElementVal();break;case 38:switch(a.preventDefault(),this.highlightedUnit){case"hour":this.incrementHour(),this.highlightHour();break;case"minute":this.incrementMinute(),this.highlightMinute();break;case"second":this.incrementSecond(),this.highlightSecond();break;case"meridian":this.toggleMeridian(),this.highlightMeridian()}this.update();break;case 39:a.preventDefault(),this.highlightNextUnit(),this.updateFromElementVal();break;case 40:switch(a.preventDefault(),this.highlightedUnit){case"hour":this.decrementHour(),this.highlightHour();break;case"minute":this.decrementMinute(),this.highlightMinute();break;case"second":this.decrementSecond(),this.highlightSecond();break;case"meridian":this.toggleMeridian(),this.highlightMeridian()}this.update()}},getCursorPosition:function(){var a=this.$element.get(0);if("selectionStart"in a)return a.selectionStart;if(c.selection){a.focus();var b=c.selection.createRange(),d=c.selection.createRange().text.length;return b.moveStart("character",-a.value.length),b.text.length-d}},getTemplate:function(){var a,b,c,d,e,f;switch(this.showInputs?(b='<input type="text" class="bootstrap-timepicker-hour" maxlength="2"/>',c='<input type="text" class="bootstrap-timepicker-minute" maxlength="2"/>',d='<input type="text" class="bootstrap-timepicker-second" maxlength="2"/>',e='<input type="text" class="bootstrap-timepicker-meridian" maxlength="2"/>'):(b='<span class="bootstrap-timepicker-hour"></span>',c='<span class="bootstrap-timepicker-minute"></span>',d='<span class="bootstrap-timepicker-second"></span>',e='<span class="bootstrap-timepicker-meridian"></span>'),f='<table><tr><td><a href="#" data-action="incrementHour"><span class="'+this.icons.up+'"></span></a></td><td class="separator">&nbsp;</td><td><a href="#" data-action="incrementMinute"><span class="'+this.icons.up+'"></span></a></td>'+(this.showSeconds?'<td class="separator">&nbsp;</td><td><a href="#" data-action="incrementSecond"><span class="'+this.icons.up+'"></span></a></td>':"")+(this.showMeridian?'<td class="separator">&nbsp;</td><td class="meridian-column"><a href="#" data-action="toggleMeridian"><span class="'+this.icons.up+'"></span></a></td>':"")+"</tr><tr><td>"+b+'</td> <td class="separator">:</td><td>'+c+"</td> "+(this.showSeconds?'<td class="separator">:</td><td>'+d+"</td>":"")+(this.showMeridian?'<td class="separator">&nbsp;</td><td>'+e+"</td>":"")+'</tr><tr><td><a href="#" data-action="decrementHour"><span class="'+this.icons.down+'"></span></a></td><td class="separator"></td><td><a href="#" data-action="decrementMinute"><span class="'+this.icons.down+'"></span></a></td>'+(this.showSeconds?'<td class="separator">&nbsp;</td><td><a href="#" data-action="decrementSecond"><span class="'+this.icons.down+'"></span></a></td>':"")+(this.showMeridian?'<td class="separator">&nbsp;</td><td><a href="#" data-action="toggleMeridian"><span class="'+this.icons.down+'"></span></a></td>':"")+"</tr></table>",this.template){case"modal":a='<div class="bootstrap-timepicker-widget modal hide fade in" data-backdrop="'+(this.modalBackdrop?"true":"false")+'"><div class="modal-header"><a href="#" class="close" data-dismiss="modal">&times;</a><h3>
6126Pick a Time</h3></div><div class="modal-content">'+f+'</div><div class="modal-footer"><a href="#" class="btn btn-primary" data-dismiss="modal">OK</a></div></div>';break;case"dropdown":a='<div class="bootstrap-timepicker-widget dropdown-menu">'+f+"</div>"}return a},getTime:function(){return""===this.hour?"":this.hour+":"+(1===this.minute.toString().length?"0"+this.minute:this.minute)+(this.showSeconds?":"+(1===this.second.toString().length?"0"+this.second:this.second):"")+(this.showMeridian?" "+this.meridian:"")},hideWidget:function(){this.isOpen!==!1&&(this.$element.trigger({type:"hide.timepicker",time:{value:this.getTime(),hours:this.hour,minutes:this.minute,seconds:this.second,meridian:this.meridian}}),"modal"===this.template&&this.$widget.modal?this.$widget.modal("hide"):this.$widget.removeClass("open"),a(c).off("mousedown.timepicker, touchend.timepicker",this.handleDocumentClick),this.isOpen=!1,this.$widget.detach())},highlightUnit:function(){this.position=this.getCursorPosition(),this.position>=0&&this.position<=2?this.highlightHour():this.position>=3&&this.position<=5?this.highlightMinute():this.position>=6&&this.position<=8?this.showSeconds?this.highlightSecond():this.highlightMeridian():this.position>=9&&this.position<=11&&this.highlightMeridian()},highlightNextUnit:function(){switch(this.highlightedUnit){case"hour":this.highlightMinute();break;case"minute":this.showSeconds?this.highlightSecond():this.showMeridian?this.highlightMeridian():this.highlightHour();break;case"second":this.showMeridian?this.highlightMeridian():this.highlightHour();break;case"meridian":this.highlightHour()}},highlightPrevUnit:function(){switch(this.highlightedUnit){case"hour":this.showMeridian?this.highlightMeridian():this.showSeconds?this.highlightSecond():this.highlightMinute();break;case"minute":this.highlightHour();break;case"second":this.highlightMinute();break;case"meridian":this.showSeconds?this.highlightSecond():this.highlightMinute()}},highlightHour:function(){var a=this.$element.get(0),b=this;this.highlightedUnit="hour",a.setSelectionRange&&setTimeout(function(){b.hour<10?a.setSelectionRange(0,1):a.setSelectionRange(0,2)},0)},highlightMinute:function(){var a=this.$element.get(0),b=this;this.highlightedUnit="minute",a.setSelectionRange&&setTimeout(function(){b.hour<10?a.setSelectionRange(2,4):a.setSelectionRange(3,5)},0)},highlightSecond:function(){var a=this.$element.get(0),b=this;this.highlightedUnit="second",a.setSelectionRange&&setTimeout(function(){b.hour<10?a.setSelectionRange(5,7):a.setSelectionRange(6,8)},0)},highlightMeridian:function(){var a=this.$element.get(0),b=this;this.highlightedUnit="meridian",a.setSelectionRange&&(this.showSeconds?setTimeout(function(){b.hour<10?a.setSelectionRange(8,10):a.setSelectionRange(9,11)},0):setTimeout(function(){b.hour<10?a.setSelectionRange(5,7):a.setSelectionRange(6,8)},0))},incrementHour:function(){if(this.showMeridian){if(11===this.hour)return this.hour++,this.toggleMeridian();12===this.hour&&(this.hour=0)}return this.hour===this.maxHours-1?void(this.hour=0):void this.hour++},incrementMinute:function(a){var b;b=a?this.minute+a:this.minute+this.minuteStep-this.minute%this.minuteStep,b>59?(this.incrementHour(),this.minute=b-60):this.minute=b},incrementSecond:function(){var a=this.second+this.secondStep-this.second%this.secondStep;a>59?(this.incrementMinute(!0),this.second=a-60):this.second=a},mousewheel:function(b){if(!this.disableMousewheel){b.preventDefault(),b.stopPropagation();var c=b.originalEvent.wheelDelta||-b.originalEvent.detail,d=null;switch("mousewheel"===b.type?d=-1*b.originalEvent.wheelDelta:"DOMMouseScroll"===b.type&&(d=40*b.originalEvent.detail),d&&(b.preventDefault(),a(this).scrollTop(d+a(this).scrollTop())),this.highlightedUnit){case"minute":c>0?this.incrementMinute():this.decrementMinute(),this.highlightMinute();break;case"second":c>0?this.incrementSecond():this.decrementSecond(),this.highlightSecond();break;case"meridian":this.toggleMeridian(),this.highlightMeridian();break;default:c>0?this.incrementHour():this.decrementHour(),this.highlightHour()}return!1}},changeToNearestStep:function(a,b){return a%b===0?a:Math.round(a%b/b)?(a+(b-a%b))%60:a-a%b},place:function(){if(!this.isInline){var c=this.$widget.outerWidth(),d=this.$widget.outerHeight(),e=10,f=a(b).width(),g=a(b).height(),h=a(b).scrollTop(),i=parseInt(this.$element.parents().filter(function(){return"auto"!==a(this).css("z-index")}).first().css("z-index"),10)+10,j=this.component?this.component.parent().offset():this.$element.offset(),k=this.component?this.component.outerHeight(!0):this.$element.outerHeight(!1),l=this.component?this.component.outerWidth(!0):this.$element.outerWidth(!1),m=j.left,n=j.top;this.$widget.removeClass("timepicker-orient-top timepicker-orient-bottom timepicker-orient-right timepicker-orient-left"),"auto"!==this.orientation.x?(this.$widget.addClass("timepicker-orient-"+this.orientation.x),"right"===this.orientation.x&&(m-=c-l)):(this.$widget.addClass("timepicker-orient-left"),j.left<0?m-=j.left-e:j.left+c>f&&(m=f-c-e));var o,p,q=this.orientation.y;"auto"===q&&(o=-h+j.top-d,p=h+g-(j.top+k+d),q=Math.max(o,p)===p?"top":"bottom"),this.$widget.addClass("timepicker-orient-"+q),"top"===q?n+=k:n-=d+
6126parseInt(this.$widget.css("padding-top"),10),this.$widget.css({top:n,left:m,zIndex:i})}},remove:function(){a("document").off(".timepicker"),this.$widget&&this.$widget.remove(),delete this.$element.data().timepicker},setDefaultTime:function(a){if(this.$element.val())this.updateFromElementVal();else if("current"===a){var b=new Date,c=b.getHours(),d=b.getMinutes(),e=b.getSeconds(),f="AM";0!==e&&(e=Math.ceil(b.getSeconds()/this.secondStep)*this.secondStep,60===e&&(d+=1,e=0)),0!==d&&(d=Math.ceil(b.getMinutes()/this.minuteStep)*this.minuteStep,60===d&&(c+=1,d=0)),this.showMeridian&&(0===c?c=12:c>=12?(c>12&&(c-=12),f="PM"):f="AM"),this.hour=c,this.minute=d,this.second=e,this.meridian=f,this.update()}else a===!1?(this.hour=0,this.minute=0,this.second=0,this.meridian="AM"):this.setTime(a)},setTime:function(a,b){if(!a)return void this.clear();var c,d,e,f,g,h;if("object"==typeof a&&a.getMonth)e=a.getHours(),f=a.getMinutes(),g=a.getSeconds(),this.showMeridian&&(h="AM",e>12&&(h="PM",e%=12),12===e&&(h="PM"));else{if(c=(/a/i.test(a)?1:0)+(/p/i.test(a)?2:0),c>2)return void this.clear();if(d=a.replace(/[^0-9\:]/g,"").split(":"),e=d[0]?d[0].toString():d.toString(),this.explicitMode&&e.length>2&&e.length%2!==0)return void this.clear();f=d[1]?d[1].toString():"",g=d[2]?d[2].toString():"",e.length>4&&(g=e.slice(-2),e=e.slice(0,-2)),e.length>2&&(f=e.slice(-2),e=e.slice(0,-2)),f.length>2&&(g=f.slice(-2),f=f.slice(0,-2)),e=parseInt(e,10),f=parseInt(f,10),g=parseInt(g,10),isNaN(e)&&(e=0),isNaN(f)&&(f=0),isNaN(g)&&(g=0),g>59&&(g=59),f>59&&(f=59),e>=this.maxHours&&(e=this.maxHours-1),this.showMeridian?(e>12&&(c=2,e-=12),c||(c=1),0===e&&(e=12),h=1===c?"AM":"PM"):12>e&&2===c?e+=12:e>=this.maxHours?e=this.maxHours-1:(0>e||12===e&&1===c)&&(e=0)}this.hour=e,this.snapToStep?(this.minute=this.changeToNearestStep(f,this.minuteStep),this.second=this.changeToNearestStep(g,this.secondStep)):(this.minute=f,this.second=g),this.meridian=h,this.update(b)},showWidget:function(){this.isOpen||this.$element.is(":disabled")||(this.$widget.appendTo(this.appendWidgetTo),a(c).on("mousedown.timepicker, touchend.timepicker",{scope:this},this.handleDocumentClick),this.$element.trigger({type:"show.timepicker",time:{value:this.getTime(),hours:this.hour,minutes:this.minute,seconds:this.second,meridian:this.meridian}}),this.place(),this.disableFocus&&this.$element.blur(),""===this.hour&&(this.defaultTime?this.setDefaultTime(this.defaultTime):this.setTime("0:0:0")),"modal"===this.template&&this.$widget.modal?this.$widget.modal("show").on("hidden",a.proxy(this.hideWidget,this)):this.isOpen===!1&&this.$widget.addClass("open"),this.isOpen=!0)},toggleMeridian:function(){this.meridian="AM"===this.meridian?"PM":"AM"},update:function(a){this.updateElement(),a||this.updateWidget(),this.$element.trigger({type:"changeTime.timepicker",time:{value:this.getTime(),hours:this.hour,minutes:this.minute,seconds:this.second,meridian:this.meridian}})},updateElement:function(){this.$element.val(this.getTime()).change()},updateFromElementVal:function(){this.setTime(this.$element.val())},updateWidget:function(){if(this.$widget!==!1){var a=this.hour,b=1===this.minute.toString().length?"0"+this.minute:this.minute,c=1===this.second.toString().length?"0"+this.second:this.second;this.showInputs?(this.$widget.find("input.bootstrap-timepicker-hour").val(a),this.$widget.find("input.bootstrap-timepicker-minute").val(b),this.showSeconds&&this.$widget.find("input.bootstrap-timepicker-second").val(c),this.showMeridian&&this.$widget.find("input.bootstrap-timepicker-meridian").val(this.meridian)):(this.$widget.find("span.bootstrap-timepicker-hour").text(a),this.$widget.find("span.bootstrap-timepicker-minute").text(b),this.showSeconds&&this.$widget.find("span.bootstrap-timepicker-second").text(c),this.showMeridian&&this.$widget.find("span.bootstrap-timepicker-meridian").text(this.meridian))}},updateFromWidgetInputs:function(){if(this.$widget!==!1){var a=this.$widget.find("input.bootstrap-timepicker-hour").val()+":"+this.$widget.find("input.bootstrap-timepicker-minute").val()+(this.showSeconds?":"+this.$widget.find("input.bootstrap-timepicker-second").val():"")+(this.showMeridian?this.$widget.find("input.bootstrap-timepicker-meridian").val():"");this.setTime(a,!0)}},widgetClick:function(b){b.stopPropagation(),b.preventDefault();var c=a(b.target),d=c.closest("a").data("action");d&&this[d](),this.update(),c.is("input")&&c.get(0).setSelectionRange(0,2)},widgetKeydown:function(b){var c=a(b.target),d=c.attr("class").replace("bootstrap-timepicker-","");
6126switch(b.which){case 9:if(b.shiftKey){if("hour"===d)return this.hideWidget()}else if(this.showMeridian&&"meridian"===d||this.showSeconds&&"second"===d||!this.showMeridian&&!this.showSeconds&&"minute"===d)return this.hideWidget();break;case 27:this.hideWidget();break;case 38:switch(b.preventDefault(),d){case"hour":this.incrementHour();break;case"minute":this.incrementMinute();break;case"second":this.incrementSecond();break;case"meridian":this.toggleMeridian()}this.setTime(this.getTime()),c.get(0).setSelectionRange(0,2);break;case 40:switch(b.preventDefault(),d){case"hour":this.decrementHour();break;case"minute":this.decrementMinute();break;case"second":this.decrementSecond();break;case"meridian":this.toggleMeridian()}this.setTime(this.getTime()),c.get(0).setSelectionRange(0,2)}},widgetKeyup:function(a){(65===a.which||77===a.which||80===a.which||46===a.which||8===a.which||a.which>=48&&a.which<=57||a.which>=96&&a.which<=105)&&this.updateFromWidgetInputs()}},a.fn.timepicker=function(b){var c=Array.apply(null,arguments);return c.shift(),this.each(function(){var e=a(this),f=e.data("timepicker"),g="object"==typeof b&&b;f||e.data("timepicker",f=new d(this,a.extend({},a.fn.timepicker.defaults,g,a(this).data()))),"string"==typeof b&&f[b].apply(f,c)})},a.fn.timepicker.defaults={defaultTime:"current",disableFocus:!1,disableMousewheel:!1,isOpen:!1,minuteStep:15,modalBackdrop:!1,orientation:{x:"auto",y:"auto"},secondStep:15,snapToStep:!1,showSeconds:!1,showInputs:!0,showMeridian:!0,template:"dropdown",appendWidgetTo:"body",showWidgetOnAddonClick:!0,icons:{up:"glyphicon glyphicon-chevron-up",down:"glyphicon glyphicon-chevron-down"},maxHours:24,explicitMode:!1},a.fn.timepicker.Constructor=d,a(c).on("focus.timepicker.data-api click.timepicker.data-api",'[data-provide="timepicker"]',function(b){var c=a(this);c.data("timepicker")||(b.preventDefault(),c.timepicker())})}(jQuery,window,document);
6127$.fn.timepicker.defaults = $.extend(true, {}, $.fn.timepicker.defaults, {
6128    icons: {
6129        up: 'la la-angle-up',
6130        down: 'la la-angle-down'  
6131    }
6132});
6133/**
6134* @version: 2.1.30
6135* @author: Dan Grossman http://www.dangrossman.info/
6136* @copyright: Copyright (c) 2012-2017 Dan Grossman. All rights reserved.
6137* @license: Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php
6138* @website: http://www.daterangepicker.com/
6139*/
6140// Follow the UMD template https://github.com/umdjs/umd/blob/master/templates/returnExportsGlobal.js
6141(function (root, factory) {
6142    if (typeof define === 'function' && define.amd) {
6143        // AMD. Make globaly available as well
6144        define(['moment', 'jquery'], function (moment, jquery) {
6145            if (!jquery.fn) jquery.fn = {}; // webpack server rendering
6146            return factory(moment, jquery);
6147        });
6148    } else if (typeof module === 'object' && module.exports) {
6149        // Node / Browserify
6150        //isomorphic issue
6151        var jQuery = (typeof window != 'undefined') ? window.jQuery : undefined;
6152        if (!jQuery) {
6153            jQuery = require('jquery');
6154            if (!jQuery.fn) jQuery.fn = {};
6155        }
6156        var moment = (typeof window != 'undefined' && typeof window.moment != 'undefined') ? window.moment : require('moment');
6157        module.exports = factory(moment, jQuery);
6158    } else {
6159        // Browser globals
6160        root.daterangepicker = factory(root.moment, root.jQuery);
6161    }
6162}(this, function(moment, $) {
6163    var DateRangePicker = function(element, options, cb) {
6164
6165        //default settings for options
6166        this.parentEl = 'body';
6167        this.element = $(element);
6168        this.startDate = moment().startOf('day');
6169        this.endDate = moment().endOf('day');
6170        this.minDate = false;
6171        this.maxDate = false;
6172        this.dateLimit = false;
6173        this.autoApply = false;
6174        this.singleDatePicker = false;
6175        this.showDropdowns = false;
6176        this.showWeekNumbers = false;
6177        this.showISOWeekNumbers = false;
6178        this.showCustomRangeLabel = true;
6179        this.timePicker = false;
6180        this.timePicker24Hour = false;
6181        this.timePickerIncrement = 1;
6182        this.timePickerSeconds = false;
6183        this.linkedCalendars = true;
6184        this.autoUpdateInput = true;
6185        this.alwaysShowCalendars = false;
6186        this.ranges = {};
6187
6188        this.opens = 'right';
6189        if (this.element.hasClass('pull-right'))
6190            this.opens = 'left';
6191
6192        this.drops = 'down';
6193        if (this.element.hasClass('dropup'))
6194            this.drops = 'up';
6195
vendor: 64,159 bytes, lines 6196-7628
6196        this.buttonClasses = 'btn btn-sm';
6197        this.applyClass = 'btn-success';
6198        this.cancelClass = 'btn-default';
6199
6200        this.locale = {
6201            direction: 'ltr',
6202            format: moment.localeData().longDateFormat('L'),
6203            separator: ' - ',
6204            applyLabel: 'Apply',
6205            cancelLabel: 'Cancel',
6206            weekLabel: 'W',
6207            customRangeLabel: 'Custom Range',
6208            daysOfWeek: moment.weekdaysMin(),
6209            monthNames: moment.monthsShort(),
6210            firstDay: moment.localeData().firstDayOfWeek()
6211        };
6212
6213        this.callback = function() { };
6214
6215        //some state information
6216        this.isShowing = false;
6217        this.leftCalendar = {};
6218        this.rightCalendar = {};
6219
6220        //custom options from user
6221        if (typeof options !== 'object' || options === null)
6222            options = {};
6223
6224        //allow setting options with data attributes
6225        //data-api options will be overwritten with custom javascript options
6226        options = $.extend(this.element.data(), options);
6227
6228        //html template for the picker UI
6229        if (typeof options.template !== 'string' && !(options.template instanceof $))
6230            options.template = '<div class="daterangepicker dropdown-menu">' +
6231                '<div class="calendar left">' +
6232                    '<div class="daterangepicker_input">' +
6233                      '<input class="input-mini form-control" type="text" name="daterangepicker_start" value="" />' +
6234                      '<i class="fa fa-calendar glyphicon glyphicon-calendar"></i>' +
6235                      '<div class="calendar-time">' +
6236                        '<div></div>' +
6237                        '<i class="fa fa-clock-o glyphicon glyphicon-time"></i>' +
6238                      '</div>' +
6239                    '</div>' +
6240                    '<div class="calendar-table"></div>' +
6241                '</div>' +
6242                '<div class="calendar right">' +
6243                    '<div class="daterangepicker_input">' +
6244                      '<input class="input-mini form-control" type="text" name="daterangepicker_end" value="" />' +
6245                      '<i class="fa fa-calendar glyphicon glyphicon-calendar"></i>' +
6246                      '<div class="calendar-time">' +
6247                        '<div></div>' +
6248                        '<i class="fa fa-clock-o glyphicon glyphicon-time"></i>' +
6249                      '</div>' +
6250                    '</div>' +
6251                    '<div class="calendar-table"></div>' +
6252                '</div>' +
6253                '<div class="ranges">' +
6254                    '<div class="range_inputs">' +
6255                        '<button class="applyBtn" disabled="disabled" type="button"></button> ' +
6256                        '<button class="cancelBtn" type="button"></button>' +
6257                    '</div>' +
6258                '</div>' +
6259            '</div>';
6260
6261        this.parentEl = (options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl);
6262        this.container = $(options.template).appendTo(this.parentEl);
6263
6264        //
6265        // handle all the possible options overriding defaults
6266        //
6267
6268        if (typeof options.locale === 'object') {
6269
6270            if (typeof options.locale.direction === 'string')
6271                this.locale.direction = options.locale.direction;
6272
6273            if (typeof options.locale.format === 'string')
6274                this.locale.format = options.locale.format;
6275
6276            if (typeof options.locale.separator === 'string')
6277                this.locale.separator = options.locale.separator;
6278
6279            if (typeof options.locale.daysOfWeek === 'object')
6280                this.locale.daysOfWeek = options.locale.daysOfWeek.slice();
6281
6282            if (typeof options.locale.monthNames === 'object')
6283              this.locale.monthNames = options.locale.monthNames.slice();
6284
6285            if (typeof options.locale.firstDay === 'number')
6286              this.locale.firstDay = options.locale.firstDay;
6287
6288            if (typeof options.locale.applyLabel === 'string')
6289              this.locale.applyLabel = options.locale.applyLabel;
6290
6291            if (typeof options.locale.cancelLabel === 'string')
6292              this.locale.cancelLabel = options.locale.cancelLabel;
6293
6294            if (typeof options.locale.weekLabel === 'string')
6295              this.locale.weekLabel = options.locale.weekLabel;
6296
6297            if (typeof options.locale.customRangeLabel === 'string'){
6298                //Support unicode chars in the custom range name.
6299                var elem = document.createElement('textarea');
6300                elem.innerHTML = options.locale.customRangeLabel;
6301                var rangeHtml = elem.value;
6302                this.locale.customRangeLabel = rangeHtml;
6303            }
6304        }
6305        this.container.addClass(this.locale.direction);
6306
6307        if (typeof options.startDate === 'string')
6308            this.startDate = moment(options.startDate, this.locale.format);
6309
6310        if (typeof options.endDate === 'string')
6311            this.endDate = moment(options.endDate, this.locale.format);
6312
6313        if (typeof options.minDate === 'string')
6314            this.minDate = moment(options.minDate, this.locale.format);
6315
6316        if (typeof options.maxDate === 'string')
6317            this.maxDate = moment(options.maxDate, this.locale.format);
6318
6319        if (typeof options.startDate === 'object')
6320            this.startDate = moment(options.startDate);
6321
6322        if (typeof options.endDate === 'object')
6323            this.endDate = moment(options.endDate);
6324
6325        if (typeof options.minDate === 'object')
6326            this.minDate = moment(options.minDate);
6327
6328        if (typeof options.maxDate === 'object')
6329            this.maxDate = moment(options.maxDate);
6330
6331        // sanity check for bad options
6332        if (this.minDate && this.startDate.isBefore(this.minDate))
6333            this.startDate = this.minDate.clone();
6334
6335        // sanity check for bad options
6336        if (this.maxDate && this.endDate.isAfter(this.maxDate))
6337            this.endDate = this.maxDate.clone();
6338
6339        if (typeof options.applyClass === 'string')
6340            this.applyClass = options.applyClass;
6341
6342        if (typeof options.cancelClass === 'string')
6343            this.cancelClass = options.cancelClass;
6344
6345        if (typeof options.dateLimit === 'object')
6346            this.dateLimit = options.dateLimit;
6347
6348        if (typeof options.opens === 'string')
6349            this.opens = options.opens;
6350
6351        if (typeof options.drops === 'string')
6352            this.drops = options.drops;
6353
6354        if (typeof options.showWeekNumbers === 'boolean')
6355            this.showWeekNumbers = options.showWeekNumbers;
6356
6357        if (typeof options.showISOWeekNumbers === 'boolean')
6358            this.showISOWeekNumbers = options.showISOWeekNumbers;
6359
6360        if (typeof options.buttonClasses === 'string')
6361            this.buttonClasses = options.buttonClasses;
6362
6363        if (typeof options.buttonClasses === 'object')
6364            this.buttonClasses = options.buttonClasses.join(' ');
6365
6366        if (typeof options.showDropdowns === 'boolean')
6367            this.showDropdowns = options.showDropdowns;
6368
6369        if (typeof options.showCustomRangeLabel === 'boolean')
6370            this.showCustomRangeLabel = options.showCustomRangeLabel;
6371
6372        if (typeof options.singleDatePicker === 'boolean') {
6373            this.singleDatePicker = options.singleDatePicker;
6374            if (this.singleDatePicker)
6375                this.endDate = this.startDate.clone();
6376        }
6377
6378        if (typeof options.timePicker === 'boolean')
6379            this.timePicker = options.timePicker;
6380
6381        if (typeof options.timePickerSeconds === 'boolean')
6382            this.timePickerSeconds = options.timePickerSeconds;
6383
6384        if (typeof options.timePickerIncrement === 'number')
6385            this.timePickerIncrement = options.timePickerIncrement;
6386
6387        if (typeof options.timePicker24Hour === 'boolean')
6388            this.timePicker24Hour = options.timePicker24Hour;
6389
6390        if (typeof options.autoApply === 'boolean')
6391            this.autoApply = options.autoApply;
6392
6393        if (typeof options.autoUpdateInput === 'boolean')
6394            this.autoUpdateInput = options.autoUpdateInput;
6395
6396        if (typeof options.linkedCalendars === 'boolean')
6397            this.linkedCalendars = options.linkedCalendars;
6398
6399        if (typeof options.isInvalidDate === 'function')
6400            this.isInvalidDate = options.isInvalidDate;
6401
6402        if (typeof options.isCustomDate === 'function')
6403            this.isCustomDate = options.isCustomDate;
6404
6405        if (typeof options.alwaysShowCalendars === 'boolean')
6406            this.alwaysShowCalendars = options.alwaysShowCalendars;
6407
6408        // update day names order to firstDay
6409        if (this.locale.firstDay != 0) {
6410            var iterator = this.locale.firstDay;
6411            while (iterator > 0) {
6412                this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift());
6413                iterator--;
6414            }
6415        }
6416
6417        var start, end, range;
6418
6419        //if no start/end dates set, check if an input element contains initial values
6420        if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') {
6421            if ($(this.element).is('input[type=text]')) {
6422                var val = $(this.element).val(),
6423                    split = val.split(this.locale.separator);
6424
6425                start = end = null;
6426
6427                if (split.length == 2) {
6428                    start = moment(split[0], this.locale.format);
6429                    end = moment(split[1], this.locale.format);
6430                } else if (this.singleDatePicker && val !== "") {
6431                    start = moment(val, this.locale.format);
6432                    end = moment(val, this.locale.format);
6433                }
6434                if (start !== null && end !== null) {
6435                    this.setStartDate(start);
6436                    this.setEndDate(end);
6437                }
6438            }
6439        }
6440
6441        if (typeof options.ranges === 'object') {
6442            for (range in options.ranges) {
6443
6444                if (typeof options.ranges[range][0] === 'string')
6445                    start = moment(options.ranges[range][0], this.locale.format);
6446                else
6447                    start = moment(options.ranges[range][0]);
6448
6449                if (typeof options.ranges[range][1] === 'string')
6450                    end = moment(options.ranges[range][1], this.locale.format);
6451                else
6452                    end = moment(options.ranges[range][1]);
6453
6454                // If the start or end date exceed those allowed by the minDate or dateLimit
6455                // options, shorten the range to the allowable period.
6456                if (this.minDate && start.isBefore(this.minDate))
6457                    start = this.minDate.clone();
6458
6459                var maxDate = this.maxDate;
6460                if (this.dateLimit && maxDate && start.clone().add(this.dateLimit).isAfter(maxDate))
6461                    maxDate = start.clone().add(this.dateLimit);
6462                if (maxDate && end.isAfter(maxDate))
6463                    end = maxDate.clone();
6464
6465                // If the end of the range is before the minimum or the start of the range is
6466                // after the maximum, don't display this range option at all.
6467                if ((this.minDate && end.isBefore(this.minDate, this.timepicker ? 'minute' : 'day')) 
6468                  || (maxDate && start.isAfter(maxDate, this.timepicker ? 'minute' : 'day')))
6469                    continue;
6470
6471                //Support unicode chars in the range names.
6472                var elem = document.createElement('textarea');
6473                elem.innerHTML = range;
6474                var rangeHtml = elem.value;
6475
6476                this.ranges[rangeHtml] = [start, end];
6477            }
6478
6479            var list = '<ul>';
6480            for (range in this.ranges) {
6481                list += '<li data-range-key="' + range + '">' + range + '</li>';
6482            }
6483            if (this.showCustomRangeLabel) {
6484                list += '<li data-range-key="' + this.locale.customRangeLabel + '">' + this.locale.customRangeLabel + '</li>';
6485            }
6486            list += '</ul>';
6487            this.container.find('.ranges').prepend(list);
6488        }
6489
6490        if (typeof cb === 'function') {
6491            this.callback = cb;
6492        }
6493
6494        if (!this.timePicker) {
6495            this.startDate = this.startDate.startOf('day');
6496            this.endDate = this.endDate.endOf('day');
6497            this.container.find('.calendar-time').hide();
6498        }
6499
6500        //can't be used together for now
6501        if (this.timePicker && this.autoApply)
6502            this.autoApply = false;
6503
6504        if (this.autoApply && typeof options.ranges !== 'object') {
6505            this.container.find('.ranges').hide();
6506        } else if (this.autoApply) {
6507            this.container.find('.applyBtn, .cancelBtn').addClass('hide');
6508        }
6509
6510        if (this.singleDatePicker) {
6511            this.container.addClass('single');
6512            this.container.find('.calendar.left').addClass('single');
6513            this.container.find('.calendar.left').show();
6514            this.container.find('.calendar.right').hide();
6515            this.container.find('.daterangepicker_input input, .daterangepicker_input > i').hide();
6516            if (this.timePicker) {
6517                this.container.find('.ranges ul').hide();
6518            } else {
6519                this.container.find('.ranges').hide();
6520            }
6521        }
6522
6523        if ((typeof options.ranges === 'undefined' && !this.singleDatePicker) || this.alwaysShowCalendars) {
6524            this.container.addClass('show-calendar');
6525        }
6526
6527        this.container.addClass('opens' + this.opens);
6528
6529        //swap the position of the predefined ranges if opens right
6530        if (typeof options.ranges !== 'undefined' && this.opens == 'right') {
6531            this.container.find('.ranges').prependTo( this.container.find('.calendar.left').parent() );
6532        }
6533
6534        //apply CSS classes and labels to buttons
6535        this.container.find('.applyBtn, .cancelBtn').addClass(this.buttonClasses);
6536        if (this.applyClass.length)
6537            this.container.find('.applyBtn').addClass(this.applyClass);
6538        if (this.cancelClass.length)
6539            this.container.find('.cancelBtn').addClass(this.cancelClass);
6540        this.container.find('.applyBtn').html(this.locale.applyLabel);
6541        this.container.find('.cancelBtn').html(this.locale.cancelLabel);
6542
6543        //
6544        // event listeners
6545        //
6546
6547        this.container.find('.calendar')
6548            .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this))
6549            .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this))
6550            .on('mousedown.daterangepicker', 'td.available', $.proxy(this.clickDate, this))
6551            .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.hoverDate, this))
6552            .on('mouseleave.daterangepicker', 'td.available', $.proxy(this.updateFormInputs, this))
6553            .on('change.daterangepicker', 'select.yearselect', $.proxy(this.monthOrYearChanged, this))
6554            .on('change.daterangepicker', 'select.monthselect', $.proxy(this.monthOrYearChanged, this))
6555            .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.secondselect,select.ampmselect', $.proxy(this.timeChanged, this))
6556            .on('click.daterangepicker', '.daterangepicker_input input', $.proxy(this.showCalendars, this))
6557            .on('focus.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsFocused, this))
6558            .on('blur.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsBlurred, this))
6559            .on('change.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsChanged, this))
6560            .on('keydown.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsKeydown, this));
6561
6562        this.container.find('.ranges')
6563            .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this))
6564            .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this))
6565            .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this))
6566            .on('mouseenter.daterangepicker', 'li', $.proxy(this.hoverRange, this))
6567            .on('mouseleave.daterangepicker', 'li', $.proxy(this.updateFormInputs, this));
6568
6569        if (this.element.is('input') || this.element.is('button')) {
6570            this.element.on({
6571                'click.daterangepicker': $.proxy(this.show, this),
6572                'focus.daterangepicker': $.proxy(this.show, this),
6573                'keyup.daterangepicker': $.proxy(this.elementChanged, this),
6574                'keydown.daterangepicker': $.proxy(this.keydown, this) //IE 11 compatibility
6575            });
6576        } else {
6577            this.element.on('click.daterangepicker', $.proxy(this.toggle, this));
6578            this.element.on('keydown.daterangepicker', $.proxy(this.toggle, this));
6579        }
6580
6581        //
6582        // if attached to a text input, set the initial value
6583        //
6584
6585        if (this.element.is('input') && !this.singleDatePicker && this.autoUpdateInput) {
6586            this.element.val(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format));
6587            this.element.trigger('change');
6588        } else if (this.element.is('input') && this.autoUpdateInput) {
6589            this.element.val(this.startDate.format(this.locale.format));
6590            this.element.trigger('change');
6591        }
6592
6593    };
6594
6595    DateRangePicker.prototype = {
6596
6597        constructor: DateRangePicker,
6598
6599        setStartDate: function(startDate) {
6600            if (typeof startDate === 'string')
6601                this.startDate = moment(startDate, this.locale.format);
6602
6603            if (typeof startDate === 'object')
6604                this.startDate = moment(startDate);
6605
6606            if (!this.timePicker)
6607                this.startDate = this.startDate.startOf('day');
6608
6609            if (this.timePicker && this.timePickerIncrement)
6610                this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);
6611
6612            if (this.minDate && this.startDate.isBefore(this.minDate)) {
6613                this.startDate = this.minDate.clone();
6614                if (this.timePicker && this.timePickerIncrement)
6615                    this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);
6616            }
6617
6618            if (this.maxDate && this.startDate.isAfter(this.maxDate)) {
6619                this.startDate = this.maxDate.clone();
6620                if (this.timePicker && this.timePickerIncrement)
6621                    this.startDate.minute(Math.floor(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);
6622            }
6623
6624            if (!this.isShowing)
6625                this.updateElement();
6626
6627            this.updateMonthsInView();
6628        },
6629
6630        setEndDate: function(endDate) {
6631            if (typeof endDate === 'string')
6632                this.endDate = moment(endDate, this.locale.format);
6633
6634            if (typeof endDate === 'object')
6635                this.endDate = moment(endDate);
6636
6637            if (!this.timePicker)
6638                this.endDate = this.endDate.add(1,'d').startOf('day').subtract(1,'second');
6639
6640            if (this.timePicker && this.timePickerIncrement)
6641                this.endDate.minute(Math.round(this.endDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);
6642
6643            if (this.endDate.isBefore(this.startDate))
6644                this.endDate = this.startDate.clone();
6645
6646            if (this.maxDate && this.endDate.isAfter(this.maxDate))
6647                this.endDate = this.maxDate.clone();
6648
6649            if (this.dateLimit && this.startDate.clone().add(this.dateLimit).isBefore(this.endDate))
6650                this.endDate = this.startDate.clone().add(this.dateLimit);
6651
6652            this.previousRightTime = this.endDate.clone();
6653
6654            if (!this.isShowing)
6655                this.updateElement();
6656
6657            this.updateMonthsInView();
6658        },
6659
6660        isInvalidDate: function() {
6661            return false;
6662        },
6663
6664        isCustomDate: function() {
6665            return false;
6666        },
6667
6668        updateView: function() {
6669            if (this.timePicker) {
6670                this.renderTimePicker('left');
6671                this.renderTimePicker('right');
6672                if (!this.endDate) {
6673                    this.container.find('.right .calendar-time select').attr('disabled', 'disabled').addClass('disabled');
6674                } else {
6675                    this.container.find('.right .calendar-time select').removeAttr('disabled').removeClass('disabled');
6676                }
6677            }
6678            if (this.endDate) {
6679                this.container.find('input[name="daterangepicker_end"]').removeClass('active');
6680                this.container.find('input[name="daterangepicker_start"]').addClass('active');
6681            } else {
6682                this.container.find('input[name="daterangepicker_end"]').addClass('active');
6683                this.container.find('input[name="daterangepicker_start"]').removeClass('active');
6684            }
6685            this.updateMonthsInView();
6686            this.updateCalendars();
6687            this.updateFormInputs();
6688        },
6689
6690        updateMonthsInView: function() {
6691            if (this.endDate) {
6692
6693                //if both dates are visible already, do nothing
6694                if (!this.singleDatePicker && this.leftCalendar.month && this.rightCalendar.month &&
6695                    (this.startDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.startDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM'))
6696                    &&
6697                    (this.endDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.endDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM'))
6698                    ) {
6699                    return;
6700                }
6701
6702                this.leftCalendar.month = this.startDate.clone().date(2);
6703                if (!this.linkedCalendars && (this.endDate.month() != this.startDate.month() || this.endDate.year() != this.startDate.year())) {
6704                    this.rightCalendar.month = this.endDate.clone().date(2);
6705                } else {
6706                    this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month');
6707                }
6708
6709            } else {
6710                if (this.leftCalendar.month.format('YYYY-MM') != this.startDate.format('YYYY-MM') && this.rightCalendar.month.format('YYYY-MM') != this.startDate.format('YYYY-MM')) {
6711                    this.leftCalendar.month = this.startDate.clone().date(2);
6712                    this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month');
6713                }
6714            }
6715            if (this.maxDate && this.linkedCalendars && !this.singleDatePicker && this.rightCalendar.month > this.maxDate) {
6716              this.rightCalendar.month = this.maxDate.clone().date(2);
6717              this.leftCalendar.month = this.maxDate.clone().date(2).subtract(1, 'month');
6718            }
6719        },
6720
6721        updateCalendars: function() {
6722
6723            if (this.timePicker) {
6724                var hour, minute, second;
6725                if (this.endDate) {
6726                    hour = parseInt(this.container.find('.left .hourselect').val(), 10);
6727                    minute = parseInt(this.container.find('.left .minuteselect').val(), 10);
6728                    second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0;
6729                    if (!this.timePicker24Hour) {
6730                        var ampm = this.container.find('.left .ampmselect').val();
6731                        if (ampm === 'PM' && hour < 12)
6732                            hour += 12;
6733                        if (ampm === 'AM' && hour === 12)
6734                            hour = 0;
6735                    }
6736                } else {
6737                    hour = parseInt(this.container.find('.right .hourselect').val(), 10);
6738                    minute = parseInt(this.container.find('.right .minuteselect').val(), 10);
6739                    second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0;
6740                    if (!this.timePicker24Hour) {
6741                        var ampm = this.container.find('.right .ampmselect').val();
6742                        if (ampm === 'PM' && hour < 12)
6743                            hour += 12;
6744                        if (ampm === 'AM' && hour === 12)
6745                            hour = 0;
6746                    }
6747                }
6748                this.leftCalendar.month.hour(hour).minute(minute).second(second);
6749                this.rightCalendar.month.hour(hour).minute(minute).second(second);
6750            }
6751
6752            this.renderCalendar('left');
6753            this.renderCalendar('right');
6754
6755            //highlight any predefined range matching the current start and end dates
6756            this.container.find('.ranges li').removeClass('active');
6757            if (this.endDate == null) return;
6758
6759            this.calculateChosenLabel();
6760        },
6761
6762        renderCalendar: function(side) {
6763
6764            //
6765            // Build the matrix of dates that will populate the calendar
6766            //
6767
6768            var calendar = side == 'left' ? this.leftCalendar : this.rightCalendar;
6769            var month = calendar.month.month();
6770            var year = calendar.month.year();
6771            var hour = calendar.month.hour();
6772            var minute = calendar.month.minute();
6773            var second = calendar.month.second();
6774            var daysInMonth = moment([year, month]).daysInMonth();
6775            var firstDay = moment([year, month, 1]);
6776            var lastDay = moment([year, month, daysInMonth]);
6777            var lastMonth = moment(firstDay).subtract(1, 'month').month();
6778            var lastYear = moment(firstDay).subtract(1, 'month').year();
6779            var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth();
6780            var dayOfWeek = firstDay.day();
6781
6782            //initialize a 6 rows x 7 columns array for the calendar
6783            var calendar = [];
6784            calendar.firstDay = firstDay;
6785            calendar.lastDay = lastDay;
6786
6787            for (var i = 0; i < 6; i++) {
6788                calendar[i] = [];
6789            }
6790
6791            //populate the calendar with date objects
6792            var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1;
6793            if (startDay > daysInLastMonth)
6794                startDay -= 7;
6795
6796            if (dayOfWeek == this.locale.firstDay)
6797                startDay = daysInLastMonth - 6;
6798
6799            var curDate = moment([lastYear, lastMonth, startDay, 12, minute, second]);
6800
6801            var col, row;
6802            for (var i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add(24, 'hour')) {
6803                if (i > 0 && col % 7 === 0) {
6804                    col = 0;
6805                    row++;
6806                }
6807                calendar[row][col] = curDate.clone().hour(hour).minute(minute).second(second);
6808                curDate.hour(12);
6809
6810                if (this.minDate && calendar[row][col].format('YYYY-MM-DD') == this.minDate.format('YYYY-MM-DD') && calendar[row][col].isBefore(this.minDate) && side == 'left') {
6811                    calendar[row][col] = this.minDate.clone();
6812                }
6813
6814                if (this.maxDate && calendar[row][col].format('YYYY-MM-DD') == this.maxDate.format('YYYY-MM-DD') && calendar[row][col].isAfter(this.maxDate) && side == 'right') {
6815                    calendar[row][col] = this.maxDate.clone();
6816                }
6817
6818            }
6819
6820            //make the calendar object available to hoverDate/clickDate
6821            if (side == 'left') {
6822                this.leftCalendar.calendar = calendar;
6823            } else {
6824                this.rightCalendar.calendar = calendar;
6825            }
6826
6827            //
6828            // Display the calendar
6829            //
6830
6831            var minDate = side == 'left' ? this.minDate : this.startDate;
6832            var maxDate = this.maxDate;
6833            var selected = side == 'left' ? this.startDate : this.endDate;
6834            var arrow = this.locale.direction == 'ltr' ? {left: 'chevron-left', right: 'chevron-right'} : {left: 'chevron-right', right: 'chevron-left'};
6835
6836            var html = '<table class="table-condensed">';
6837            html += '<thead>';
6838            html += '<tr>';
6839
6840            // add empty cell for week number
6841            if (this.showWeekNumbers || this.showISOWeekNumbers)
6842                html += '<th></th>';
6843
6844            if ((!minDate || minDate.isBefore(calendar.firstDay)) && (!this.linkedCalendars || side == 'left')) {
6845                html += '<th class="prev available"><i class="fa fa-' + arrow.left + ' glyphicon glyphicon-' + arrow.left + '"></i></th>';
6846            } else {
6847                html += '<th></th>';
6848            }
6849
6850            var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(" YYYY");
6851
6852            if (this.showDropdowns) {
6853                var currentMonth = calendar[1][1].month();
6854                var currentYear = calendar[1][1].year();
6855                var maxYear = (maxDate && maxDate.year()) || (currentYear + 5);
6856                var minYear = (minDate && minDate.year()) || (currentYear - 50);
6857                var inMinYear = currentYear == minYear;
6858                var inMaxYear = currentYear == maxYear;
6859
6860                var monthHtml = '<select class="monthselect">';
6861                for (var m = 0; m < 12; m++) {
6862                    if ((!inMinYear || m >= minDate.month()) && (!inMaxYear || m <= maxDate.month())) {
6863                        monthHtml += "<option value='" + m + "'" +
6864                            (m === currentMonth ? " selected='selected'" : "") +
6865                            ">" + this.locale.monthNames[m] + "</option>";
6866                    } else {
6867                        monthHtml += "<option value='" + m + "'" +
6868                            (m === currentMonth ? " selected='selected'" : "") +
6869                            " disabled='disabled'>" + this.locale.monthNames[m] + "</option>";
6870                    }
6871                }
6872                monthHtml += "</select>";
6873
6874                var yearHtml = '<select class="yearselect">';
6875                for (var y = minYear; y <= maxYear; y++) {
6876                    yearHtml += '<option value="' + y + '"' +
6877                        (y === currentYear ? ' selected="selected"' : '') +
6878                        '>' + y + '</option>';
6879                }
6880                yearHtml += '</select>';
6881
6882                dateHtml = monthHtml + yearHtml;
6883            }
6884
6885            html += '<th colspan="5" class="month">' + dateHtml + '</th>';
6886            if ((!maxDate || maxDate.isAfter(calendar.lastDay)) && (!this.linkedCalendars || side == 'right' || this.singleDatePicker)) {
6887                html += '<th class="next available"><i class="fa fa-' + arrow.right + ' glyphicon glyphicon-' + arrow.right + '"></i></th>';
6888            } else {
6889                html += '<th></th>';
6890            }
6891
6892            html += '</tr>';
6893            html += '<tr>';
6894
6895            // add week number label
6896            if (this.showWeekNumbers || this.showISOWeekNumbers)
6897                html += '<th class="week">' + this.locale.weekLabel + '</th>';
6898
6899            $.each(this.locale.daysOfWeek, function(index, dayOfWeek) {
6900                html += '<th>' + dayOfWeek + '</th>';
6901            });
6902
6903            html += '</tr>';
6904            html += '</thead>';
6905            html += '<tbody>';
6906
6907            //adjust maxDate to reflect the dateLimit setting in order to
6908            //grey out end dates beyond the dateLimit
6909            if (this.endDate == null && this.dateLimit) {
6910                var maxLimit = this.startDate.clone().add(this.dateLimit).endOf('day');
6911                if (!maxDate || maxLimit.isBefore(maxDate)) {
6912                    maxDate = maxLimit;
6913                }
6914            }
6915
6916            for (var row = 0; row < 6; row++) {
6917                html += '<tr>';
6918
6919                // add week number
6920                if (this.showWeekNumbers)
6921                    html += '<td class="week">' + calendar[row][0].week() + '</td>';
6922                else if (this.showISOWeekNumbers)
6923                    html += '<td class="week">' + calendar[row][0].isoWeek() + '</td>';
6924
6925                for (var col = 0; col < 7; col++) {
6926
6927                    var classes = [];
6928
6929                    //highlight today's date
6930                    if (calendar[row][col].isSame(new Date(), "day"))
6931                        classes.push('today');
6932
6933                    //highlight weekends
6934                    if (calendar[row][col].isoWeekday() > 5)
6935                        classes.push('weekend');
6936
6937                    //grey out the dates in other months displayed at beginning and end of this calendar
6938                    if (calendar[row][col].month() != calendar[1][1].month())
6939                        classes.push('off');
6940
6941                    //don't allow selection of dates before the minimum date
6942                    if (this.minDate && calendar[row][col].isBefore(this.minDate, 'day'))
6943                        classes.push('off', 'disabled');
6944
6945                    //don't allow selection of dates after the maximum date
6946                    if (maxDate && calendar[row][col].isAfter(maxDate, 'day'))
6947                        classes.push('off', 'disabled');
6948
6949                    //don't allow selection of date if a custom function decides it's invalid
6950                    if (this.isInvalidDate(calendar[row][col]))
6951                        classes.push('off', 'disabled');
6952
6953                    //highlight the currently selected start date
6954                    if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD'))
6955                        classes.push('active', 'start-date');
6956
6957                    //highlight the currently selected end date
6958                    if (this.endDate != null && calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD'))
6959                        classes.push('active', 'end-date');
6960
6961                    //highlight dates in-between the selected dates
6962                    if (this.endDate != null && calendar[row][col] > this.startDate && calendar[row][col] < this.endDate)
6963                        classes.push('in-range');
6964
6965                    //apply custom classes for this date
6966                    var isCustom = this.isCustomDate(calendar[row][col]);
6967                    if (isCustom !== false) {
6968                        if (typeof isCustom === 'string')
6969                            classes.push(isCustom);
6970                        else
6971                            Array.prototype.push.apply(classes, isCustom);
6972                    }
6973
6974                    var cname = '', disabled = false;
6975                    for (var i = 0; i < classes.length; i++) {
6976                        cname += classes[i] + ' ';
6977                        if (classes[i] == 'disabled')
6978                            disabled = true;
6979                    }
6980                    if (!disabled)
6981                        cname += 'available';
6982
6983                    html += '<td class="' + cname.replace(/^\s+|\s+$/g, '') + '" data-title="' + 'r' + row + 'c' + col + '">' + calendar[row][col].date() + '</td>';
6984
6985                }
6986                html += '</tr>';
6987            }
6988
6989            html += '</tbody>';
6990            html += '</table>';
6991
6992            this.container.find('.calendar.' + side + ' .calendar-table').html(html);
6993
6994        },
6995
6996        renderTimePicker: function(side) {
6997
6998            // Don't bother updating the time picker if it's currently disabled
6999            // because an end date hasn't been clicked yet
7000            if (side == 'right' && !this.endDate) return;
7001
7002            var html, selected, minDate, maxDate = this.maxDate;
7003
7004            if (this.dateLimit && (!this.maxDate || this.startDate.clone().add(this.dateLimit).isAfter(this.maxDate)))
7005                maxDate = this.startDate.clone().add(this.dateLimit);
7006
7007            if (side == 'left') {
7008                selected = this.startDate.clone();
7009                minDate = this.minDate;
7010            } else if (side == 'right') {
7011                selected = this.endDate.clone();
7012                minDate = this.startDate;
7013
7014                //Preserve the time already selected
7015                var timeSelector = this.container.find('.calendar.right .calendar-time div');
7016                if (timeSelector.html() != '') {
7017
7018                    selected.hour(timeSelector.find('.hourselect option:selected').val() || selected.hour());
7019                    selected.minute(timeSelector.find('.minuteselect option:selected').val() || selected.minute());
7020                    selected.second(timeSelector.find('.secondselect option:selected').val() || selected.second());
7021
7022                    if (!this.timePicker24Hour) {
7023                        var ampm = timeSelector.find('.ampmselect option:selected').val();
7024                        if (ampm === 'PM' && selected.hour() < 12)
7025                            selected.hour(selected.hour() + 12);
7026                        if (ampm === 'AM' && selected.hour() === 12)
7027                            selected.hour(0);
7028                    }
7029
7030                }
7031
7032                if (selected.isBefore(this.startDate))
7033                    selected = this.startDate.clone();
7034
7035                if (maxDate && selected.isAfter(maxDate))
7036                    selected = maxDate.clone();
7037
7038            }
7039
7040            //
7041            // hours
7042            //
7043
7044            html = '<select class="hourselect">';
7045
7046            var start = this.timePicker24Hour ? 0 : 1;
7047            var end = this.timePicker24Hour ? 23 : 12;
7048
7049            for (var i = start; i <= end; i++) {
7050                var i_in_24 = i;
7051                if (!this.timePicker24Hour)
7052                    i_in_24 = selected.hour() >= 12 ? (i == 12 ? 12 : i + 12) : (i == 12 ? 0 : i);
7053
7054                var time = selected.clone().hour(i_in_24);
7055                var disabled = false;
7056                if (minDate && time.minute(59).isBefore(minDate))
7057                    disabled = true;
7058                if (maxDate && time.minute(0).isAfter(maxDate))
7059                    disabled = true;
7060
7061                if (i_in_24 == selected.hour() && !disabled) {
7062                    html += '<option value="' + i + '" selected="selected">' + i + '</option>';
7063                } else if (disabled) {
7064                    html += '<option value="' + i + '" disabled="disabled" class="disabled">' + i + '</option>';
7065                } else {
7066                    html += '<option value="' + i + '">' + i + '</option>';
7067                }
7068            }
7069
7070            html += '</select> ';
7071
7072            //
7073            // minutes
7074            //
7075
7076            html += ': <select class="minuteselect">';
7077
7078            for (var i = 0; i < 60; i += this.timePickerIncrement) {
7079                var padded = i < 10 ? '0' + i : i;
7080                var time = selected.clone().minute(i);
7081
7082                var disabled = false;
7083                if (minDate && time.second(59).isBefore(minDate))
7084                    disabled = true;
7085                if (maxDate && time.second(0).isAfter(maxDate))
7086                    disabled = true;
7087
7088                if (selected.minute() == i && !disabled) {
7089                    html += '<option value="' + i + '" selected="selected">' + padded + '</option>';
7090                } else if (disabled) {
7091                    html += '<option value="' + i + '" disabled="disabled" class="disabled">' + padded + '</option>';
7092                } else {
7093                    html += '<option value="' + i + '">' + padded + '</option>';
7094                }
7095            }
7096
7097            html += '</select> ';
7098
7099            //
7100            // seconds
7101            //
7102
7103            if (this.timePickerSeconds) {
7104                html += ': <select class="secondselect">';
7105
7106                for (var i = 0; i < 60; i++) {
7107                    var padded = i < 10 ? '0' + i : i;
7108                    var time = selected.clone().second(i);
7109
7110                    var disabled = false;
7111                    if (minDate && time.isBefore(minDate))
7112                        disabled = true;
7113                    if (maxDate && time.isAfter(maxDate))
7114                        disabled = true;
7115
7116                    if (selected.second() == i && !disabled) {
7117                        html += '<option value="' + i + '" selected="selected">' + padded + '</option>';
7118                    } else if (disabled) {
7119                        html += '<option value="' + i + '" disabled="disabled" class="disabled">' + padded + '</option>';
7120                    } else {
7121                        html += '<option value="' + i + '">' + padded + '</option>';
7122                    }
7123                }
7124
7125                html += '</select> ';
7126            }
7127
7128            //
7129            // AM/PM
7130            //
7131
7132            if (!this.timePicker24Hour) {
7133                html += '<select class="ampmselect">';
7134
7135                var am_html = '';
7136                var pm_html = '';
7137
7138                if (minDate && selected.clone().hour(12).minute(0).second(0).isBefore(minDate))
7139                    am_html = ' disabled="disabled" class="disabled"';
7140
7141                if (maxDate && selected.clone().hour(0).minute(0).second(0).isAfter(maxDate))
7142                    pm_html = ' disabled="disabled" class="disabled"';
7143
7144                if (selected.hour() >= 12) {
7145                    html += '<option value="AM"' + am_html + '>AM</option><option value="PM" selected="selected"' + pm_html + '>PM</option>';
7146                } else {
7147                    html += '<option value="AM" selected="selected"' + am_html + '>AM</option><option value="PM"' + pm_html + '>PM</option>';
7148                }
7149
7150                html += '</select>';
7151            }
7152
7153            this.container.find('.calendar.' + side + ' .calendar-time div').html(html);
7154
7155        },
7156
7157        updateFormInputs: function() {
7158
7159            //ignore mouse movements while an above-calendar text input has focus
7160            if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus"))
7161                return;
7162
7163            this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.locale.format));
7164            if (this.endDate)
7165                this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.locale.format));
7166
7167            if (this.singleDatePicker || (this.endDate && (this.startDate.isBefore(this.endDate) || this.startDate.isSame(this.endDate)))) {
7168                this.container.find('button.applyBtn').removeAttr('disabled');
7169            } else {
7170                this.container.find('button.applyBtn').attr('disabled', 'disabled');
7171            }
7172
7173        },
7174
7175        move: function() {
7176            var parentOffset = { top: 0, left: 0 },
7177                containerTop;
7178            var parentRightEdge = $(window).width();
7179            if (!this.parentEl.is('body')) {
7180                parentOffset = {
7181                    top: this.parentEl.offset().top - this.parentEl.scrollTop(),
7182                    left: this.parentEl.offset().left - this.parentEl.scrollLeft()
7183                };
7184                parentRightEdge = this.parentEl[0].clientWidth + this.parentEl.offset().left;
7185            }
7186
7187            if (this.drops == 'up')
7188                containerTop = this.element.offset().top - this.container.outerHeight() - parentOffset.top;
7189            else
7190                containerTop = this.element.offset().top + this.element.outerHeight() - parentOffset.top;
7191            this.container[this.drops == 'up' ? 'addClass' : 'removeClass']('dropup');
7192
7193            if (this.opens == 'left') {
7194                this.container.css({
7195                    top: containerTop,
7196                    right: parentRightEdge - this.element.offset().left - this.element.outerWidth(),
7197                    left: 'auto'
7198                });
7199                if (this.container.offset().left < 0) {
7200                    this.container.css({
7201                        right: 'auto',
7202                        left: 9
7203                    });
7204                }
7205            } else if (this.opens == 'center') {
7206                this.container.css({
7207                    top: containerTop,
7208                    left: this.element.offset().left - parentOffset.left + this.element.outerWidth() / 2
7209                            - this.container.outerWidth() / 2,
7210                    right: 'auto'
7211                });
7212                if (this.container.offset().left < 0) {
7213                    this.container.css({
7214                        right: 'auto',
7215                        left: 9
7216                    });
7217                }
7218            } else {
7219                this.container.css({
7220                    top: containerTop,
7221                    left: this.element.offset().left - parentOffset.left,
7222                    right: 'auto'
7223                });
7224                if (this.container.offset().left + this.container.outerWidth() > $(window).width()) {
7225                    this.container.css({
7226                        left: 'auto',
7227                        right: 0
7228                    });
7229                }
7230            }
7231        },
7232
7233        show: function(e) {
7234            if (this.isShowing) return;
7235
7236            // Create a click proxy that is private to this instance of datepicker, for unbinding
7237            this._outsideClickProxy = $.proxy(function(e) { this.outsideClick(e); }, this);
7238
7239            // Bind global datepicker mousedown for hiding and
7240            $(document)
7241              .on('mousedown.daterangepicker', this._outsideClickProxy)
7242              // also support mobile devices
7243              .on('touchend.daterangepicker', this._outsideClickProxy)
7244              // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them
7245              .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy)
7246              // and also close when focus changes to outside the picker (eg. tabbing between controls)
7247              .on('focusin.daterangepicker', this._outsideClickProxy);
7248
7249            // Reposition the picker if the window is resized while it's open
7250            $(window).on('resize.daterangepicker', $.proxy(function(e) { this.move(e); }, this));
7251
7252            this.oldStartDate = this.startDate.clone();
7253            this.oldEndDate = this.endDate.clone();
7254            this.previousRightTime = this.endDate.clone();
7255
7256            this.updateView();
7257            this.container.show();
7258            this.move();
7259            this.element.trigger('show.daterangepicker', this);
7260            this.isShowing = true;
7261        },
7262
7263        hide: function(e) {
7264            if (!this.isShowing) return;
7265
7266            //incomplete date selection, revert to last values
7267            if (!this.endDate) {
7268                this.startDate = this.oldStartDate.clone();
7269                this.endDate = this.oldEndDate.clone();
7270            }
7271
7272            //if a new date range was selected, invoke the user callback function
7273            if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))
7274                this.callback(this.startDate, this.endDate, this.chosenLabel);
7275
7276            //if picker is attached to a text input, update it
7277            this.updateElement();
7278
7279            $(document).off('.daterangepicker');
7280            $(window).off('.daterangepicker');
7281            this.container.hide();
7282            this.element.trigger('hide.daterangepicker', this);
7283            this.isShowing = false;
7284        },
7285
7286        toggle: function(e) {
7287            if (this.isShowing) {
7288                this.hide();
7289            } else {
7290                this.show();
7291            }
7292        },
7293
7294        outsideClick: function(e) {
7295            var target = $(e.target);
7296            // if the page is clicked anywhere except within the daterangerpicker/button
7297            // itself then call this.hide()
7298            if (
7299                // ie modal dialog fix
7300                e.type == "focusin" ||
7301                target.closest(this.element).length ||
7302                target.closest(this.container).length ||
7303                target.closest('.calendar-table').length
7304                ) return;
7305            this.hide();
7306            this.element.trigger('outsideClick.daterangepicker', this);
7307        },
7308
7309        showCalendars: function() {
7310            this.container.addClass('show-calendar');
7311            this.move();
7312            this.element.trigger('showCalendar.daterangepicker', this);
7313        },
7314
7315        hideCalendars: function() {
7316            this.container.removeClass('show-calendar');
7317            this.element.trigger('hideCalendar.daterangepicker', this);
7318        },
7319
7320        hoverRange: function(e) {
7321
7322            //ignore mouse movements while an above-calendar text input has focus
7323            if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus"))
7324                return;
7325
7326            var label = e.target.getAttribute('data-range-key');
7327
7328            if (label == this.locale.customRangeLabel) {
7329                this.updateView();
7330            } else {
7331                var dates = this.ranges[label];
7332                this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.locale.format));
7333                this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.locale.format));
7334            }
7335
7336        },
7337
7338        clickRange: function(e) {
7339            var label = e.target.getAttribute('data-range-key');
7340            this.chosenLabel = label;
7341            if (label == this.locale.customRangeLabel) {
7342                this.showCalendars();
7343            } else {
7344                var dates = this.ranges[label];
7345                this.startDate = dates[0];
7346                this.endDate = dates[1];
7347
7348                if (!this.timePicker) {
7349                    this.startDate.startOf('day');
7350                    this.endDate.endOf('day');
7351                }
7352
7353                if (!this.alwaysShowCalendars)
7354                    this.hideCalendars();
7355                this.clickApply();
7356            }
7357        },
7358
7359        clickPrev: function(e) {
7360            var cal = $(e.target).parents('.calendar');
7361            if (cal.hasClass('left')) {
7362                this.leftCalendar.month.subtract(1, 'month');
7363                if (this.linkedCalendars)
7364                    this.rightCalendar.month.subtract(1, 'month');
7365            } else {
7366                this.rightCalendar.month.subtract(1, 'month');
7367            }
7368            this.updateCalendars();
7369        },
7370
7371        clickNext: function(e) {
7372            var cal = $(e.target).parents('.calendar');
7373            if (cal.hasClass('left')) {
7374                this.leftCalendar.month.add(1, 'month');
7375            } else {
7376                this.rightCalendar.month.add(1, 'month');
7377                if (this.linkedCalendars)
7378                    this.leftCalendar.month.add(1, 'month');
7379            }
7380            this.updateCalendars();
7381        },
7382
7383        hoverDate: function(e) {
7384
7385            //ignore mouse movements while an above-calendar text input has focus
7386            //if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus"))
7387            //    return;
7388
7389            //ignore dates that can't be selected
7390            if (!$(e.target).hasClass('available')) return;
7391
7392            //have the text inputs above calendars reflect the date being hovered over
7393            var title = $(e.target).attr('data-title');
7394            var row = title.substr(1, 1);
7395            var col = title.substr(3, 1);
7396            var cal = $(e.target).parents('.calendar');
7397            var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col];
7398
7399            if (this.endDate && !this.container.find('input[name=daterangepicker_start]').is(":focus")) {
7400                this.container.find('input[name=daterangepicker_start]').val(date.format(this.locale.format));
7401            } else if (!this.endDate && !this.container.find('input[name=daterangepicker_end]').is(":focus")) {
7402                this.container.find('input[name=daterangepicker_end]').val(date.format(this.locale.format));
7403            }
7404
7405            //highlight the dates between the start date and the date being hovered as a potential end date
7406            var leftCalendar = this.leftCalendar;
7407            var rightCalendar = this.rightCalendar;
7408            var startDate = this.startDate;
7409            if (!this.endDate) {
7410                this.container.find('.calendar tbody td').each(function(index, el) {
7411
7412                    //skip week numbers, only look at dates
7413                    if ($(el).hasClass('week')) return;
7414
7415                    var title = $(el).attr('data-title');
7416                    var row = title.substr(1, 1);
7417                    var col = title.substr(3, 1);
7418                    var cal = $(el).parents('.calendar');
7419                    var dt = cal.hasClass('left') ? leftCalendar.calendar[row][col] : rightCalendar.calendar[row][col];
7420
7421                    if ((dt.isAfter(startDate) && dt.isBefore(date)) || dt.isSame(date, 'day')) {
7422                        $(el).addClass('in-range');
7423                    } else {
7424                        $(el).removeClass('in-range');
7425                    }
7426
7427                });
7428            }
7429
7430        },
7431
7432        clickDate: function(e) {
7433
7434            if (!$(e.target).hasClass('available')) return;
7435
7436            var title = $(e.target).attr('data-title');
7437            var row = title.substr(1, 1);
7438            var col = title.substr(3, 1);
7439            var cal = $(e.target).parents('.calendar');
7440            var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col];
7441
7442            //
7443            // this function needs to do a few things:
7444            // * alternate between selecting a start and end date for the range,
7445            // * if the time picker is enabled, apply the hour/minute/second from the select boxes to the clicked date
7446            // * if autoapply is enabled, and an end date was chosen, apply the selection
7447            // * if single date picker mode, and time picker isn't enabled, apply the selection immediately
7448            // * if one of the inputs above the calendars was focused, cancel that manual input
7449            //
7450
7451            if (this.endDate || date.isBefore(this.startDate, 'day')) { //picking start
7452                if (this.timePicker) {
7453                    var hour = parseInt(this.container.find('.left .hourselect').val(), 10);
7454                    if (!this.timePicker24Hour) {
7455                        var ampm = this.container.find('.left .ampmselect').val();
7456                        if (ampm === 'PM' && hour < 12)
7457                            hour += 12;
7458                        if (ampm === 'AM' && hour === 12)
7459                            hour = 0;
7460                    }
7461                    var minute = parseInt(this.container.find('.left .minuteselect').val(), 10);
7462                    var second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0;
7463                    date = date.clone().hour(hour).minute(minute).second(second);
7464                }
7465                this.endDate = null;
7466                this.setStartDate(date.clone());
7467            } else if (!this.endDate && date.isBefore(this.startDate)) {
7468                //special case: clicking the same date for start/end,
7469                //but the time of the end date is before the start date
7470                this.setEndDate(this.startDate.clone());
7471            } else { // picking end
7472                if (this.timePicker) {
7473                    var hour = parseInt(this.container.find('.right .hourselect').val(), 10);
7474                    if (!this.timePicker24Hour) {
7475                        var ampm = this.container.find('.right .ampmselect').val();
7476                        if (ampm === 'PM' && hour < 12)
7477                            hour += 12;
7478                        if (ampm === 'AM' && hour === 12)
7479                            hour = 0;
7480                    }
7481                    var minute = parseInt(this.container.find('.right .minuteselect').val(), 10);
7482                    var second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0;
7483                    date = date.clone().hour(hour).minute(minute).second(second);
7484                }
7485                this.setEndDate(date.clone());
7486                if (this.autoApply) {
7487                  this.calculateChosenLabel();
7488                  this.clickApply();
7489                }
7490            }
7491
7492            if (this.singleDatePicker) {
7493                this.setEndDate(this.startDate);
7494                if (!this.timePicker)
7495                    this.clickApply();
7496            }
7497
7498            this.updateView();
7499
7500            //This is to cancel the blur event handler if the mouse was in one of the inputs
7501            e.stopPropagation();
7502
7503        },
7504
7505        calculateChosenLabel: function () {
7506            var customRange = true;
7507            var i = 0;
7508            for (var range in this.ranges) {
7509              if (this.timePicker) {
7510                    var format = this.timePickerSeconds ? "YYYY-MM-DD hh:mm:ss" : "YYYY-MM-DD hh:mm";
7511                    //ignore times when comparing dates if time picker seconds is not enabled
7512                    if (this.startDate.format(format) == this.ranges[range][0].format(format) && this.endDate.format(format) == this.ranges[range][1].format(format)) {
7513                        customRange = false;
7514                        this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').html();
7515                        break;
7516                    }
7517                } else {
7518                    //ignore times when comparing dates if time picker is not enabled
7519                    if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) {
7520                        customRange = false;
7521                        this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').html();
7522                        break;
7523                    }
7524                }
7525                i++;
7526            }
7527            if (customRange) {
7528                if (this.showCustomRangeLabel) {
7529                    this.chosenLabel = this.container.find('.ranges li:last').addClass('active').html();
7530                } else {
7531                    this.chosenLabel = null;
7532                }
7533                this.showCalendars();
7534            }
7535        },
7536
7537        clickApply: function(e) {
7538            this.hide();
7539            this.element.trigger('apply.daterangepicker', this);
7540        },
7541
7542        clickCancel: function(e) {
7543            this.startDate = this.oldStartDate;
7544            this.endDate = this.oldEndDate;
7545            this.hide();
7546            this.element.trigger('cancel.daterangepicker', this);
7547        },
7548
7549        monthOrYearChanged: function(e) {
7550            var isLeft = $(e.target).closest('.calendar').hasClass('left'),
7551                leftOrRight = isLeft ? 'left' : 'right',
7552                cal = this.container.find('.calendar.'+leftOrRight);
7553
7554            // Month must be Number for new moment versions
7555            var month = parseInt(cal.find('.monthselect').val(), 10);
7556            var year = cal.find('.yearselect').val();
7557
7558            if (!isLeft) {
7559                if (year < this.startDate.year() || (year == this.startDate.year() && month < this.startDate.month())) {
7560                    month = this.startDate.month();
7561                    year = this.startDate.year();
7562                }
7563            }
7564
7565            if (this.minDate) {
7566                if (year < this.minDate.year() || (year == this.minDate.year() && month < this.minDate.month())) {
7567                    month = this.minDate.month();
7568                    year = this.minDate.year();
7569                }
7570            }
7571
7572            if (this.maxDate) {
7573                if (year > this.maxDate.year() || (year == this.maxDate.year() && month > this.maxDate.month())) {
7574                    month = this.maxDate.month();
7575                    year = this.maxDate.year();
7576                }
7577            }
7578
7579            if (isLeft) {
7580                this.leftCalendar.month.month(month).year(year);
7581                if (this.linkedCalendars)
7582                    this.rightCalendar.month = this.leftCalendar.month.clone().add(1, 'month');
7583            } else {
7584                this.rightCalendar.month.month(month).year(year);
7585                if (this.linkedCalendars)
7586                    this.leftCalendar.month = this.rightCalendar.month.clone().subtract(1, 'month');
7587            }
7588            this.updateCalendars();
7589        },
7590
7591        timeChanged: function(e) {
7592
7593            var cal = $(e.target).closest('.calendar'),
7594                isLeft = cal.hasClass('left');
7595
7596            var hour = parseInt(cal.find('.hourselect').val(), 10);
7597            var minute = parseInt(cal.find('.minuteselect').val(), 10);
7598            var second = this.timePickerSeconds ? parseInt(cal.find('.secondselect').val(), 10) : 0;
7599
7600            if (!this.timePicker24Hour) {
7601                var ampm = cal.find('.ampmselect').val();
7602                if (ampm === 'PM' && hour < 12)
7603                    hour += 12;
7604                if (ampm === 'AM' && hour === 12)
7605                    hour = 0;
7606            }
7607
7608            if (isLeft) {
7609                var start = this.startDate.clone();
7610                start.hour(hour);
7611                start.minute(minute);
7612                start.second(second);
7613                this.setStartDate(start);
7614                if (this.singleDatePicker) {
7615                    this.endDate = this.startDate.clone();
7616                } else if (this.endDate && this.endDate.format('YYYY-MM-DD') == start.format('YYYY-MM-DD') && this.endDate.isBefore(start)) {
7617                    this.setEndDate(start.clone());
7618                }
7619            } else if (this.endDate) {
7620                var end = this.endDate.clone();
7621                end.hour(hour);
7622                end.minute(minute);
7623                end.second(second);
7624                this.setEndDate(end);
7625            }
7626
7627            //update the calendars so all clickable dates reflect the new time component
7628            this.updateCalendars();
7629
7630            //update the form inputs above the calendars with the new time
7631            this.updateFormInputs();
7632
7633            //re-render the time pickers because changing one selection can affect what's enabled in another
7634            this.renderTimePicker('left');
7635            this.renderTimePicker('right');
7636
7637        },
7638
7639        formInputsChanged: function(e) {
7640            var isRight = $(e.target).closest('.calendar').hasClass('right');
7641            var start = moment(this.container.find('input[name="daterangepicker_start"]').val(), this.locale.format);
7642            var end = moment(this.container.find('input[name="daterangepicker_end"]').val(), this.locale.format);
7643
7644            if (start.isValid() && end.isValid()) {
7645
7646                if (isRight && end.isBefore(start))
7647                    start = end.clone();
7648
7649                this.setStartDate(start);
7650                this.setEndDate(end);
7651
7652                if (isRight) {
7653                    this.container.find('input[name="daterangepicker_start"]').val(this.startDate.format(this.locale.format));
7654                } else {
7655                    this.container.find('input[name="daterangepicker_end"]').val(this.endDate.format(this.locale.format));
7656                }
7657
7658            }
7659
7660            this.updateView();
7661        },
7662
7663        formInputsFocused: function(e) {
7664
7665            // Highlight the focused input
7666            this.container.find('input[name="daterangepicker_start"], input[name="daterangepicker_end"]').removeClass('active');
7667            $(e.target).addClass('active');
7668
7669            // Set the state such that if the user goes back to using a mouse, 
7670            // the calendars are aware we're selecting the end of the range, not
7671            // the start. This allows someone to edit the end of a date range without
7672            // re-selecting the beginning, by clicking on the end date input then
7673            // using the calendar.
7674            var isRight = $(e.target).closest('.calendar').hasClass('right');
7675            if (isRight) {
7676                this.endDate = null;
7677                this.setStartDate(this.startDate.clone());
7678                this.updateView();
7679            }
7680
7681        },
7682
7683        formInputsBlurred: function(e) {
7684
7685            // this function has one purpose right now: if you tab from the first
7686            // text input to the second in the UI, the endDate is nulled so that
7687            // you can click another, but if you tab out without clicking anything
7688            // or changing the input value, the old endDate should be retained
7689
7690            if (!this.endDate) {
7691                var val = this.container.find('input[name="daterangepicker_end"]').val();
7692                var end = moment(val, this.locale.format);
7693                if (end.isValid()) {
7694                    this.setEndDate(end);
7695                    this.updateView();
7696                }
7697            }
7698
7699        },
7700
7701        formInputsKeydown: function(e) {
7702            // This function ensures that if the 'enter' key was pressed in the input, then the calendars
7703            // are updated with the startDate and endDate.
7704            // This behaviour is automatic in Chrome/Firefox/Edge but not in IE 11 hence why this exists.
7705            // Other browsers and versions of IE are untested and the behaviour is unknown.
7706            if (e.keyCode === 13) {
7707                // Prevent the calendar from being updated twice on Chrome/Firefox/Edge
7708                e.preventDefault(); 
7709                this.formInputsChanged(e);
7710            }
7711        },
7712
7713
7714        elementChanged: function() {
7715            if (!this.element.is('input')) return;
7716            if (!this.element.val().length) return;
7717
7718            var dateString = this.element.val().split(this.locale.separator),
7719                start = null,
7720                end = null;
7721
7722            if (dateString.length === 2) {
7723                start = moment(dateString[0], this.locale.format);
7724                end = moment(dateString[1], this.locale.format);
7725            }
7726
7727            if (this.singleDatePicker || start === null || end === null) {
7728                start = moment(this.element.val(), this.locale.format);
7729                end = start;
7730            }
7731
7732            if (!start.isValid() || !end.isValid()) return;
7733
7734            this.setStartDate(start);
7735            this.setEndDate(end);
7736            this.updateView();
7737        },
7738
7739        keydown: function(e) {
7740            //hide on tab or enter
7741            if ((e.keyCode === 9) || (e.keyCode === 13)) {
7742                this.hide();
7743            }
7744
7745            //hide on esc and prevent propagation
7746            if (e.keyCode === 27) {
7747                e.preventDefault();
7748                e.stopPropagation();
7749
7750                this.hide();
7751            }
7752        },
7753
7754        updateElement: function() {
7755            if (this.element.is('input') && !this.singleDatePicker && this.autoUpdateInput) {
7756                this.element.val(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format));
7757                this.element.trigger('change');
7758            } else if (this.element.is('input') && this.autoUpdateInput) {
7759                this.element.val(this.startDate.format(this.locale.format));
7760                this.element.trigger('change');
7761            }
7762        },
7763
7764        remove: function() {
7765            this.container.remove();
7766            this.element.off('.daterangepicker');
7767            this.element.removeData();
7768        }
7769
7770    };
7771
7772    $.fn.daterangepicker = function(options, callback) {
7773        var implementOptions = $.extend(true, {}, $.fn.daterangepicker.defaultOptions, options);
7774        this.each(function() {
7775            var el = $(this);
7776            if (el.data('daterangepicker'))
7777                el.data('daterangepicker').remove();
7778            el.data('daterangepicker', new DateRangePicker(el, implementOptions, callback));
7779        });
7780        return this;
7781    };
7782
7783    return DateRangePicker;
7784
7785}));
7786
7787
7788/*
7789 *  Bootstrap TouchSpin - v3.1.1
7790 *  A mobile and touch friendly input spinner component for Bootstrap 3.
7791 *  http://www.virtuosoft.eu/code/bootstrap-touchspin/
7792 *
7793 *  Made by István Ujj-Mészáros
7794 *  Under Apache License v2.0 License
7795 */
7796(function($) {
7797  'use strict';
7798
7799  var _currentSpinnerId = 0;
7800
7801  function _scopedEventName(name, id) {
7802    return name + '.touchspin_' + id;
7803  }
7804
7805  function _scopeEventNames(names, id) {
7806    return $.map(names, function(name) {
7807      return _scopedEventName(name, id);
7808    });
7809  }
7810
7811  $.fn.TouchSpin = function(options) {
7812
7813    if (options === 'destroy') {
7814      this.each(function() {
7815        var originalinput = $(this),
7816            originalinput_data = originalinput.data();
7817        $(document).off(_scopeEventNames([
7818          'mouseup',
7819          'touchend',
7820          'touchcancel',
7821          'mousemove',
7822          'touchmove',
7823          'scroll',
7824          'scrollstart'], originalinput_data.spinnerid).join(' '));
7825      });
7826      return;
7827    }
7828
7829    var defaults = {
7830      min: 0,
7831      max: 100,
7832      initval: '',
7833      replacementval: '',
7834      step: 1,
7835      decimals: 0,
7836      stepinterval: 100,
7837      forcestepdivisibility: 'round', // none | floor | round | ceil
7838      stepintervaldelay: 500,
7839      verticalbuttons: false,
7840      verticalupclass: 'glyphicon glyphicon-chevron-up',
7841      verticaldownclass: 'glyphicon glyphicon-chevron-down',
7842      prefix: '',
7843      postfix: '',
7844      prefix_extraclass: '',
7845      postfix_extraclass: '',
7846      booster: true,
7847      boostat: 10,
7848      maxboostedstep: false,
7849      mousewheel: true,
7850      buttondown_class: 'btn btn-default',
7851      buttonup_class: 'btn btn-default',
7852	  buttondown_txt: '-',
7853	  buttonup_txt: '+'
7854    };
7855
7856    var attributeMap = {
7857      min: 'min',
7858      max: 'max',
7859      initval: 'init-val',
7860      replacementval: 'replacement-val',
7861      step: 'step',
7862      decimals: 'decimals',
7863      stepinterval: 'step-interval',
7864      verticalbuttons: 'vertical-buttons',
7865      verticalupclass: 'vertical-up-class',
7866      verticaldownclass: 'vertical-down-class',
7867      forcestepdivisibility: 'force-step-divisibility',
7868      stepintervaldelay: 'step-interval-delay',
7869      prefix: 'prefix',
7870      postfix: 'postfix',
7871      prefix_extraclass: 'prefix-extra-class',
7872      postfix_extraclass: 'postfix-extra-class',
7873      booster: 'booster',
7874      boostat: 'boostat',
7875      maxboostedstep: 'max-boosted-step',
7876      mousewheel: 'mouse-wheel',
7877      buttondown_class: 'button-down-class',
7878      buttonup_class: 'button-up-class',
7879	  buttondown_txt: 'button-down-txt',
7880	  buttonup_txt: 'button-up-txt'
7881    };
7882
7883    return this.each(function() {
7884
7885      var settings,
7886          originalinput = $(this),
7887          originalinput_data = originalinput.data(),
7888          container,
7889          elements,
7890          value,
7891          downSpinTimer,
7892          upSpinTimer,
7893          downDelayTimeout,
7894          upDelayTimeout,
7895          spincount = 0,
7896          spinning = false;
7897
7898      init();
7899
7900
7901      function init() {
7902        if (originalinput.data('alreadyinitialized')) {
7903          return;
7904        }
7905
7906        originalinput.data('alreadyinitialized', true);
7907        _currentSpinnerId += 1;
7908        originalinput.data('spinnerid', _currentSpinnerId);
7909
7910
7911        if (!originalinput.is('input')) {
7912          console.log('Must be an input.');
7913          return;
7914        }
7915
7916        _initSettings();
7917        _setInitval();
7918        _checkValue();
7919        _buildHtml();
7920        _initElements();
7921        _hideEmptyPrefixPostfix();
7922        _bindEvents();
7923        _bindEventsInterface();
7924        elements.input.css('display', 'block');
7925      }
7926
7927      function _setInitval() {
7928        if (settings.initval !== '' && originalinput.val() === '') {
7929          originalinput.val(settings.initval);
7930        }
7931      }
7932
7933      function changeSettings(newsettings) {
7934        _updateSettings(newsettings);
7935        _checkValue();
7936
7937        var value = elements.input.val();
7938
7939        if (value !== '') {
7940          value = Number(elements.input.val());
7941          elements.input.val(value.toFixed(settings.decimals));
7942        }
7943      }
7944
7945      function _initSettings() {
7946        settings = $.extend({}, defaults, originalinput_data, _parseAttributes(), options);
7947      }
7948
7949      function _parseAttributes() {
7950        var data = {};
7951        $.each(attributeMap, function(key, value) {
7952          var attrName = 'bts-' + value + '';
7953          if (originalinput.is('[data-' + attrName + ']')) {
7954            data[key] = originalinput.data(attrName);
7955          }
7956        });
7957        return data;
7958      }
7959
7960      function _updateSettings(newsettings) {
7961        settings = $.extend({}, settings, newsettings);
7962      }
7963
7964      function _buildHtml() {
7965        var initval = originalinput.val(),
7966            parentelement = originalinput.parent();
7967
7968        if (initval !== '') {
7969          initval = Number(initval).toFixed(settings.decimals);
7970        }
7971
7972        originalinput.data('initvalue', initval).val(initval);
7973        originalinput.addClass('form-control');
7974
7975        if (parentelement.hasClass('input-group')) {
7976          _advanceInputGroup(parentelement);
7977        }
7978        else {
7979          _buildInputGroup();
7980        }
7981      }
7982
7983      function _advanceInputGroup(parentelement) {
7984        parentelement.addClass('bootstrap-touchspin');
7985
7986        var prev = originalinput.prev(),
7987            next = originalinput.next();
7988
7989        var downhtml,
7990            uphtml,
7991            prefixhtml = '<span class="input-group-addon bootstrap-touchspin-prefix">' + settings.prefix + '</span>',
7992            postfixhtml = '<span class="input-group-addon bootstrap-touchspin-postfix">' + settings.postfix + '</span>';
7993
7994        if (prev.hasClass('input-group-btn')) {
7995          downhtml = '<button class="' + settings.buttondown_class + ' bootstrap-touchspin-down" type="button">' + settings.buttondown_txt + '</button>';
7996          prev.append(downhtml);
7997        }
7998        else {
7999          downhtml = '<span class="input-group-btn"><button class="' + settings.buttondown_class + ' bootstrap-touchspin-down" type="button">' + settings.buttondown_txt + '</button></span>';
8000          $(downhtml).insertBefore(originalinput);
8001        }
8002
8003        if (next.hasClass('input-group-btn')) {
8004          uphtml = '<button class="' + settings.buttonup_class + ' bootstrap-touchspin-up" type="button">' + settings.buttonup_txt + '</button>';
8005          next.prepend(uphtml);
8006        }
8007        else {
8008          uphtml = '<span class="input-group-btn"><button class="' + settings.buttonup_class + ' bootstrap-touchspin-up" type="button">' + settings.buttonup_txt + '</button></span>';
8009          $(uphtml).insertAfter(originalinput);
8010        }
8011
8012        $(prefixhtml).insertBefore(originalinput);
8013        $(postfixhtml).insertAfter(originalinput);
8014
8015        container = parentelement;
8016      }
8017
8018      function _buildInputGroup() {
8019        var html;
8020
8021        if (settings.verticalbuttons) {
8022          html = '<div class="input-group bootstrap-touchspin"><span class="input-group-addon bootstrap-touchspin-prefix">' + settings.prefix + '</span><span class="input-group-addon bootstrap-touchspin-postfix">' + settings.postfix + '</span><span class="input-group-btn-vertical"><button class="' + settings.buttondown_class + ' bootstrap-touchspin-up" type="button"><i class="' + settings.verticalupclass + '"></i></button><button class="' + settings.buttonup_class + ' bootstrap-touchspin-down" type="button"><i class="' + settings.verticaldownclass + '"></i></button></span></div>';
8023        }
8024        else {
8025          html = '<div class="input-group bootstrap-touchspin"><span class="input-group-btn"><button class="' + settings.buttondown_class + ' bootstrap-touchspin-down" type="button">' + settings.buttondown_txt + '</button></span><span class="input-group-addon bootstrap-touchspin-prefix">' + settings.prefix + '</span><span class="input-group-addon bootstrap-touchspin-postfix">' + settings.postfix + '</span><span class="input-group-btn"><button class="' + settings.buttonup_class + ' bootstrap-touchspin-up" type="button">' + settings.buttonup_txt + '</button></span></div>';
8026        }
8027
8028        container = $(html).insertBefore(originalinput);
8029
8030        $('.bootstrap-touchspin-prefix', container).after(originalinput);
8031
8032        if (originalinput.hasClass('input-sm')) {
8033          container.addClass('input-group-sm');
8034        }
8035        else if (originalinput.hasClass('input-lg')) {
8036          container.addClass('input-group-lg');
8037        }
8038      }
8039
8040      function _initElements() {
8041        elements = {
8042          down: $('.bootstrap-touchspin-down', container),
8043          up: $('.bootstrap-touchspin-up', container),
8044          input: $('input', container),
8045          prefix: $('.bootstrap-touchspin-prefix', container).addClass(settings.prefix_extraclass),
8046          postfix: $('.bootstrap-touchspin-postfix', container).addClass(settings.postfix_extraclass)
8047        };
8048      }
8049
8050      function _hideEmptyPrefixPostfix() {
8051        if (settings.prefix === '') {
8052          elements.prefix.hide();
8053        }
8054
8055        if (settings.postfix === '') {
8056          elements.postfix.hide();
8057        }
8058      }
8059
8060      function _bindEvents() {
8061        originalinput.on('keydown', function(ev) {
8062          var code = ev.keyCode || ev.which;
8063
8064          if (code === 38) {
8065            if (spinning !== 'up') {
8066              upOnce();
8067              startUpSpin();
8068            }
8069            ev.preventDefault();
8070          }
8071          else if (code === 40) {
8072            if (spinning !== 'down') {
8073              downOnce();
8074              startDownSpin();
8075            }
8076            ev.preventDefault();
8077          }
8078        });
8079
8080        originalinput.on('keyup', function(ev) {
8081          var code = ev.keyCode || ev.which;
8082
8083          if (code === 38) {
8084            stopSpin();
8085          }
8086          else if (code === 40) {
8087            stopSpin();
8088          }
8089        });
8090
8091        originalinput.on('blur', function() {
8092          _checkValue();
8093        });
8094
8095        elements.down.on('keydown', function(ev) {
8096          var code = ev.keyCode || ev.which;
8097
8098          if (code === 32 || code === 13) {
8099            if (spinning !== 'down') {
8100              downOnce();
8101              startDownSpin();
8102            }
8103            ev.preventDefault();
8104          }
8105        });
8106
8107        elements.down.on('keyup', function(ev) {
8108          var code = ev.keyCode || ev.which;
8109
8110          if (code === 32 || code === 13) {
8111            stopSpin();
8112          }
8113        });
8114
8115        elements.up.on('keydown', function(ev) {
8116          var code = ev.keyCode || ev.which;
8117
8118          if (code === 32 || code === 13) {
8119            if (spinning !== 'up') {
8120              upOnce();
8121              startUpSpin();
8122            }
8123            ev.preventDefault();
8124          }
8125        });
8126
8127        elements.up.on('keyup', function(ev) {
8128          var code = ev.keyCode || ev.which;
8129
8130          if (code === 32 || code === 13) {
8131            stopSpin();
8132          }
8133        });
8134
8135        elements.down.on('mousedown.touchspin', function(ev) {
8136          elements.down.off('touchstart.touchspin');  // android 4 workaround
8137
8138          if (originalinput.is(':disabled')) {
8139            return;
8140          }
8141
8142          downOnce();
8143          startDownSpin();
8144
8145          ev.preventDefault();
8146          ev.stopPropagation();
8147        });
8148
8149        elements.down.on('touchstart.touchspin', function(ev) {
8150          elements.down.off('mousedown.touchspin');  // android 4 workaround
8151
8152          if (originalinput.is(':disabled')) {
8153            return;
8154          }
8155
8156          downOnce();
8157          startDownSpin();
8158
8159          ev.preventDefault();
8160          ev.stopPropagation();
8161        });
8162
8163        elements.up.on('mousedown.touchspin', function(ev) {
8164          elements.up.off('touchstart.touchspin');  // android 4 workaround
8165
8166          if (originalinput.is(':disabled')) {
8167            return;
8168          }
8169
8170          upOnce();
8171          startUpSpin();
8172
8173          ev.preventDefault();
8174          ev.stopPropagation();
8175        });
8176
8177        elements.up.on('touchstart.touchspin', function(ev) {
8178          elements.up.off('mousedown.touchspin');  // android 4 workaround
8179
8180          if (originalinput.is(':disabled')) {
8181            return;
8182          }
8183
8184          upOnce();
8185          startUpSpin();
8186
8187          ev.preventDefault();
8188          ev.stopPropagation();
8189        });
8190
8191        elements.up.on('mouseout touchleave touchend touchcancel', function(ev) {
8192          if (!spinning) {
8193            return;
8194          }
8195
8196          ev.stopPropagation();
8197          stopSpin();
8198        });
8199
8200        elements.down.on('mouseout touchleave touchend touchcancel', function(ev) {
8201          if (!spinning) {
8202            return;
8203          }
8204
8205          ev.stopPropagation();
8206          stopSpin();
8207        });
8208
8209        elements.down.on('mousemove touchmove', function(ev) {
8210          if (!spinning) {
8211            return;
8212          }
8213
8214          ev.stopPropagation();
8215          ev.preventDefault();
8216        });
8217
8218        elements.up.on('mousemove touchmove', function(ev) {
8219          if (!spinning) {
8220            return;
8221          }
8222
8223          ev.stopPropagation();
8224          ev.preventDefault();
8225        });
8226
8227        $(document).on(_scopeEventNames(['mouseup', 'touchend', 'touchcancel'], _currentSpinnerId).join(' '), function(ev) {
8228          if (!spinning) {
8229            return;
8230          }
8231
8232          ev.preventDefault();
8233          stopSpin();
8234        });
8235
8236        $(document).on(_scopeEventNames(['mousemove', 'touchmove', 'scroll', 'scrollstart'], _currentSpinnerId).join(' '), function(ev) {
8237          if (!spinning) {
8238            return;
8239          }
8240
8241          ev.preventDefault();
8242          stopSpin();
8243        });
8244
8245        originalinput.on('mousewheel DOMMouseScroll', function(ev) {
8246          if (!settings.mousewheel || !originalinput.is(':focus')) {
8247            return;
8248          }
8249
8250          var delta = ev.originalEvent.wheelDelta || -ev.originalEvent.deltaY || -ev.originalEvent.detail;
8251
8252          ev.stopPropagation();
8253          ev.preventDefault();
8254
8255          if (delta < 0) {
8256            downOnce();
8257          }
8258          else {
8259            upOnce();
8260          }
8261        });
8262      }
8263
8264      function _bindEventsInterface() {
8265        originalinput.on('touchspin.uponce', function() {
8266          stopSpin();
8267          upOnce();
8268        });
8269
8270        originalinput.on('touchspin.downonce', function() {
8271          stopSpin();
8272          downOnce();
8273        });
8274
8275        originalinput.on('touchspin.startupspin', function() {
8276          startUpSpin();
8277        });
8278
8279        originalinput.on('touchspin.startdownspin', function() {
8280          startDownSpin();
8281        });
8282
8283        originalinput.on('touchspin.stopspin', function() {
8284          stopSpin();
8285        });
8286
8287        originalinput.on('touchspin.updatesettings', function(e, newsettings) {
8288          changeSettings(newsettings);
8289        });
8290      }
8291
8292      function _forcestepdivisibility(value) {
8293        switch (settings.forcestepdivisibility) {
8294          case 'round':
8295            return (Math.round(value / settings.step) * settings.step).toFixed(settings.decimals);
8296          case 'floor':
8297            return (Math.floor(value / settings.step) * settings.step).toFixed(settings.decimals);
8298          case 'ceil':
8299            return (Math.ceil(value / settings.step) * settings.step).toFixed(settings.decimals);
8300          default:
8301            return value;
8302        }
8303      }
8304
8305      function _checkValue() {
8306        var val, parsedval, returnval;
8307
8308        val = originalinput.val();
8309
8310        if (val === '') {
8311          if (settings.replacementval !== '') {
8312            originalinput.val(settings.replacementval);
8313            originalinput.trigger('change');
8314          }
8315          return;
8316        }
8317
8318        if (settings.decimals > 0 && val === '.') {
8319          return;
8320        }
8321
8322        parsedval = parseFloat(val);
8323
8324        if (isNaN(parsedval)) {
8325          if (settings.replacementval !== '') {
8326            parsedval = settings.replacementval;
8327          }
8328          else {
8329            parsedval = 0;
8330          }
8331        }
8332
8333        returnval = parsedval;
8334
8335        if (parsedval.toString() !== val) {
8336          returnval = parsedval;
8337        }
8338
8339        if (parsedval < settings.min) {
8340          returnval = settings.min;
8341        }
8342
8343        if (parsedval > settings.max) {
8344          returnval = settings.max;
8345        }
8346
8347        returnval = _forcestepdivisibility(returnval);
8348
8349        if (Number(val).toString() !== returnval.toString()) {
8350          originalinput.val(returnval);
8351          originalinput.trigger('change');
8352        }
8353      }
8354
8355      function _getBoostedStep() {
8356        if (!settings.booster) {
8357          return settings.step;
8358        }
8359        else {
8360          var boosted = Math.pow(2, Math.floor(spincount / settings.boostat)) * settings.step;
8361
8362          if (settings.maxboostedstep) {
8363            if (boosted > settings.maxboostedstep) {
8364              boosted = settings.maxboostedstep;
8365              value = Math.round((value / boosted)) * boosted;
8366            }
8367          }
8368
8369          return Math.max(settings.step, boosted);
8370        }
8371      }
8372
8373      function upOnce() {
8374        _checkValue();
8375
8376        value = parseFloat(elements.input.val());
8377        if (isNaN(value)) {
8378          value = 0;
8379        }
8380
8381        var initvalue = value,
8382            boostedstep = _getBoostedStep();
8383
8384        value = value + boostedstep;
8385
8386        if (value > settings.max) {
8387          value = settings.max;
8388          originalinput.trigger('touchspin.on.max');
8389          stopSpin();
8390        }
8391
8392        elements.input.val(Number(value).toFixed(settings.decimals));
8393
8394        if (initvalue !== value) {
8395          originalinput.trigger('change');
8396        }
8397      }
8398
8399      function downOnce() {
8400        _checkValue();
8401
8402        value = parseFloat(elements.input.val());
8403        if (isNaN(value)) {
8404          value = 0;
8405        }
8406
8407        var initvalue = value,
8408            boostedstep = _getBoostedStep();
8409
8410        value = value - boostedstep;
8411
8412        if (value < settings.min) {
8413          value = settings.min;
8414          originalinput.trigger('touchspin.on.min');
8415          stopSpin();
8416        }
8417
8418        elements.input.val(value.toFixed(settings.decimals));
8419
8420        if (initvalue !== value) {
8421          originalinput.trigger('change');
8422        }
8423      }
8424
8425      function startDownSpin() {
8426        stopSpin();
8427
8428        spincount = 0;
8429        spinning = 'down';
8430
8431        originalinput.trigger('touchspin.on.startspin');
8432        originalinput.trigger('touchspin.on.startdownspin');
8433
8434        downDelayTimeout = setTimeout(function() {
8435          downSpinTimer = setInterval(function() {
8436            spincount++;
8437            downOnce();
8438          }, settings.stepinterval);
8439        }, settings.stepintervaldelay);
8440      }
8441
8442      function startUpSpin() {
8443        stopSpin();
8444
8445        spincount = 0;
8446        spinning = 'up';
8447
8448        originalinput.trigger('touchspin.on.startspin');
8449        originalinput.trigger('touchspin.on.startupspin');
8450
8451        upDelayTimeout = setTimeout(function() {
8452          upSpinTimer = setInterval(function() {
8453            spincount++;
8454            upOnce();
8455          }, settings.stepinterval);
8456        }, settings.stepintervaldelay);
8457      }
8458
8459      function stopSpin() {
8460        clearTimeout(downDelayTimeout);
8461        clearTimeout(upDelayTimeout);
8462        clearInterval(downSpinTimer);
8463        clearInterval(upSpinTimer);
8464
8465        switch (spinning) {
8466          case 'up':
8467            originalinput.trigger('touchspin.on.stopupspin');
8468            originalinput.trigger('touchspin.on.stopspin');
8469            break;
8470          case 'down':
8471            originalinput.trigger('touchspin.on.stopdownspin');
8472            originalinput.trigger('touchspin.on.stopspin');
8473            break;
8474        }
8475
8476        spincount = 0;
8477        spinning = false;
8478      }
8479
8480    });
8481
8482  };
8483
8484})(jQuery);
8485
8486(function ($) {
8487  'use strict';
8488  /**
8489   * We need an event when the elements are destroyed
8490   * because if an input is removed, we have to remove the
8491   * maxlength object associated (if any).
8492   * From:
8493   * http://stackoverflow.com/questions/2200494/jquery-trigger-event-when-an-element-is-removed-from-the-dom
8494   */
8495  if (!$.event.special.destroyed) {
8496    $.event.special.destroyed = {
8497      remove: function (o) {
8498        if (o.handler) {
8499          o.handler();
8500        }
8501      }
8502    };
8503  }
8504
8505
8506  $.fn.extend({
8507    maxlength: function (options, callback) {
8508      var documentBody = $('body'),
8509        defaults = {
8510          showOnReady: false, // true to always show when indicator is ready
8511          alwaysShow: false, // if true the indicator it's always shown.
8512          threshold: 10, // Represents how many chars left are needed to show up the counter
8513          warningClass: 'label label-success',
8514          limitReachedClass: 'label label-important label-danger',
8515          separator: ' / ',
8516          preText: '',
8517          postText: '',
8518          showMaxLength: true,
8519          placement: 'bottom',
8520          message: null, // an alternative way to provide the message text
8521          showCharsTyped: true, // show the number of characters typed and not the number of characters remaining
8522          validate: false, // if the browser doesn't support the maxlength attribute, attempt to type more than
8523          // the indicated chars, will be prevented.
8524          utf8: false, // counts using bytesize rather than length. eg: '£' is counted as 2 characters.
8525          appendToParent: false, // append the indicator to the input field's parent instead of body
8526          twoCharLinebreak: true,  // count linebreak as 2 characters to match IE/Chrome textarea validation. As well as DB storage.
8527          allowOverMax: false  // false = use maxlength attribute and browswer functionality.
8528          // true = removes maxlength attribute and replaces with 'data-bs-mxl'.
8529          // Form submit validation is handled on your own.  when maxlength has been exceeded 'overmax' class added to element
8530        };
8531
8532      if ($.isFunction(options) && !callback) {
8533        callback = options;
8534        options = {};
8535      }
8536      options = $.extend(defaults, options);
8537
8538      /**
8539      * Return the length of the specified input.
8540      *
8541      * @param input
8542      * @return {number}
8543      */
8544      function inputLength(input) {
8545        var text = input.val();
8546
8547        if (options.twoCharLinebreak) {
8548          // Count all line breaks as 2 characters
8549          text = text.replace(/\r(?!\n)|\n(?!\r)/g, '\r\n');
8550        } else {
8551          // Remove all double-character (\r\n) linebreaks, so they're counted only once.
8552          text = text.replace(new RegExp('\r?\n', 'g'), '\n');
8553        }
8554
8555        var currentLength = 0;
8556
8557        if (options.utf8) {
8558          currentLength = utf8Length(text);
8559        } else {
8560          currentLength = text.length;
8561        }
8562        return currentLength;
8563      }
8564
8565      /**
8566      * Truncate the text of the specified input.
8567      *
8568      * @param input
8569      * @param limit
8570      */
8571      function truncateChars(input, maxlength) {
8572        var text = input.val();
8573        var newlines = 0;
8574
8575        if (options.twoCharLinebreak) {
8576          text = text.replace(/\r(?!\n)|\n(?!\r)/g, '\r\n');
8577
8578          if (text.substr(text.length - 1) === '\n' && text.length % 2 === 1) {
8579            newlines = 1;
8580          }
8581        }
8582
8583        input.val(text.substr(0, maxlength - newlines));
8584      }
8585
8586      /**
8587      * Return the length of the specified input in UTF8 encoding.
8588      *
8589      * @param input
8590      * @return {number}
8591      */
8592      function utf8Length(string) {
8593        var utf8length = 0;
8594        for (var n = 0; n < string.length; n++) {
8595          var c = string.charCodeAt(n);
8596          if (c < 128) {
8597            utf8length++;
8598          }
8599          else if ((c > 127) && (c < 2048)) {
8600            utf8length = utf8length + 2;
8601          }
8602          else {
8603            utf8length = utf8length + 3;
8604          }
8605        }
8606        return utf8length;
8607      }
8608
8609      /**
8610       * Return true if the indicator should be showing up.
8611       *
8612       * @param input
8613       * @param thereshold
8614       * @param maxlength
8615       * @return {number}
8616       */
8617      function charsLeftThreshold(input, thereshold, maxlength) {
8618        var output = true;
8619        if (!options.alwaysShow && (maxlength - inputLength(input) > thereshold)) {
8620          output = false;
8621        }
8622        return output;
8623      }
8624
8625      /**
8626       * Returns how many chars are left to complete the fill up of the form.
8627       *
8628       * @param input
8629       * @param maxlength
8630       * @return {number}
8631       */
8632      function remainingChars(input, maxlength) {
8633        var length = maxlength - inputLength(input);
8634        return length;
8635      }
8636
8637      /**
8638       * When called displays the indicator.
8639       *
8640       * @param indicator
8641       */
8642      function showRemaining(currentInput, indicator) {
8643        indicator.css({
8644          display: 'block'
8645        });
8646        currentInput.trigger('maxlength.shown');
8647      }
8648
8649      /**
8650       * When called shows the indicator.
8651       *
8652       * @param indicator
8653       */
8654      function hideRemaining(currentInput, indicator) {
8655        indicator.css({
8656          display: 'none'
8657        });
8658        currentInput.trigger('maxlength.hidden');
8659      }
8660
8661      /**
8662      * This function updates the value in the indicator
8663      *
8664      * @param maxLengthThisInput
8665      * @param typedChars
8666      * @return String
8667      */
8668      function updateMaxLengthHTML(currentInputText, maxLengthThisInput, typedChars) {
8669        var output = '';
8670        if (options.message) {
8671          if (typeof options.message === 'function') {
8672            output = options.message(currentInputText, maxLengthThisInput);
8673          } else {
8674            output = options.message.replace('%charsTyped%', typedChars)
8675              .replace('%charsRemaining%', maxLengthThisInput - typedChars)
8676              .replace('%charsTotal%', maxLengthThisInput);
8677          }
8678        } else {
8679          if (options.preText) {
8680            output += options.preText;
8681          }
8682          if (!options.showCharsTyped) {
8683            output += maxLengthThisInput - typedChars;
8684          }
8685          else {
8686            output += typedChars;
8687          }
8688          if (options.showMaxLength) {
8689            output += options.separator + maxLengthThisInput;
8690          }
8691          if (options.postText) {
8692            output += options.postText;
8693          }
8694        }
8695        return output;
8696      }
8697
8698      /**
8699       * This function updates the value of the counter in the indicator.
8700       * Wants as parameters: the number of remaining chars, the element currently managed,
8701       * the maxLength for the current input and the indicator generated for it.
8702       *
8703       * @param remaining
8704       * @param currentInput
8705       * @param maxLengthCurrentInput
8706       * @param maxLengthIndicator
8707       */
8708      function manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator) {
8709        if (maxLengthIndicator) {
8710          maxLengthIndicator.html(updateMaxLengthHTML(currentInput.val(), maxLengthCurrentInput, (maxLengthCurrentInput - remaining)));
8711
8712          if (remaining > 0) {
8713            if (charsLeftThreshold(currentInput, options.threshold, maxLengthCurrentInput)) {
8714              showRemaining(currentInput, maxLengthIndicator.removeClass(options.limitReachedClass).addClass(options.warningClass));
8715            } else {
8716              hideRemaining(currentInput, maxLengthIndicator);
8717            }
8718          } else {
8719            showRemaining(currentInput, maxLengthIndicator.removeClass(options.warningClass).addClass(options.limitReachedClass));
8720          }
8721        }
8722
8723        if (options.allowOverMax) {
8724          // class to use for form validation on custom maxlength attribute
8725          if (remaining < 0) {
8726            currentInput.addClass('overmax');
8727          } else {
8728            currentInput.removeClass('overmax');
8729          }
8730        }
8731      }
8732
8733      /**
8734       * This function returns an object containing all the
8735       * informations about the position of the current input
8736       *
8737       * @param currentInput
8738       * @return object {bottom height left right top width}
8739       *
8740       */
8741      function getPosition(currentInput) {
8742        var el = currentInput[0];
8743        return $.extend({}, (typeof el.getBoundingClientRect === 'function') ? el.getBoundingClientRect() : {
8744          width: el.offsetWidth,
8745          height: el.offsetHeight
8746        }, currentInput.offset());
8747      }
8748
8749      /**
8750       * This function places the maxLengthIndicator at the
8751       * top / bottom / left / right of the currentInput
8752       *
8753       * @param currentInput
8754       * @param maxLengthIndicator
8755       * @return null
8756       *
8757       */
8758      function place(currentInput, maxLengthIndicator) {
8759        var pos = getPosition(currentInput);
8760
8761        // Supports custom placement handler
8762        if ($.type(options.placement) === 'function'){
8763          options.placement(currentInput, maxLengthIndicator, pos);
8764          return;
8765        }
8766
8767        // Supports custom placement via css positional properties
8768        if ($.isPlainObject(options.placement)){
8769          placeWithCSS(options.placement, maxLengthIndicator);
8770          return;
8771        }
8772
8773        var inputOuter = currentInput.outerWidth(),
8774          outerWidth = maxLengthIndicator.outerWidth(),
8775          actualWidth = maxLengthIndicator.width(),
8776          actualHeight = maxLengthIndicator.height();
8777
8778        // get the right position if the indicator is appended to the input's parent
8779        if (options.appendToParent) {
8780          pos.top -= currentInput.parent().offset().top;
8781          pos.left -= currentInput.parent().offset().left;
8782        }
8783
8784        switch (options.placement) {
8785          case 'bottom':
8786            maxLengthIndicator.css({ top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 });
8787            break;
8788          case 'top':
8789            maxLengthIndicator.css({ top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 });
8790            break;
8791          case 'left':
8792            maxLengthIndicator.css({ top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth });
8793            break;
8794          case 'right':
8795            maxLengthIndicator.css({ top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width });
8796            break;
8797          case 'bottom-right':
8798            maxLengthIndicator.css({ top: pos.top + pos.height, left: pos.left + pos.width });
8799            break;
8800          case 'top-right':
8801            maxLengthIndicator.css({ top: pos.top - actualHeight, left: pos.left + inputOuter });
8802            break;
8803          case 'top-left':
8804            maxLengthIndicator.css({ top: pos.top - actualHeight, left: pos.left - outerWidth });
8805            break;
8806          case 'bottom-left':
8807            maxLengthIndicator.css({ top: pos.top + currentInput.outerHeight(), left: pos.left - outerWidth });
8808            break;
8809          case 'centered-right':
8810            maxLengthIndicator.css({ top: pos.top + (actualHeight / 2), left: pos.left + inputOuter - outerWidth - 3 });
8811            break;
8812
8813            // Some more options for placements
8814          case 'bottom-right-inside':
8815            maxLengthIndicator.css({ top: pos.top + pos.height, left: pos.left + pos.width - outerWidth });
8816            break;
8817          case 'top-right-inside':
8818            maxLengthIndicator.css({ top: pos.top - actualHeight, left: pos.left + inputOuter - outerWidth });
8819            break;
8820          case 'top-left-inside':
8821            maxLengthIndicator.css({ top: pos.top - actualHeight, left: pos.left });
8822            break;
8823          case 'bottom-left-inside':
8824            maxLengthIndicator.css({ top: pos.top + currentInput.outerHeight(), left: pos.left });
8825            break;
8826        }
8827      }
8828
8829      /**
8830       * This function places the maxLengthIndicator based on placement config object.
8831       *
8832       * @param {object} placement
8833       * @param {$} maxLengthIndicator
8834       * @return null
8835       *
8836       */
8837      function placeWithCSS(placement, maxLengthIndicator) {
8838        if (!placement || !maxLengthIndicator){
8839          return;
8840        }
8841
8842        var POSITION_KEYS = [
8843          'top',
8844          'bottom',
8845          'left',
8846          'right',
8847          'position'
8848        ];
8849
8850        var cssPos = {};
8851
8852        // filter css properties to position
8853        $.each(POSITION_KEYS, function (i, key) {
8854          var val = options.placement[key];
8855          if (typeof val !== 'undefined'){
8856            cssPos[key] = val;
8857          }
8858        });
8859
8860        maxLengthIndicator.css(cssPos);
8861
8862        return;
8863      }
8864
8865      /**
8866       * This function retrieves the maximum length of currentInput
8867       *
8868       * @param currentInput
8869       * @return {number}
8870       *
8871       */
8872      function getMaxLength(currentInput) {
8873        var attr = 'maxlength';
8874        if (options.allowOverMax) {
8875          attr = 'data-bs-mxl';
8876        }
8877        return currentInput.attr(attr) || currentInput.attr('size');
8878      }
8879
8880      return this.each(function () {
8881
8882        var currentInput = $(this),
8883          maxLengthCurrentInput,
8884          maxLengthIndicator;
8885
8886        $(window).resize(function () {
8887          if (maxLengthIndicator) {
8888            place(currentInput, maxLengthIndicator);
8889          }
8890        });
8891
8892        if (options.allowOverMax) {
8893          $(this).attr('data-bs-mxl', $(this).attr('maxlength'));
8894          $(this).removeAttr('maxlength');
8895        }
8896
8897        function firstInit() {
8898          var maxlengthContent = updateMaxLengthHTML(currentInput.val(), maxLengthCurrentInput, '0');
8899          maxLengthCurrentInput = getMaxLength(currentInput);
8900
8901          if (!maxLengthIndicator) {
8902            maxLengthIndicator = $('<span class="bootstrap-maxlength"></span>').css({
8903              display: 'none',
8904              position: 'absolute',
8905              whiteSpace: 'nowrap',
8906              zIndex: 1099
8907            }).html(maxlengthContent);
8908          }
8909
8910          // We need to detect resizes if we are dealing with a textarea:
8911          if (currentInput.is('textarea')) {
8912            currentInput.data('maxlenghtsizex', currentInput.outerWidth());
8913            currentInput.data('maxlenghtsizey', currentInput.outerHeight());
8914
8915            currentInput.mouseup(function () {
8916              if (currentInput.outerWidth() !== currentInput.data('maxlenghtsizex') || currentInput.outerHeight() !== currentInput.data('maxlenghtsizey')) {
8917                place(currentInput, maxLengthIndicator);
8918              }
8919
8920              currentInput.data('maxlenghtsizex', currentInput.outerWidth());
8921              currentInput.data('maxlenghtsizey', currentInput.outerHeight());
8922            });
8923          }
8924
8925          if (options.appendToParent) {
8926            currentInput.parent().append(maxLengthIndicator);
8927            currentInput.parent().css('position', 'relative');
8928          } else {
8929            documentBody.append(maxLengthIndicator);
8930          }
8931
8932          var remaining = remainingChars(currentInput, getMaxLength(currentInput));
8933          manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator);
8934          place(currentInput, maxLengthIndicator);
8935        }
8936
8937        if (options.showOnReady) {
8938          currentInput.ready(function () {
8939            firstInit();
8940          });
8941        } else {
8942          currentInput.focus(function () {
8943            firstInit();
8944          });
8945        }
8946
8947        currentInput.on('maxlength.reposition', function () {
8948          place(currentInput, maxLengthIndicator);
8949        });
8950
8951
8952        currentInput.on('destroyed', function () {
8953          if (maxLengthIndicator) {
8954            maxLengthIndicator.remove();
8955          }
8956        });
8957
8958        currentInput.on('blur', function () {
8959          if (maxLengthIndicator && !options.showOnReady) {
8960            maxLengthIndicator.remove();
8961          }
8962        });
8963
8964        currentInput.on('input', function () {
8965          var maxlength = getMaxLength(currentInput),
8966            remaining = remainingChars(currentInput, maxlength),
8967            output = true;
8968
8969          if (options.validate && remaining < 0) {
8970            truncateChars(currentInput, maxlength);
8971            output = false;
8972          } else {
8973            manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator);
8974          }
8975
8976          //reposition the indicator if placement "bottom-right-inside" & "top-right-inside" is used
8977          if (options.placement === 'bottom-right-inside' || options.placement === 'top-right-inside') {
8978            place(currentInput, maxLengthIndicator);
8979          }
8980
8981          return output;
8982        });
8983      });
8984    }
8985  });
8986}(jQuery));
8987
8988/**
8989  * bootstrap-switch - Turn checkboxes and radio buttons into toggle switches.
8990  *
8991  * @version v3.3.4
8992  * @homepage https://bttstrp.github.io/bootstrap-switch
8993  * @author Mattia Larentis <[email protected]> (http://larentis.eu)
8994  * @license Apache-2.0
8995  */
8996
8997(function (global, factory) {
8998  if (typeof define === "function" && define.amd) {
8999    define(['jquery'], factory);
9000  } else if (typeof exports !== "undefined") {
9001    factory(require('jquery'));
9002  } else {
9003    var mod = {
9004      exports: {}
9005    };
9006    factory(global.jquery);
9007    global.bootstrapSwitch = mod.exports;
9008  }
9009})(this, function (_jquery) {
9010  'use strict';
9011
9012  var _jquery2 = _interopRequireDefault(_jquery);
9013
9014  function _interopRequireDefault(obj) {
9015    return obj && obj.__esModule ? obj : {
9016      default: obj
9017    };
9018  }
9019
9020  var _extends = Object.assign || function (target) {
9021    for (var i = 1; i < arguments.length; i++) {
9022      var source = arguments[i];
9023
9024      for (var key in source) {
9025        if (Object.prototype.hasOwnProperty.call(source, key)) {
9026          target[key] = source[key];
9027        }
9028      }
9029    }
9030
9031    return target;
9032  };
9033
9034  function _classCallCheck(instance, Constructor) {
9035    if (!(instance instanceof Constructor)) {
9036      throw new TypeError("Cannot call a class as a function");
9037    }
9038  }
9039
9040  var _createClass = function () {
9041    function defineProperties(target, props) {
9042      for (var i = 0; i < props.length; i++) {
9043        var descriptor = props[i];
9044        descriptor.enumerable = descriptor.enumerable || false;
9045        descriptor.configurable = true;
9046        if ("value" in descriptor) descriptor.writable = true;
9047        Object.defineProperty(target, descriptor.key, descriptor);
9048      }
9049    }
9050
9051    return function (Constructor, protoProps, staticProps) {
9052      if (protoProps) defineProperties(Constructor.prototype, protoProps);
9053      if (staticProps) defineProperties(Constructor, staticProps);
9054      return Constructor;
9055    };
9056  }();
9057
9058  var $ = _jquery2.default || window.jQuery || window.$;
9059
9060  var BootstrapSwitch = function () {
9061    function BootstrapSwitch(element) {
9062      var _this = this;
9063
9064      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9065
9066      _classCallCheck(this, BootstrapSwitch);
9067
9068      this.$element = $(element);
9069      this.options = $.extend({}, $.fn.bootstrapSwitch.defaults, this._getElementOptions(), options);
9070      this.prevOptions = {};
9071      this.$wrapper = $('<div>', {
9072        class: function _class() {
9073          var classes = [];
9074          classes.push(_this.options.state ? 'on' : 'off');
9075          if (_this.options.size) {
9076            classes.push(_this.options.size);
9077          }
9078          if (_this.options.disabled) {
9079            classes.push('disabled');
9080          }
9081          if (_this.options.readonly) {
9082            classes.push('readonly');
9083          }
9084          if (_this.options.indeterminate) {
9085            classes.push('indeterminate');
9086          }
9087          if (_this.options.inverse) {
9088            classes.push('inverse');
9089          }
9090          if (_this.$element.attr('id')) {
9091            classes.push('id-' + _this.$element.attr('id'));
9092          }
9093          return classes.map(_this._getClass.bind(_this)).concat([_this.options.baseClass], _this._getClasses(_this.options.wrapperClass)).join(' ');
9094        }
9095      });
9096      this.$container = $('<div>', { class: this._getClass('container') });
9097      this.$on = $('<span>', {
9098        html: this.options.onText,
9099        class: this._getClass('handle-on') + ' ' + this._getClass(this.options.onColor)
9100      });
9101      this.$off = $('<span>', {
9102        html: this.options.offText,
9103        class: this._getClass('handle-off') + ' ' + this._getClass(this.options.offColor)
9104      });
9105      this.$label = $('<span>', {
9106        html: this.options.labelText,
9107        class: this._getClass('label')
9108      });
9109
9110      this.$element.on('init.bootstrapSwitch', this.options.onInit.bind(this, element));
9111      this.$element.on('switchChange.bootstrapSwitch', function () {
9112        for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
9113          args[_key] = arguments[_key];
9114        }
9115
9116        if (_this.options.onSwitchChange.apply(element, args) === false) {
9117          if (_this.$element.is(':radio')) {
9118            $('[name="' + _this.$element.attr('name') + '"]').trigger('previousState.bootstrapSwitch', true);
9119          } else {
9120            _this.$element.trigger('previousState.bootstrapSwitch', true);
9121          }
9122        }
9123      });
9124
9125      this.$container = this.$element.wrap(this.$container).parent();
9126      this.$wrapper = this.$container.wrap(this.$wrapper).parent();
9127      this.$element.before(this.options.inverse ? this.$off : this.$on).before(this.$label).before(this.options.inverse ? this.$on : this.$off);
9128
9129      if (this.options.indeterminate) {
9130        this.$element.prop('indeterminate', true);
9131      }
9132
9133      this._init();
9134      this._elementHandlers();
9135      this._handleHandlers();
9136      this._labelHandlers();
9137      this._formHandler();
9138      this._externalLabelHandler();
9139      this.$element.trigger('init.bootstrapSwitch', this.options.state);
9140    }
9141
9142    _createClass(BootstrapSwitch, [{
9143      key: 'setPrevOptions',
9144      value: function setPrevOptions() {
9145        this.prevOptions = _extends({}, this.options);
9146      }
9147    }, {
9148      key: 'state',
9149      value: function state(value, skip) {
9150        if (typeof value === 'undefined') {
9151          return this.options.state;
9152        }
9153        if (this.options.disabled || this.options.readonly || this.options.state && !this.options.radioAllOff && this.$element.is(':radio')) {
9154          return this.$element;
9155        }
9156        if (this.$element.is(':radio')) {
9157          $('[name="' + this.$element.attr('name') + '"]').trigger('setPreviousOptions.bootstrapSwitch');
9158        } else {
9159          this.$element.trigger('setPreviousOptions.bootstrapSwitch');
9160        }
9161        if (this.options.indeterminate) {
9162          this.indeterminate(false);
9163        }
9164        this.$element.prop('checked', Boolean(value)).trigger('change.bootstrapSwitch', skip);
9165        return this.$element;
9166      }
9167    }, {
9168      key: 'toggleState',
9169      value: function toggleState(skip) {
9170        if (this.options.disabled || this.options.readonly) {
9171          return this.$element;
9172        }
9173        if (this.options.indeterminate) {
9174          this.indeterminate(false);
9175          return this.state(true);
9176        } else {
9177          return this.$element.prop('checked', !this.options.state).trigger('change.bootstrapSwitch', skip);
9178        }
9179      }
9180    }, {
9181      key: 'size',
9182      value: function size(value) {
9183        if (typeof value === 'undefined') {
9184          return this.options.size;
9185        }
9186        if (this.options.size != null) {
9187          this.$wrapper.removeClass(this._getClass(this.options.size));
9188        }
9189        if (value) {
9190          this.$wrapper.addClass(this._getClass(value));
9191        }
9192        this._width();
9193        this._containerPosition();
9194        this.options.size = value;
9195        return this.$element;
9196      }
9197    }, {
9198      key: 'animate',
9199      value: function animate(value) {
9200        if (typeof value === 'undefined') {
9201          return this.options.animate;
9202        }
9203        if (this.options.animate === Boolean(value)) {
9204          return this.$element;
9205        }
9206        return this.toggleAnimate();
9207      }
9208    }, {
9209      key: 'toggleAnimate',
9210      value: function toggleAnimate() {
9211        this.options.animate = !this.options.animate;
9212        this.$wrapper.toggleClass(this._getClass('animate'));
9213        return this.$element;
9214      }
9215    }, {
9216      key: 'disabled',
9217      value: function disabled(value) {
9218        if (typeof value === 'undefined') {
9219          return this.options.disabled;
9220        }
9221        if (this.options.disabled === Boolean(value)) {
9222          return this.$element;
9223        }
9224        return this.toggleDisabled();
9225      }
9226    }, {
9227      key: 'toggleDisabled',
9228      value: function toggleDisabled() {
9229        this.options.disabled = !this.options.disabled;
9230        this.$element.prop('disabled', this.options.disabled);
9231        this.$wrapper.toggleClass(this._getClass('disabled'));
9232        return this.$element;
9233      }
9234    }, {
9235      key: 'readonly',
9236      value: function readonly(value) {
9237        if (typeof value === 'undefined') {
9238          return this.options.readonly;
9239        }
9240        if (this.options.readonly === Boolean(value)) {
9241          return this.$element;
9242        }
9243        return this.toggleReadonly();
9244      }
9245    }, {
9246      key: 'toggleReadonly',
9247      value: function toggleReadonly() {
9248        this.options.readonly = !this.options.readonly;
9249        this.$element.prop('readonly', this.options.readonly);
9250        this.$wrapper.toggleClass(this._getClass('readonly'));
9251        return this.$element;
9252      }
9253    }, {
9254      key: 'indeterminate',
9255      value: function indeterminate(value) {
9256        if (typeof value === 'undefined') {
9257          return this.options.indeterminate;
9258        }
9259        if (this.options.indeterminate === Boolean(value)) {
9260          return this.$element;
9261        }
9262        return this.toggleIndeterminate();
9263      }
9264    }, {
9265      key: 'toggleIndeterminate',
9266      value: function toggleIndeterminate() {
9267        this.options.indeterminate = !this.options.indeterminate;
9268        this.$element.prop('indeterminate', this.options.indeterminate);
9269        this.$wrapper.toggleClass(this._getClass('indeterminate'));
9270        this._containerPosition();
9271        return this.$element;
9272      }
9273    }, {
9274      key: 'inverse',
9275      value: function inverse(value) {
9276        if (typeof value === 'undefined') {
9277          return this.options.inverse;
9278        }
9279        if (this.options.inverse === Boolean(value)) {
9280          return this.$element;
9281        }
9282        return this.toggleInverse();
9283      }
9284    }, {
9285      key: 'toggleInverse',
9286      value: function toggleInverse() {
9287        this.$wrapper.toggleClass(this._getClass('inverse'));
9288        var $on = this.$on.clone(true);
9289        var $off = this.$off.clone(true);
9290        this.$on.replaceWith($off);
9291        this.$off.replaceWith($on);
9292        this.$on = $off;
9293        this.$off = $on;
9294        this.options.inverse = !this.options.inverse;
9295        return this.$element;
9296      }
9297    }, {
9298      key: 'onColor',
9299      value: function onColor(value) {
9300        if (typeof value === 'undefined') {
9301          return this.options.onColor;
9302        }
9303        if (this.options.onColor) {
9304          this.$on.removeClass(this._getClass(this.options.onColor));
9305        }
9306        this.$on.addClass(this._getClass(value));
9307        this.options.onColor = value;
9308        return this.$element;
9309      }
9310    }, {
9311      key: 'offColor',
9312      value: function offColor(value) {
9313        if (typeof value === 'undefined') {
9314          return this.options.offColor;
9315        }
9316        if (this.options.offColor) {
9317          this.$off.removeClass(this._getClass(this.options.offColor));
9318        }
9319        this.$off.addClass(this._getClass(value));
9320        this.options.offColor = value;
9321        return this.$element;
9322      }
9323    }, {
9324      key: 'onText',
9325      value: function onText(value) {
9326        if (typeof value === 'undefined') {
9327          return this.options.onText;
9328        }
9329        this.$on.html(value);
9330        this._width();
9331        this._containerPosition();
9332        this.options.onText = value;
9333        return this.$element;
9334      }
9335    }, {
9336      key: 'offText',
9337      value: function offText(value) {
9338        if (typeof value === 'undefined') {
9339          return this.options.offText;
9340        }
9341        this.$off.html(value);
9342        this._width();
9343        this._containerPosition();
9344        this.options.offText = value;
9345        return this.$element;
9346      }
9347    }, {
9348      key: 'labelText',
9349      value: function labelText(value) {
9350        if (typeof value === 'undefined') {
9351          return this.options.labelText;
9352        }
9353        this.$label.html(value);
9354        this._width();
9355        this.options.labelText = value;
9356        return this.$element;
9357      }
9358    }, {
9359      key: 'handleWidth',
9360      value: function handleWidth(value) {
9361        if (typeof value === 'undefined') {
9362          return this.options.handleWidth;
9363        }
9364        this.options.handleWidth = value;
9365        this._width();
9366        this._containerPosition();
9367        return this.$element;
9368      }
9369    }, {
9370      key: 'labelWidth',
9371      value: function labelWidth(value) {
9372        if (typeof value === 'undefined') {
9373          return this.options.labelWidth;
9374        }
9375        this.options.labelWidth = value;
9376        this._width();
9377        this._containerPosition();
9378        return this.$element;
9379      }
9380    }, {
9381      key: 'baseClass',
9382      value: function baseClass(value) {
9383        return this.options.baseClass;
9384      }
9385    }, {
9386      key: 'wrapperClass',
9387      value: function wrapperClass(value) {
9388        if (typeof value === 'undefined') {
9389          return this.options.wrapperClass;
9390        }
9391        if (!value) {
9392          value = $.fn.bootstrapSwitch.defaults.wrapperClass;
9393        }
9394        this.$wrapper.removeClass(this._getClasses(this.options.wrapperClass).join(' '));
9395        this.$wrapper.addClass(this._getClasses(value).join(' '));
9396        this.options.wrapperClass = value;
9397        return this.$element;
9398      }
9399    }, {
9400      key: 'radioAllOff',
9401      value: function radioAllOff(value) {
9402        if (typeof value === 'undefined') {
9403          return this.options.radioAllOff;
9404        }
9405        var val = Boolean(value);
9406        if (this.options.radioAllOff === val) {
9407          return this.$element;
9408        }
9409        this.options.radioAllOff = val;
9410        return this.$element;
9411      }
9412    }, {
9413      key: 'onInit',
9414      value: function onInit(value) {
9415        if (typeof value === 'undefined') {
9416          return this.options.onInit;
9417        }
9418        if (!value) {
9419          value = $.fn.bootstrapSwitch.defaults.onInit;
9420        }
9421        this.options.onInit = value;
9422        return this.$element;
9423      }
9424    }, {
9425      key: 'onSwitchChange',
9426      value: function onSwitchChange(value) {
9427        if (typeof value === 'undefined') {
9428          return this.options.onSwitchChange;
9429        }
9430        if (!value) {
9431          value = $.fn.bootstrapSwitch.defaults.onSwitchChange;
9432        }
9433        this.options.onSwitchChange = value;
9434        return this.$element;
9435      }
9436    }, {
9437      key: 'destroy',
9438      value: function destroy() {
9439        var $form = this.$element.closest('form');
9440        if ($form.length) {
9441          $form.off('reset.bootstrapSwitch').removeData('bootstrap-switch');
9442        }
9443        this.$container.children().not(this.$element).remove();
9444        this.$element.unwrap().unwrap().off('.bootstrapSwitch').removeData('bootstrap-switch');
9445        return this.$element;
9446      }
9447    }, {
9448      key: '_getElementOptions',
9449      value: function _getElementOptions() {
9450        return {
9451          state: this.$element.is(':checked'),
9452          size: this.$element.data('size'),
9453          animate: this.$element.data('animate'),
9454          disabled: this.$element.is(':disabled'),
9455          readonly: this.$element.is('[readonly]'),
9456          indeterminate: this.$element.data('indeterminate'),
9457          inverse: this.$element.data('inverse'),
9458          radioAllOff: this.$element.data('radio-all-off'),
9459          onColor: this.$element.data('on-color'),
9460          offColor: this.$element.data('off-color'),
9461          onText: this.$element.data('on-text'),
9462          offText: this.$element.data('off-text'),
9463          labelText: this.$element.data('label-text'),
9464          handleWidth: this.$element.data('handle-width'),
9465          labelWidth: this.$element.data('label-width'),
9466          baseClass: this.$element.data('base-class'),
9467          wrapperClass: this.$element.data('wrapper-class')
9468        };
9469      }
9470    }, {
9471      key: '_width',
9472      value: function _width() {
9473        var _this2 = this;
9474
9475        var $handles = this.$on.add(this.$off).add(this.$label).css('width', '');
9476        var handleWidth = this.options.handleWidth === 'auto' ? Math.round(Math.max(this.$on.width(), this.$off.width())) : this.options.handleWidth;
9477        $handles.width(handleWidth);
9478        this.$label.width(function (index, width) {
9479          if (_this2.options.labelWidth !== 'auto') {
9480            return _this2.options.labelWidth;
9481          }
9482          if (width < handleWidth) {
9483            return handleWidth;
9484          }
9485          return width;
9486        });
9487        this._handleWidth = this.$on.outerWidth();
9488        this._labelWidth = this.$label.outerWidth();
9489        this.$container.width(this._handleWidth * 2 + this._labelWidth);
9490        return this.$wrapper.width(this._handleWidth + this._labelWidth);
9491      }
9492    }, {
9493      key: '_containerPosition',
9494      value: function _containerPosition() {
9495        var _this3 = this;
9496
9497        var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.options.state;
9498        var callback = arguments[1];
9499
9500        this.$container.css('margin-left', function () {
9501          var values = [0, '-' + _this3._handleWidth + 'px'];
9502          if (_this3.options.indeterminate) {
9503            return '-' + _this3._handleWidth / 2 + 'px';
9504          }
9505          if (state) {
9506            if (_this3.options.inverse) {
9507              return values[1];
9508            } else {
9509              return values[0];
9510            }
9511          } else {
9512            if (_this3.options.inverse) {
9513              return values[0];
9514            } else {
9515              return values[1];
9516            }
9517          }
9518        });
9519      }
9520    }, {
9521      key: '_init',
9522      value: function _init() {
9523        var _this4 = this;
9524
9525        var init = function init() {
9526          _this4.setPrevOptions();
9527          _this4._width();
9528          _this4._containerPosition();
9529          setTimeout(function () {
9530            if (_this4.options.animate) {
9531              return _this4.$wrapper.addClass(_this4._getClass('animate'));
9532            }
9533          }, 50);
9534        };
9535        if (this.$wrapper.is(':visible')) {
9536          init();
9537          return;
9538        }
9539        var initInterval = window.setInterval(function () {
9540          if (_this4.$wrapper.is(':visible')) {
9541            init();
9542            return window.clearInterval(initInterval);
9543          }
9544        }, 50);
9545      }
9546    }, {
9547      key: '_elementHandlers',
9548      value: function _elementHandlers() {
9549        var _this5 = this;
9550
9551        return this.$element.on({
9552          'setPreviousOptions.bootstrapSwitch': this.setPrevOptions.bind(this),
9553
9554          'previousState.bootstrapSwitch': function previousStateBootstrapSwitch() {
9555            _this5.options = _this5.prevOptions;
9556            if (_this5.options.indeterminate) {
9557              _this5.$wrapper.addClass(_this5._getClass('indeterminate'));
9558            }
9559            _this5.$element.prop('checked', _this5.options.state).trigger('change.bootstrapSwitch', true);
9560          },
9561
9562          'change.bootstrapSwitch': function changeBootstrapSwitch(event, skip) {
9563            event.preventDefault();
9564            event.stopImmediatePropagation();
9565            var state = _this5.$element.is(':checked');
9566            _this5._containerPosition(state);
9567            if (state === _this5.options.state) {
9568              return;
9569            }
9570            _this5.options.state = state;
9571            _this5.$wrapper.toggleClass(_this5._getClass('off')).toggleClass(_this5._getClass('on'));
9572            if (!skip) {
9573              if (_this5.$element.is(':radio')) {
9574                $('[name="' + _this5.$element.attr('name') + '"]').not(_this5.$element).prop('checked', false).trigger('change.bootstrapSwitch', true);
9575              }
9576              _this5.$element.trigger('switchChange.bootstrapSwitch', [state]);
9577            }
9578          },
9579
9580          'focus.bootstrapSwitch': function focusBootstrapSwitch(event) {
9581            event.preventDefault();
9582            _this5.$wrapper.addClass(_this5._getClass('focused'));
9583          },
9584
9585          'blur.bootstrapSwitch': function blurBootstrapSwitch(event) {
9586            event.preventDefault();
9587            _this5.$wrapper.removeClass(_this5._getClass('focused'));
9588          },
9589
9590          'keydown.bootstrapSwitch': function keydownBootstrapSwitch(event) {
9591            if (!event.which || _this5.options.disabled || _this5.options.readonly) {
9592              return;
9593            }
9594            if (event.which === 37 || event.which === 39) {
9595              event.preventDefault();
9596              event.stopImmediatePropagation();
9597              _this5.state(event.which === 39);
9598            }
9599          }
9600        });
9601      }
9602    }, {
9603      key: '_handleHandlers',
9604      value: function _handleHandlers() {
9605        var _this6 = this;
9606
9607        this.$on.on('click.bootstrapSwitch', function (event) {
9608          event.preventDefault();
9609          event.stopPropagation();
9610          _this6.state(false);
9611          return _this6.$element.trigger('focus.bootstrapSwitch');
9612        });
9613        return this.$off.on('click.bootstrapSwitch', function (event) {
9614          event.preventDefault();
9615          event.stopPropagation();
9616          _this6.state(true);
9617          return _this6.$element.trigger('focus.bootstrapSwitch');
9618        });
9619      }
9620    }, {
9621      key: '_labelHandlers',
9622      value: function _labelHandlers() {
9623        var _this7 = this;
9624
9625        var handlers = {
9626          click: function click(event) {
9627            event.stopPropagation();
9628          },
9629
9630
9631          'mousedown.bootstrapSwitch touchstart.bootstrapSwitch': function mousedownBootstrapSwitchTouchstartBootstrapSwitch(event) {
9632            if (_this7._dragStart || _this7.options.disabled || _this7.options.readonly) {
9633              return;
9634            }
9635            event.preventDefault();
9636            event.stopPropagation();
9637            _this7._dragStart = (event.pageX || event.originalEvent.touches[0].pageX) - parseInt(_this7.$container.css('margin-left'), 10);
9638            if (_this7.options.animate) {
9639              _this7.$wrapper.removeClass(_this7._getClass('animate'));
9640            }
9641            _this7.$element.trigger('focus.bootstrapSwitch');
9642          },
9643
9644          'mousemove.bootstrapSwitch touchmove.bootstrapSwitch': function mousemoveBootstrapSwitchTouchmoveBootstrapSwitch(event) {
9645            if (_this7._dragStart == null) {
9646              return;
9647            }
9648            var difference = (event.pageX || event.originalEvent.touches[0].pageX) - _this7._dragStart;
9649            event.preventDefault();
9650            if (difference < -_this7._handleWidth || difference > 0) {
9651              return;
9652            }
9653            _this7._dragEnd = difference;
9654            _this7.$container.css('margin-left', _this7._dragEnd + 'px');
9655          },
9656
9657          'mouseup.bootstrapSwitch touchend.bootstrapSwitch': function mouseupBootstrapSwitchTouchendBootstrapSwitch(event) {
9658            if (!_this7._dragStart) {
9659              return;
9660            }
9661            event.preventDefault();
9662            if (_this7.options.animate) {
9663              _this7.$wrapper.addClass(_this7._getClass('animate'));
9664            }
9665            if (_this7._dragEnd) {
9666              var state = _this7._dragEnd > -(_this7._handleWidth / 2);
9667              _this7._dragEnd = false;
9668              _this7.state(_this7.options.inverse ? !state : state);
9669            } else {
9670              _this7.state(!_this7.options.state);
9671            }
9672            _this7._dragStart = false;
9673          },
9674
9675          'mouseleave.bootstrapSwitch': function mouseleaveBootstrapSwitch() {
9676            _this7.$label.trigger('mouseup.bootstrapSwitch');
9677          }
9678        };
9679        this.$label.on(handlers);
9680      }
9681    }, {
9682      key: '_externalLabelHandler',
9683      value: function _externalLabelHandler() {
9684        var _this8 = this;
9685
9686        var $externalLabel = this.$element.closest('label');
9687        $externalLabel.on('click', function (event) {
9688          event.preventDefault();
9689          event.stopImmediatePropagation();
9690          if (event.target === $externalLabel[0]) {
9691            _this8.toggleState();
9692          }
9693        });
9694      }
9695    }, {
9696      key: '_formHandler',
9697      value: function _formHandler() {
9698        var $form = this.$element.closest('form');
9699        if ($form.data('bootstrap-switch')) {
9700          return;
9701        }
9702        $form.on('reset.bootstrapSwitch', function () {
9703          window.setTimeout(function () {
9704            $form.find('input').filter(function () {
9705              return $(this).data('bootstrap-switch');
9706            }).each(function () {
9707              return $(this).bootstrapSwitch('state', this.checked);
9708            });
9709          }, 1);
9710        }).data('bootstrap-switch', true);
9711      }
9712    }, {
9713      key: '_getClass',
9714      value: function _getClass(name) {
9715        return this.options.baseClass + '-' + name;
9716      }
9717    }, {
9718      key: '_getClasses',
9719      value: function _getClasses(classes) {
9720        if (!$.isArray(classes)) {
9721          return [this._getClass(classes)];
9722        }
9723        return classes.map(this._getClass.bind(this));
9724      }
9725    }]);
9726
9727    return BootstrapSwitch;
9728  }();
9729
9730  $.fn.bootstrapSwitch = function (option) {
9731    for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
9732      args[_key2 - 1] = arguments[_key2];
9733    }
9734
9735    function reducer(ret, next) {
9736      var $this = $(next);
9737      var existingData = $this.data('bootstrap-switch');
9738      var data = existingData || new BootstrapSwitch(next, option);
9739      if (!existingData) {
9740        $this.data('bootstrap-switch', data);
9741      }
9742      if (typeof option === 'string') {
9743        return data[option].apply(data, args);
9744      }
9745      return ret;
9746    }
9747    return Array.prototype.reduce.call(this, reducer, this);
9748  };
9749  $.fn.bootstrapSwitch.Constructor = BootstrapSwitch;
9750  $.fn.bootstrapSwitch.defaults = {
9751    state: true,
9752    size: null,
9753    animate: true,
9754    disabled: false,
9755    readonly: false,
9756    indeterminate: false,
9757    inverse: false,
9758    radioAllOff: false,
9759    onColor: 'primary',
9760    offColor: 'default',
9761    onText: 'ON',
9762    offText: 'OFF',
9763    labelText: '&nbsp',
9764    handleWidth: 'auto',
9765    labelWidth: 'auto',
9766    baseClass: 'bootstrap-switch',
9767    wrapperClass: 'wrapper',
9768    onInit: function onInit() {},
9769    onSwitchChange: function onSwitchChange() {}
9770  };
9771});
9772
9773//$.fn.bootstrapSwitch.defaults.size = 'large';
9774//$.fn.bootstrapSwitch.defaults.onColor = 'success';
9775+function(a){"use strict";function c(c){return this.each(function(){var d=a(this),e=d.data("multiselectsplitter"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("multiselectsplitter",e=new b(this,f)),"string"==typeof c&&e[c]())})}var b=function(a,b){this.init("multiselectsplitter",a,b)};b.DEFAULTS={selectSize:null,maxSelectSize:null,clearOnFirstChange:!1,onlySameGroup:!1,groupCounter:!1,maximumSelected:null,afterInitialize:null,maximumAlert:function(a){alert("Only "+a+" values can be selected")},createFirstSelect:function(a,b){return"<option>"+a+"</option>"},createSecondSelect:function(a,b){return"<option>"+a+"</option>"},template:'<div class="row" data-multiselectsplitter-wrapper-selector><div class="col-xs-6 col-sm-6"><select class="form-control" data-multiselectsplitter-firstselect-selector></select></div> <!-- Add the extra clearfix for only the required viewport --><div class="col-xs-6 col-sm-6"><select class="form-control" data-multiselectsplitter-secondselect-selector></select></div></div>'},b.prototype.init=function(c,d,e){var f=this;f.type=c,f.last$ElementSelected=[],f.initialized=!1,f.$element=a(d),f.$element.hide(),f.options=a.extend({},b.DEFAULTS,e),f.$element.after(f.options.template),f.$wrapper=f.$element.next("div[data-multiselectsplitter-wrapper-selector]"),f.$firstSelect=a("select[data-multiselectsplitter-firstselect-selector]",f.$wrapper),f.$secondSelect=a("select[data-multiselectsplitter-secondselect-selector]",f.$wrapper);var g=0,h=0;if(0!=f.$element.find("optgroup").length){f.$element.find("optgroup").each(function(){var b=a(this).attr("label"),c=a(f.options.createFirstSelect(b,f.$element));c.val(b),c.attr("data-current-label",c.text()),f.$firstSelect.append(c);var d=a(this).find("option").length;d>h&&(h=d),g++});var i=Math.max(g,h);i=Math.min(i,10),f.options.selectSize?i=f.options.selectSize:f.options.maxSelectSize&&(i=Math.min(i,f.options.maxSelectSize)),f.$firstSelect.attr("size",i),f.$secondSelect.attr("size",i),f.$element.attr("multiple")&&f.$secondSelect.attr("multiple","multiple"),f.$element.is(":disabled")&&f.disable(),f.$firstSelect.on("change",a.proxy(f.updateParentCategory,f)),f.$secondSelect.on("click change",a.proxy(f.updateChildCategory,f)),f.update=function(){if(!(f.$element.find("option").length<1)){var b,a=f.$element.find("option:selected:first");b=a.length?a.parent().attr("label"):f.$element.find("option:first").parent().attr("label"),f.$firstSelect.find('option[value="'+b+'"]').prop("selected",!0),f.$firstSelect.trigger("change")}}
9775,f.update(),f.initialized=!0,f.options.afterInitialize&&f.options.afterInitialize(f.$firstSelect,f.$secondSelect)}},b.prototype.disable=function(){this.$secondSelect.prop("disabled",!0),this.$firstSelect.prop("disabled",!0)},b.prototype.enable=function(){this.$secondSelect.prop("disabled",!1),this.$firstSelect.prop("disabled",!1)},b.prototype.createSecondSelect=function(){var b=this;b.$secondSelect.empty(),a.each(b.$element.find('optgroup[label="'+b.$firstSelect.val()+'"] option'),function(c,d){var e=a(this).val(),f=a(this).text(),g=a(b.options.createSecondSelect(f,b.$firstSelect));g.val(e),a.each(b.$element.find("option:selected"),function(b,c){a(c).val()==e&&g.prop("selected",!0)}),b.$secondSelect.append(g)})},b.prototype.updateParentCategory=function(){var a=this;a.last$ElementSelected=a.$element.find("option:selected"),a.options.clearOnFirstChange&&a.initialized&&a.$element.find("option:selected").prop("selected",!1),a.createSecondSelect(),a.checkSelected(),a.updateCounter()},b.prototype.updateCounter=function(){var b=this;b.$element.attr("multiple")&&b.options.groupCounter&&a.each(b.$firstSelect.find("option"),function(c,d){var e=a(d).val(),f=a(d).data("currentLabel"),g=b.$element.find('optgroup[label="'+e+'"] option:selected').length;g>0&&(f+=" ("+g+")"),a(d).html(f)})},b.prototype.checkSelected=function(){var b=this;if(b.$element.attr("multiple")&&b.options.maximumSelected){var c=0;if(c="function"==typeof b.options.maximumSelected?b.options.maximumSelected(b.$firstSelect,b.$secondSelect):b.options.maximumSelected,!(c<1)){var d=b.$element.find("option:selected");if(d.length>c){b.$firstSelect.find("option:selected").prop("selected",!1),b.$secondSelect.find("option:selected").prop("selected",!1),b.initialized?(b.$element.find("option:selected").prop("selected",!1),b.last$ElementSelected.prop("selected",!0)):a.each(b.$element.find("option:selected"),function(b,d){b>c-1&&a(d).prop("selected",!1)});var e=b.last$ElementSelected.first().parent().attr("label");b.$firstSelect.find('option[value="'+e+'"]').prop("selected",!0),b.createSecondSelect(),b.options.maximumAlert(c)}}}},b.prototype.basicUpdateChildCategory=function(b,c){var d=this;d.last$ElementSelected=d.$element.find("option:selected");var e=d.$secondSelect.val();a.isArray(e)||(e=[e]);var f=d.$firstSelect.val(),g=!1;d.$element.attr("multiple")?d.options.onlySameGroup?a.each(d.$element.find("option:selected"),function(b,c){if(a(c).parent().attr("label")!=f)return g=!0,!1}):c||(g=!0):g=!0,g?d.$element.find("option:selected").prop("selected",!1):a.each(d.$element.find("option:selected"),function(b,c){f==a(c).parent().attr("label")&&a.inArray(a(c).val(),e)==-1&&a(c).prop("selected",!1)}),a.each(e,function(a,b){d.$element.find('option[value="'+b+'"]').prop("selected",!0)}),d.checkSelected(),d.updateCounter(),d.$element.trigger("change")},b.prototype.updateChildCategory=function(b){"change"==b.type?this.timeOut=setTimeout(a.proxy(function(){this.basicUpdateChildCategory(b,b.ctrlKey)},this),10):"click"==b.type&&(clearTimeout(this.timeOut),this.basicUpdateChildCategory(b,b.ctrlKey))},b.prototype.destroy=function(){this.$wrapper.remove(),this.$element.removeData(this.type),this.$element.show()},a.fn.multiselectsplitter=c,a.fn.multiselectsplitter.Constructor=b,a.fn.multiselectsplitter.VERSION="1.0.1"}(jQuery);
9776/*!
9777 * Bootstrap-select v1.13.0-beta (https://developer.snapappointments.com/bootstrap-select)
9778 *
9779 * Copyright 2012-2018 SnapAppointments, LLC
9780 * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE)
9781 */
9782
9783(function (root, factory) {
9784  if (typeof define === 'function' && define.amd) {
9785    // AMD. Register as an anonymous module unless amdModuleId is set
9786    define(["jquery"], function (a0) {
9787      return (factory(a0));
9788    });
9789  } else if (typeof module === 'object' && module.exports) {
9790    // Node. Does not work with strict CommonJS, but
9791    // only CommonJS-like environments that support module.exports,
9792    // like Node.
9793    module.exports = factory(require("jquery"));
9794  } else {
9795    factory(root["jQuery"]);
9796  }
9797}(this, function (jQuery) {
9798
9799(function ($) {
9800  'use strict';
9801
9802  var testElement = document.createElement('_');
9803
9804  testElement.classList.toggle('c3', false);
9805
9806  // Polyfill for IE 10 and Firefox <24, where classList.toggle does not
9807  // support the second argument.
9808  if (testElement.classList.contains('c3')) {
9809    var _toggle = DOMTokenList.prototype.toggle;
9810
9811    DOMTokenList.prototype.toggle = function(token, force) {
9812      if (1 in arguments && !this.contains(token) === !force) {
9813        return force;
9814      } else {
9815        return _toggle.call(this, token);
9816      }
9817    };
9818  }
9819
9820  // shallow array comparison
9821  function isEqual (array1, array2) {
9822    return array1.length === array2.length && array1.every(function(element, index) {
9823      return element === array2[index]; 
9824    });
vendor: 4,091 bytes, lines 9825-9963
9825  };
9826
9827  //<editor-fold desc="Shims">
9828  if (!String.prototype.startsWith) {
9829    (function () {
9830      'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
9831      var defineProperty = (function () {
9832        // IE 8 only supports `Object.defineProperty` on DOM elements
9833        try {
9834          var object = {};
9835          var $defineProperty = Object.defineProperty;
9836          var result = $defineProperty(object, object, object) && $defineProperty;
9837        } catch (error) {
9838        }
9839        return result;
9840      }());
9841      var toString = {}.toString;
9842      var startsWith = function (search) {
9843        if (this == null) {
9844          throw new TypeError();
9845        }
9846        var string = String(this);
9847        if (search && toString.call(search) == '[object RegExp]') {
9848          throw new TypeError();
9849        }
9850        var stringLength = string.length;
9851        var searchString = String(search);
9852        var searchLength = searchString.length;
9853        var position = arguments.length > 1 ? arguments[1] : undefined;
9854        // `ToInteger`
9855        var pos = position ? Number(position) : 0;
9856        if (pos != pos) { // better `isNaN`
9857          pos = 0;
9858        }
9859        var start = Math.min(Math.max(pos, 0), stringLength);
9860        // Avoid the `indexOf` call if no match is possible
9861        if (searchLength + start > stringLength) {
9862          return false;
9863        }
9864        var index = -1;
9865        while (++index < searchLength) {
9866          if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) {
9867            return false;
9868          }
9869        }
9870        return true;
9871      };
9872      if (defineProperty) {
9873        defineProperty(String.prototype, 'startsWith', {
9874          'value': startsWith,
9875          'configurable': true,
9876          'writable': true
9877        });
9878      } else {
9879        String.prototype.startsWith = startsWith;
9880      }
9881    }());
9882  }
9883
9884  if (!Object.keys) {
9885    Object.keys = function (
9886      o, // object
9887      k, // key
9888      r  // result array
9889      ){
9890      // initialize object and result
9891      r=[];
9892      // iterate over object keys
9893      for (k in o)
9894          // fill result array with non-prototypical keys
9895        r.hasOwnProperty.call(o, k) && r.push(k);
9896      // return result
9897      return r;
9898    };
9899  }
9900
9901  // set data-selected on select element if the value has been programmatically selected
9902  // prior to initialization of bootstrap-select
9903  // * consider removing or replacing an alternative method *
9904  var valHooks = {
9905    useDefault: false,
9906    _set: $.valHooks.select.set
9907  };
9908
9909  $.valHooks.select.set = function (elem, value) {
9910    if (value && !valHooks.useDefault) $(elem).data('selected', true);
9911
9912    return valHooks._set.apply(this, arguments);
9913  };
9914
9915  var changed_arguments = null;
9916
9917  var EventIsSupported = (function () {
9918    try {
9919      new Event('change');
9920      return true;
9921    } catch (e) {
9922      return false;
9923    }
9924  })();
9925
9926  $.fn.triggerNative = function (eventName) {
9927    var el = this[0],
9928        event;
9929
9930    if (el.dispatchEvent) { // for modern browsers & IE9+
9931      if (EventIsSupported) {
9932        // For modern browsers
9933        event = new Event(eventName, {
9934          bubbles: true
9935        });
9936      } else {
9937        // For IE since it doesn't support Event constructor
9938        event = document.createEvent('Event');
9939        event.initEvent(eventName, true, false);
9940      }
9941
9942      el.dispatchEvent(event);
9943    } else if (el.fireEvent) { // for IE8
9944      event = document.createEventObject();
9945      event.eventType = eventName;
9946      el.fireEvent('on' + eventName, event);
9947    } else {
9948      // fall back to jQuery.trigger
9949      this.trigger(eventName);
9950    }
9951  };
9952  //</editor-fold>
9953
9954  function stringSearch(li, searchString, method, normalize) {
9955    var stringTypes = [
9956        'content',
9957        'subtext',
9958        'tokens'
9959      ],
9960      searchSuccess = false;
9961
9962    for (var i = 0; i < stringTypes.length; i++) {
9963      var stringType = stringTypes[i],
9964          string = li[stringType];
9965
9966      if (string) {
9967        if (normalize) string = normalizeToBase(string);
9968        string = string.toUpperCase();
9969
9970        if (method === 'contains') {
9971          searchSuccess = string.indexOf(searchString) >= 0;
9972        } else {
9973          searchSuccess = string.startsWith(searchString);
9974        }
9975
9976        if (searchSuccess) break;
9977      }
9978    }
9979
9980    return searchSuccess;
9981  }
9982
9983  function toInteger(value) {
9984    return parseInt(value, 10) || 0;
9985  }
9986
9987  /**
9988   * Remove all diatrics from the given text.
9989   * @access private
9990   * @param {String} text
9991   * @returns {String}
9992   */
9993  function normalizeToBase(text) {
9994    var rExps = [
9995      {re: /[\xC0-\xC6]/g, ch: "A"},
9996      {re: /[\xE0-\xE6]/g, ch: "a"},
9997      {re: /[\xC8-\xCB]/g, ch: "E"},
9998      {re: /[\xE8-\xEB]/g, ch: "e"},
9999      {re: /[\xCC-\xCF]/g, ch: "I"},
10000      {re: /[\xEC-\xEF]/g, ch: "i"},
10001      {re: /[\xD2-\xD6]/g, ch: "O"},
10002      {re: /[\xF2-\xF6]/g, ch: "o"},
10003      {re: /[\xD9-\xDC]/g, ch: "U"},
10004      {re: /[\xF9-\xFC]/g, ch: "u"},
10005      {re: /[\xC7-\xE7]/g, ch: "c"},
10006      {re: /[\xD1]/g, ch: "N"},
10007      {re: /[\xF1]/g, ch: "n"}
10008    ];
10009    $.each(rExps, function () {
10010      text = text ? text.replace(this.re, this.ch) : '';
10011    });
10012    return text;
10013  }
10014
10015
10016  // List of HTML entities for escaping.
10017  var escapeMap = {
10018    '&': '&amp;',
10019    '<': '&lt;',
10020    '>': '&gt;',
10021    '"': '&quot;',
10022    "'": '&#x27;',
10023    '`': '&#x60;'
10024  };
10025  
10026  var unescapeMap = {
10027    '&amp;': '&',
10028    '&lt;': '<',
10029    '&gt;': '>',
10030    '&quot;': '"',
10031    '&#x27;': "'",
10032    '&#x60;': '`'
10033  };
10034
10035  // Functions for escaping and unescaping strings to/from HTML interpolation.
10036  var createEscaper = function (map) {
10037    var escaper = function (match) {
10038      return map[match];
10039    };
10040    // Regexes for identifying a key that needs to be escaped.
10041    var source = '(?:' + Object.keys(map).join('|') + ')';
10042    var testRegexp = RegExp(source);
10043    var replaceRegexp = RegExp(source, 'g');
10044    return function (string) {
10045      string = string == null ? '' : '' + string;
10046      return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
10047    };
10048  };
10049
10050  var htmlEscape = createEscaper(escapeMap);
10051  var htmlUnescape = createEscaper(unescapeMap);
10052
10053  /**
10054   * ------------------------------------------------------------------------
10055   * Constants
10056   * ------------------------------------------------------------------------
10057   */
10058
10059  var keyCodeMap = {
10060    32: ' ',
10061    48: '0',
10062    49: '1',
10063    50: '2',
10064    51: '3',
10065    52: '4',
10066    53: '5',
10067    54: '6',
10068    55: '7',
10069    56: '8',
10070    57: '9',
10071    59: ';',
10072    65: 'A',
10073    66: 'B',
10074    67: 'C',
10075    68: 'D',
10076    69: 'E',
10077    70: 'F',
10078    71: 'G',
10079    72: 'H',
10080    73: 'I',
10081    74: 'J',
10082    75: 'K',
10083    76: 'L',
10084    77: 'M',
10085    78: 'N',
10086    79: 'O',
10087    80: 'P',
10088    81: 'Q',
10089    82: 'R',
10090    83: 'S',
10091    84: 'T',
10092    85: 'U',
10093    86: 'V',
10094    87: 'W',
10095    88: 'X',
10096    89: 'Y',
10097    90: 'Z',
10098    96: '0',
10099    97: '1',
10100    98: '2',
10101    99: '3',
10102    100: '4',
10103    101: '5',
10104    102: '6',
10105    103: '7',
10106    104: '8',
10107    105: '9'
10108  };
10109
10110  var keyCodes = {
10111    ESCAPE: 27, // KeyboardEvent.which value for Escape (Esc) key
10112    ENTER: 13, // KeyboardEvent.which value for Enter key
10113    SPACE: 32, // KeyboardEvent.which value for space key
10114    TAB: 9, // KeyboardEvent.which value for tab key
10115    ARROW_UP: 38, // KeyboardEvent.which value for up arrow key
10116    ARROW_DOWN: 40 // KeyboardEvent.which value for down arrow key
10117  }
10118
10119  var version = {};
10120  version.full = ($.fn.dropdown.Constructor.VERSION || '').split(' ')[0].split('.');
10121  version.major = version.full[0];
10122
10123  var classNames = {
10124    DISABLED: 'disabled',
10125    DIVIDER: version.major === '4' ? 'dropdown-divider' : 'divider',
10126    SHOW: version.major === '4' ? 'show' : 'open',
10127    DROPUP: 'dropup',
10128    MENURIGHT: 'dropdown-menu-right',
10129    MENULEFT: 'dropdown-menu-left',
10130    // to-do: replace with more advanced template/customization options
10131    BUTTONCLASS: version.major === '4' ? 'btn-light' : 'btn-default'
10132  }
10133
10134  var REGEXP_ARROW = new RegExp(keyCodes.ARROW_UP + '|' + keyCodes.ARROW_DOWN);
10135  var REGEXP_TAB_OR_ESCAPE = new RegExp('^' + keyCodes.TAB + '$|' + keyCodes.ESCAPE);
10136  var REGEXP_ENTER_OR_SPACE = new RegExp(keyCodes.ENTER + '|' + keyCodes.SPACE);
10137
10138  var Selectpicker = function (element, options) {
10139    var that = this;
10140
10141    // bootstrap-select has been initialized - revert valHooks.select.set back to its original function
10142    if (!valHooks.useDefault) {
10143      $.valHooks.select.set = valHooks._set;
10144      valHooks.useDefault = true;
10145    }
10146
10147    this.$element = $(element);
10148    this.$newElement = null;
10149    this.$button = null;
10150    this.$menu = null;
10151    this.options = options;
10152    this.selectpicker = {
10153      main: {
10154        // store originalIndex (key) and newIndex (value) in this.selectpicker.main.map.newIndex for fast accessibility
10155        // allows us to do this.main.elements[this.selectpicker.main.map.newIndex[index]] to select an element based on the originalIndex
10156        map: {
10157          newIndex: {},
10158          originalIndex: {}
10159        }
10160      },
10161      current: {
10162        map: {}
10163      }, // current changes if a search is in progress
10164      search: {
10165        map: {}
10166      },
10167      view: {},
10168      keydown: {
10169        keyHistory: '',
10170        resetKeyHistory: {
10171          start: function () {
10172            return setTimeout(function () {
10173              that.selectpicker.keydown.keyHistory = '';
10174            }, 800);
10175          }
10176        }
10177      }
10178    };
10179    // If we have no title yet, try to pull it from the html title attribute (jQuery doesnt' pick it up as it's not a
10180    // data-attribute)
10181    if (this.options.title === null) {
10182      this.options.title = this.$element.attr('title');
10183    }
10184
10185    // Format window padding
10186    var winPad = this.options.windowPadding;
10187    if (typeof winPad === 'number') {
10188      this.options.windowPadding = [winPad, winPad, winPad, winPad];
10189    }
10190
10191    //Expose public methods
10192    this.val = Selectpicker.prototype.val;
10193    this.render = Selectpicker.prototype.render;
10194    this.refresh = Selectpicker.prototype.refresh;
10195    this.setStyle = Selectpicker.prototype.setStyle;
10196    this.selectAll = Selectpicker.prototype.selectAll;
10197    this.deselectAll = Selectpicker.prototype.deselectAll;
10198    this.destroy = Selectpicker.prototype.destroy;
10199    this.remove = Selectpicker.prototype.remove;
10200    this.show = Selectpicker.prototype.show;
10201    this.hide = Selectpicker.prototype.hide;
10202
10203    this.init();
10204  };
10205
10206  Selectpicker.VERSION = '1.13.0-beta';
10207
10208  // part of this is duplicated in i18n/defaults-en_US.js. Make sure to update both.
10209  Selectpicker.DEFAULTS = {
10210    noneSelectedText: 'Nothing selected',
10211    noneResultsText: 'No results matched {0}',
10212    countSelectedText: function (numSelected, numTotal) {
10213      return (numSelected == 1) ? "{0} item selected" : "{0} items selected";
10214    },
10215    maxOptionsText: function (numAll, numGroup) {
10216      return [
10217        (numAll == 1) ? 'Limit reached ({n} item max)' : 'Limit reached ({n} items max)',
10218        (numGroup == 1) ? 'Group limit reached ({n} item max)' : 'Group limit reached ({n} items max)'
10219      ];
10220    },
10221    selectAllText: 'Select All',
10222    deselectAllText: 'Deselect All',
10223    doneButton: false,
10224    doneButtonText: 'Close',
10225    multipleSeparator: ', ',
10226    styleBase: 'btn',
10227    style: 'btn-default',
10228    size: 'auto',
10229    title: null,
10230    selectedTextFormat: 'values',
10231    width: false,
10232    container: false,
10233    hideDisabled: false,
10234    showSubtext: false,
10235    showIcon: true,
10236    showContent: true,
10237    dropupAuto: true,
10238    header: false,
10239    liveSearch: false,
10240    liveSearchPlaceholder: null,
10241    liveSearchNormalize: false,
10242    liveSearchStyle: 'contains',
10243    actionsBox: false,
10244    iconBase: 'glyphicon',
10245    tickIcon: 'glyphicon-ok',
10246    showTick: false,
10247    template: {
10248      caret: '<span class="caret"></span>'
10249    },
10250    maxOptions: false,
10251    mobile: false,
10252    selectOnTab: false,
10253    dropdownAlignRight: false,
10254    windowPadding: 0,
10255    virtualScroll: 600
10256  };
10257
10258  if (version.major === '4') {
10259    Selectpicker.DEFAULTS.style = 'btn-light';
10260    Selectpicker.DEFAULTS.iconBase = '';
10261    Selectpicker.DEFAULTS.tickIcon = 'bs-ok-default';
10262  }
10263
10264  Selectpicker.prototype = {
10265
10266    constructor: Selectpicker,
10267
10268    init: function () {
10269      var that = this,
10270          id = this.$element.attr('id');
10271
10272      this.$element.addClass('bs-select-hidden');
10273
10274      this.multiple = this.$element.prop('multiple');
10275      this.autofocus = this.$element.prop('autofocus');
10276      this.$newElement = this.createDropdown();
10277      this.createLi();
10278      this.$element
10279        .after(this.$newElement)
10280        .prependTo(this.$newElement);
10281      this.$button = this.$newElement.children('button');
10282      this.$menu = this.$newElement.children('.dropdown-menu');
10283      this.$menuInner = this.$menu.children('.inner');
10284      this.$searchbox = this.$menu.find('input');
10285
10286      this.$element.removeClass('bs-select-hidden');
10287
10288      if (this.options.dropdownAlignRight === true) this.$menu.addClass(classNames.MENURIGHT);
10289
10290      if (typeof id !== 'undefined') {
10291        this.$button.attr('data-id', id);
10292      }
10293
10294      this.checkDisabled();
10295      this.clickListener();
10296      if (this.options.liveSearch) this.liveSearchListener();
10297      this.render();
10298      this.setStyle();
10299      this.setWidth();
10300      if (this.options.container) {
10301        this.selectPosition();
10302      } else {
10303        this.$element.on('hide.bs.select', function () {
10304          if (that.isVirtual()) {
10305            // empty menu on close
10306            var menuInner = that.$menuInner[0],
10307                emptyMenu = menuInner.firstChild.cloneNode(false);
10308
10309            // replace the existing UL with an empty one - this is faster than $.empty() or innerHTML = ''
10310            menuInner.replaceChild(emptyMenu, menuInner.firstChild);
10311            menuInner.scrollTop = 0;
10312          }
10313        });
10314      }
10315      this.$menu.data('this', this);
10316      this.$newElement.data('this', this);
10317      if (this.options.mobile) this.mobile();
10318
10319      this.$newElement.on({
10320        'hide.bs.dropdown': function (e) {
10321          that.$menuInner.attr('aria-expanded', false);
10322          that.$element.trigger('hide.bs.select', e);
10323        },
10324        'hidden.bs.dropdown': function (e) {
10325          that.$element.trigger('hidden.bs.select', e);
10326        },
10327        'show.bs.dropdown': function (e) {
10328          that.$menuInner.attr('aria-expanded', true);
10329          that.$element.trigger('show.bs.select', e);
10330        },
10331        'shown.bs.dropdown': function (e) {
10332          that.$element.trigger('shown.bs.select', e);
10333        }
10334      });
10335
10336      if (that.$element[0].hasAttribute('required')) {
10337        this.$element.on('invalid', function () {
10338          that.$button.addClass('bs-invalid');
10339
10340          that.$element.on({
10341            'shown.bs.select': function () {
10342              that.$element
10343                .val(that.$element.val()) // set the value to hide the validation message in Chrome when menu is opened
10344                .off('shown.bs.select');
10345            },
10346            'rendered.bs.select': function () {
10347              // if select is no longer invalid, remove the bs-invalid class
10348              if (this.validity.valid) that.$button.removeClass('bs-invalid');
10349              that.$element.off('rendered.bs.select');
10350            }
10351          });
10352
10353          that.$button.on('blur.bs.select', function () {
10354            that.$element.focus().blur();
10355            that.$button.off('blur.bs.select');
10356          });
10357        });
10358      }
10359
10360      setTimeout(function () {
10361        that.$element.trigger('loaded.bs.select');
10362      });
10363    },
10364
10365    createDropdown: function () {
10366      // Options
10367      // If we are multiple or showTick option is set, then add the show-tick class
10368      var showTick = (this.multiple || this.options.showTick) ? ' show-tick' : '',
10369          inputGroup = this.$element.parent().hasClass('input-group') ? ' input-group-btn' : '',
10370          autofocus = this.autofocus ? ' autofocus' : '';
10371      // Elements
10372      var header = this.options.header ? '<div class="popover-title"><button type="button" class="close" aria-hidden="true">&times;</button>' + this.options.header + '</div>' : '';
10373      var searchbox = this.options.liveSearch ?
10374      '<div class="bs-searchbox">' +
10375      '<input type="text" class="form-control" autocomplete="off"' +
10376      (null === this.options.liveSearchPlaceholder ? '' : ' placeholder="' + htmlEscape(this.options.liveSearchPlaceholder) + '"') + ' role="textbox" aria-label="Search">' +
10377      '</div>'
10378          : '';
10379      var actionsbox = this.multiple && this.options.actionsBox ?
10380      '<div class="bs-actionsbox">' +
10381      '<div class="btn-group btn-group-sm btn-block">' +
10382      '<button type="button" class="actions-btn bs-select-all btn ' + classNames.BUTTONCLASS + '">' +
10383      this.options.selectAllText +
10384      '</button>' +
10385      '<button type="button" class="actions-btn bs-deselect-all btn ' + classNames.BUTTONCLASS + '">' +
10386      this.options.deselectAllText +
10387      '</button>' +
10388      '</div>' +
10389      '</div>'
10390          : '';
10391      var donebutton = this.multiple && this.options.doneButton ?
10392      '<div class="bs-donebutton">' +
10393      '<div class="btn-group btn-block">' +
10394      '<button type="button" class="btn btn-sm ' + classNames.BUTTONCLASS + '">' +
10395      this.options.doneButtonText +
10396      '</button>' +
10397      '</div>' +
10398      '</div>'
10399          : '';
10400      var drop =
10401          '<div class="dropdown bootstrap-select' + showTick + inputGroup + '">' +
10402          '<button type="button" class="' + this.options.styleBase + ' dropdown-toggle" data-toggle="dropdown"' + autofocus + ' role="button">' +
10403          '<div class="filter-option">' +
10404            '<div class="filter-option-inner"></div>' +
10405          '</div>&nbsp;' +
10406          '<span class="bs-caret">' +
10407          this.options.template.caret +
10408          '</span>' +
10409          '</button>' +
10410          '<div class="dropdown-menu ' + (version.major === '4' ? '' : classNames.SHOW) + '" role="combobox">' +
10411          header +
10412          searchbox +
10413          actionsbox +
10414          '<div class="inner ' + classNames.SHOW + '" role="listbox" aria-expanded="false" tabindex="-1">' +
10415              '<ul class="dropdown-menu inner ' + (version.major === '4' ? classNames.SHOW : '') + '">' +
10416              '</ul>' +
10417          '</div>' +
10418          donebutton +
10419          '</div>' +
10420          '</div>';
10421
10422      return $(drop);
10423    },
10424
10425    setPositionData: function () {
10426      this.selectpicker.view.canHighlight = [];
10427
10428      for (var i = 0; i < this.selectpicker.current.data.length; i++) {
10429        var li = this.selectpicker.current.data[i],
10430            canHighlight = true;
10431
10432        if (li.type === 'divider') {
10433          canHighlight = false;
10434          li.height = this.sizeInfo.dividerHeight;
10435        } else if (li.type === 'optgroup-label') {
10436          canHighlight = false;
10437          li.height = this.sizeInfo.dropdownHeaderHeight;
10438        } else {
10439          li.height = this.sizeInfo.liHeight;
10440        }
10441
10442        if (li.disabled) canHighlight = false;
10443
10444        this.selectpicker.view.canHighlight.push(canHighlight);
10445
10446        li.position = (i === 0 ? 0 : this.selectpicker.current.data[i - 1].position) + li.height;
10447      }
10448    },
10449
10450    isVirtual: function () {
10451      return (this.options.virtualScroll !== false) && this.selectpicker.main.elements.length >= this.options.virtualScroll || this.options.virtualScroll === true;
10452    },
10453
10454    createView: function (isSearching, scrollTop) {
10455      scrollTop = scrollTop || 0;
10456
10457      var that = this;
10458
10459      this.selectpicker.current = isSearching ? this.selectpicker.search : this.selectpicker.main;
10460
10461      var $lis;
10462      var active = [];
10463      var selected;
10464      var prevActive;
10465      var activeIndex;
10466      var prevActiveIndex;
10467
10468      this.setPositionData();
10469
10470      scroll(scrollTop, true);
10471
10472      this.$menuInner.off('scroll.createView').on('scroll.createView', function (e, updateV
10472alue) {
10473        if (!that.noScroll) scroll(this.scrollTop, updateValue);
10474        that.noScroll = false;
10475      });
10476
10477      function scroll(scrollTop, init) {
10478        var size = that.selectpicker.current.elements.length,
10479            chunks = [],
10480            chunkSize,
10481            chunkCount,
10482            firstChunk,
10483            lastChunk,
10484            currentChunk = undefined,
10485            prevPositions,
10486            positionIsDifferent,
10487            previousElements,
10488            menuIsDifferent = true,
10489            isVirtual = that.isVirtual();
10490
10491        that.selectpicker.view.scrollTop = scrollTop;
10492
10493        if (isVirtual === true) {
10494          // if an option that is encountered that is wider than the current menu width, update the menu width accordingly
10495          if (that.sizeInfo.hasScrollBar && that.$menu[0].offsetWidth > that.sizeInfo.totalMenuWidth) {
10496            that.sizeInfo.menuWidth = that.$menu[0].offsetWidth;
10497            that.sizeInfo.totalMenuWidth = that.sizeInfo.menuWidth + that.sizeInfo.scrollBarWidth;
10498            that.$menu.css('min-width', that.sizeInfo.menuWidth);
10499          }
10500        }
10501
10502        chunkSize = Math.ceil(that.sizeInfo.menuInnerHeight / that.sizeInfo.liHeight * 1.5); // number of options in a chunk
10503        chunkCount = Math.round(size / chunkSize) || 1; // number of chunks
10504
10505        for (var i = 0; i < chunkCount; i++) {
10506          var end_of_chunk = (i + 1) * chunkSize;
10507
10508          if (i === chunkCount - 1) {
10509            end_of_chunk = size;
10510          }
10511
10512          chunks[i] = [
10513            (i) * chunkSize + (!i ? 0 : 1),
10514            end_of_chunk
10515          ];
10516
10517          if (!size) break;
10518
10519          if (currentChunk === undefined && scrollTop <= that.selectpicker.current.data[end_of_chunk - 1].position - that.sizeInfo.menuInnerHeight) {
10520            currentChunk = i;
10521          }
10522        }
10523
10524        if (currentChunk === undefined) currentChunk = 0;
10525
10526        prevPositions = [that.selectpicker.view.position0, that.selectpicker.view.position1];
10527
10528        // always display previous, current, and next chunks
10529        firstChunk = Math.max(0, currentChunk - 1);
10530        lastChunk = Math.min(chunkCount - 1, currentChunk + 1);
10531
10532        that.selectpicker.view.position0 = Math.max(0, chunks[firstChunk][0]) || 0;
10533        that.selectpicker.view.position1 = Math.min(size, chunks[lastChunk][1]) || 0;
10534
10535        positionIsDifferent = prevPositions[0] !== that.selectpicker.view.position0 || prevPositions[1] !== that.selectpicker.view.position1;
10536
10537        if (that.activeIndex !== undefined) {
10538          prevActive = that.selectpicker.current.elements[that.selectpicker.current.map.newIndex[that.prevActiveIndex]];
10539          active = that.selectpicker.current.elements[that.selectpicker.current.map.newIndex[that.activeIndex]];
10540          selected = that.selectpicker.current.elements[that.selectpicker.current.map.newIndex[that.selectedIndex]];
10541
10542          if (init) {
10543            if (that.activeIndex !== that.selectedIndex) {
10544              active.classList.remove('active');
10545              if (active.firstChild) active.firstChild.classList.remove('active');
10546            }
10547            that.activeIndex = undefined;
10548          }
10549
10550          if (that.activeIndex && that.activeIndex !== that.selectedIndex && selected && selected.length) {
10551            selected.classList.remove('active');
10552            if (selected.firstChild) selected.firstChild.classList.remove('active');
10553          }
10554        }
10555
10556        if (that.prevActiveIndex !== undefined && that.prevActiveIndex !== that.activeIndex && that.prevActiveIndex !== that.selectedIndex && prevActive && prevActive.length) {
10557          prevActive.classList.remove('active');
10558          if (prevActive.firstChild) prevActive.firstChild.classList.remove('active');
10559        }
10560
10561        if (init || positionIsDifferent) {
10562          previousElements = that.selectpicker.view.visibleElements ? that.selectpicker.view.visibleElements.slice() : [];
10563
10564          that.selectpicker.view.visibleElements = that.selectpicker.current.elements.slice(that.selectpicker.view.position0, that.selectpicker.view.position1);
10565
10566          that.setOptionStatus();
10567
10568          // if searching, check to make sure the list has actually been updated before updating DOM
10569          // this prevents unnecessary repaints
10570          if ( isSearching || (isVirtual === false && init) ) menuIsDifferent = !isEqual(previousElements, that.selectpicker.view.visibleElements);
10571
10572          // if virtual scroll is disabled and not searching,
10573          // menu should never need to be updated more than once
10574          if ( (init || isVirtual === true) && menuIsDifferent ) {
10575            var menuInner = that.$menuInner[0],
10576                menuFragment = document.createDocumentFragment(),
10577                emptyMenu = menuInner.firstChild.cloneNode(false),
10578                marginTop,
10579                marginBottom,
10580                elements = isVirtual === true ? that.selectpicker.view.visibleElements : that.selectpicker.current.elements;
10581
10582            // replace the existing UL with an empty one - this is faster than $.empty()
10583            menuInner.replaceChild(emptyMenu, menuInner.firstChild);
10584
10585            for (var i = 0, visibleElementsLen = elements.length; i < visibleElementsLen; i++) {
10586              menuFragment.appendChild(elements[i]);
10587            }
10588
10589            if (isVirtual === true) {
10590              marginTop = (that.selectpicker.view.position0 === 0 ? 0 : that.selectpicker.current.data[that.selectpicker.view.position0 - 1].position),
10591              marginBottom = (that.selectpicker.view.position1 > size - 1 ? 0 : that.selectpicker.current.data[size - 1].position - that.selectpicker.current.data[that.selectpicker.view.position1 - 1].position);
10592
10593              menuInner.firstChild.style.marginTop = marginTop + 'px';
10594              menuInner.firstChild.style.marginBottom = marginBottom + 'px';
10595            }
10596
10597            menuInner.firstChild.appendChild(menuFragment);
10598          }
10599        }
10600
10601        that.prevActiveIndex = that.activeIndex;
10602
10603        if (!that.options.liveSearch) {
10604          that.$menuInner.focus();
10605        } else if (isSearching && init) {
10606          var index = 0,
10607              newActive;
10608
10609          if (!that.selectpicker.view.canHighlight[index]) {
10610            index = 1 + that.selectpicker.view.canHighlight.slice(1).indexOf(true);
10611          }
10612
10613          newActive = that.selectpicker.view.visibleElements[index];
10614
10615          if (that.selectpicker.view.currentActive) {
10616            that.selectpicker.view.currentActive.classList.remove('active');
10617            if (that.selectpicker.view.currentActive.firstChild) that.selectpicker.view.currentActive.firstChild.classList.remove('active');
10618          }
10619
10620          if (newActive) {
10621            newActive.classList.add('active');
10622            if (newActive.firstChild) newActive.firstChild.classList.add('active');
10623          }
10624
10625          that.activeIndex = that.selectpicker.current.map.originalIndex[index];
10626        }
10627      }
10628
10629      $(window).off('resize.createView').on('resize.createView', function () {
10630        scroll(that.$menuInner[0].scrollTop);
10631      });
10632    },
10633
10634    createLi: function () {
10635      var that = this,
10636          mainElements = [],
10637          widestOption,
10638          availableOptionsCount = 0,
10639          widestOptionLength = 0,
10640          mainData = [],
10641          optID = 0,
10642          headerIndex = 0,
10643          liIndex = -1; // increment liIndex whenever a new <li> element is created to ensure newIndex is correct
10644
10645      if (!this.selectpicker.view.titleOption) this.selectpicker.view.titleOption = document.createElement('option');
10646
10647      var elementTemplates = {
10648          span: document.createElement('span'),
10649          subtext: document.createElement('small'),
10650          a: document.createElement('a'),
10651          li: document.createElement('li'),
10652          whitespace: document.createTextNode("\u00A0")
10653        },
10654        checkMark = elementTemplates.span.cloneNode(false),
10655        fragment = document.createDocumentFragment();
10656
10657      checkMark.className = that.options.iconBase + ' ' + that.options.tickIcon + ' check-mark';
10658      elementTemplates.a.appendChild(checkMark);
10659      elementTemplates.a.setAttribute('role', 'option');
10660
10661      elementTemplates.subtext.className = 'text-muted';
10662
10663      elementTemplates.text = elementTemplates.span.cloneNode(false);
10664      elementTemplates.text.className = 'text';
10665
10666      // Helper functions
10667      /**
10668       * @param content
10669       * @param [index]
10670       * @param [classes]
10671       * @param [optgroup]
10672       * @returns {HTMLElement}
10673       */
10674      var generateLI = function (content, index, classes, optgroup) {
10675        var li = elementTemplates.li.cloneNode(false);
10676
10677        if (content) {
10678          if (content.nodeType === 1 || content.nodeType === 11) {
10679            li.appendChild(content);
10680          } else {
10681            li.innerHTML = content;
10682          }
10683        }
10684
10685        if (typeof classes !== 'undefined' && '' !== classes) li.className = classes;
10686        if (typeof optgroup !== 'undefined' && null !== optgroup) li.classList.add('optgroup-' + optgroup);
10687
10688        return li;
10689      };
10690
10691      /**
10692       * @param text
10693       * @param [classes]
10694       * @param [inline]
10695       * @returns {string}
10696       */
10697      var generateA = function (text, classes, inline) {
10698        var a = elementTemplates.a.cloneNode(true);
10699
10700        if (text) {
10701          if (text.nodeType === 11) {
10702            a.appendChild(text);
10703          } else {
10704            a.insertAdjacentHTML('beforeend', text);
10705          }
10706        }
10707
10708        if (typeof classes !== 'undefined' & '' !== classes) a.className = classes;
10709        if (version.major === '4') a.classList.add('dropdown-item');
10710        if (inline) a.setAttribute('style', inline);
10711
10712        return a;
10713      };
10714
10715      var generateText = function (options) {
10716        var textElement = elementTemplates.text.cloneNode(false),
10717            optionSubtextElement,
10718            optionIconElement;
10719
10720        if (options.optionContent) {
10721          textElement.innerHTML = options.optionContent;
10722        } else {
10723          textElement.textContent = options.text;
10724
10725          if (options.optionIcon) {
10726            var whitespace = elementTemplates.whitespace.cloneNode(false);
10727
10728            optionIconElement = elementTemplates.span.cloneNode(false);
10729            optionIconElement.className = that.options.iconBase + ' ' + options.optionIcon;
10730
10731            fragment.appendChild(optionIconElement);
10732            fragment.appendChild(whitespace);
10733          }
10734
10735          if (options.optionSubtext) {
10736            optionSubtextElement = elementTemplates.subtext.cloneNode(false);
10737            optionSubtextElement.textContent = options.optionSubtext;
10738            textElement.appendChild(optionSubtextElement);
10739          }
10740        }
10741
10742        fragment.appendChild(textElement);
10743
10744        return fragment;
10745      };
10746
10747      var generateLabel = function (options) {
10748        var labelTextElement = elementTemplates.text.cloneNode(false),
10749            labelSubtextElement,
10750            labelIconElement;
10751
10752        labelTextElement.textContent = options.labelEscaped;
10753
10754        if (options.labelIcon) {
10755          var whitespace = elementTemplates.whitespace.cloneNode(false);
10756
10757          labelIconElement = elementTemplates.span.cloneNode(false);
10758          labelIconElement.className = that.options.iconBase + ' ' + options.labelIcon;
10759
10760          fragment.appendChild(labelIconElement);
10761          fragment.appendChild(whitespace);
10762        }
10763
10764        if (options.labelSubtext) {
10765          labelSubtextElement = elementTemplates.subtext.cloneNode(false);
10766          labelSubtextElement.textContent = options.labelSubtext;
10767          labelTextElement.appendChild(labelSubtextElement);
10768        }
10769
10770        fragment.appendChild(labelTextElement);
10771
10772        return fragment;
10773      }
10774
10775      if (this.options.title && !this.multiple) {
10776        // this option doesn't create a new <li> element, but does add a new option, so liIndex is decreased
10777        // since newIndex is recalculated on every refresh, liIndex needs to be decreased even if the titleOption is already appended
10778        liIndex--;
10779
10780        var element = this.$element[0],
10781            isSelected = false;
10782
10783        if (!this.selectpicker.view.titleOption.parentNode) {
10784          // Use native JS to prepend option (faster)
10785          this.selectpicker.view.titleOption.className = 'bs-title-option';
10786          this.selectpicker.view.titleOption.innerHTML = this.options.title;
10787          this.selectpicker.view.titleOption.value = '';
10788
10789          // Check if selected or data-selected attribute is already set on an option. If not, select the titleOption option.
10790          // the selected item may have been changed by user or programmatically before the bootstrap select plugin runs,
10791          // if so, the select will have the data-selected attribute
10792          var $opt = $(element.options[element.selectedIndex]);
10793          isSelected = $opt.attr('selected') === undefined && this.$element.data('selected') === undefined;
10794        }
10795
10796        element.insertBefore(this.selectpicker.view.titleOption, element.firstChild);
10797
10798        // Set selected *after* appending to select,
10799        // otherwise the option doesn't get selected in IE
10800        // set using selectedIndex, as setting the selected attr to true here doesn't work in IE11
10801        if (isSelected) element.selectedIndex = 0;
10802      }
10803
10804      var $selectOptions = this.$element.find('option');
10805
10806      $selectOptions.each(function (index) {
10807        var $this = $(this);
10808
10809        liIndex++;
10810
10811        if ($this.hasClass('bs-title-option')) return;
10812
10813        var thisData = $this.data();
10814
10815        // Get the class and text for the option
10816        var optionClass = this.className || '',
10817            inline = htmlEscape(this.style.cssText),
10818            optionContent = thisData.content,
10819            text = this.textContent,
10820            tokens = thisData.tokens,
10821            subtext = thisData.subtext,
10822            icon = thisData.icon,
10823            $parent = $this.parent(),
10824            parent = $parent[0],
10825            isOptgroup = parent.tagName === 'OPTGROUP',
10826            isOptgroupDisabled = isOptgroup && parent.disabled,
10827            isDisabled = this.disabled || isOptgroupDisabled,
10828            prevHiddenIndex,
10829            showDivider = this.previousElementSibling && this.previousElementSibling.tagName === 'OPTGROUP',
10830            textElement;
10831
10832        var parentData = $parent.data();
10833
10834        if (thisData.hidden === true || that.options.hideDisabled && (isDisabled && !isOptgroup || isOptgroupDisabled)) {
10835          // set prevHiddenIndex - the index of the first hidden option in a group of hidden options
10836          // used to determine whether or not a divider should be placed after an optgroup if there are
10837          // hidden options between the optgroup and the first visible option
10838          prevHiddenIndex = thisData.prevHiddenIndex;
10839          $this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
10840
10841          liIndex--;
10842
10843          // if previous element is not an optgroup
10844          if (!showDivider) {
10845            if (prevHiddenIndex !== undefined) {
10846              // select the element **before** the first hidden element in the group
10847              var prevHidden = $selectOptions[prevHiddenIndex].previousElementSibling;
10848              
10849              if (prevHidden && prevHidden.tagName === 'OPTGROUP' && !prevHidden.disabled) {
10850                showDivider = true;
10851              }
10852            }
10853          }
10854
10855          if (showDivider && mainData[mainData.length - 1].type !== 'divider') {
10856            liIndex++;
10857            mainElements.push(
10858              generateLI(
10859                false,
10860                null,
10861                classNames.DIVIDER,
10862                optID + 'div'
10863              )
10864            );
10865            mainData.push({
10866              type: 'divider',
10867              optID: optID,
10868              originalIndex: index
10869            });
10870          }
10871
10872          return;
10873        }
10874
10875        if (isOptgroup && thisData.divider !== true) {
10876          if (that.options.hideDisabled && isDisabled) {
10877            if (parentData.allOptionsDisabled === undefined) {
10878              var $options = $parent.children();
10879              $parent.data('allOptionsDisabled', $options.filter(':disabled').length === $options.length);
10880            }
10881
10882            if ($parent.data('allOptionsDisabled')) {
10883              liIndex--;
10884              return;
10885            }
10886          }
10887
10888          var optGroupClass = ' ' + parent.className || '';
10889
10890          if (!this.previousElementSibling) { // Is it the first option of the optgroup?
10891            optID += 1;
10892
10893            // Get the opt group label
10894            var label = parent.label,
10895                labelEscaped = htmlEscape(label),
10896                labelSubtext = parentData.subtext,
10897                labelIcon = parentData.icon;
10898
10899            if (index !== 0 && mainElements.length > 0) { // Is it NOT the first option of the select && are there elements in the dropdown?
10900              liIndex++;
10901              mainElements.push(
10902                generateLI(
10903                  false,
10904                  null,
10905                  classNames.DIVIDER,
10906                  optID + 'div'
10907                )
10908              );
10909              mainData.push({
10910                type: 'divider',
10911                optID: optID,
10912                originalIndex: index
10913              });
10914            }
10915            liIndex++;
10916
10917            var labelElement = generateLabel({
10918                  labelEscaped: labelEscaped,
10919                  labelSubtext: labelSubtext,
10920                  labelIcon: labelIcon
10921                });
10922
10923            mainElements.push(generateLI(labelElement, null, 'dropdown-header' + optGroupClass, optID));
10924            mainData.push({
10925              content: labelEscaped,
10926              subtext: labelSubtext,
10927              type: 'optgroup-label',
10928              optID: optID,
10929              originalIndex: index
10930            });
10931            
10932            headerIndex = liIndex - 1;
10933          }
10934
10935          if (that.options.hideDisabled && isDisabled || thisData.hidden === true) {
10936            liIndex--;
10937            return;
10938          }
10939
10940          textElement = generateText({
10941            text: text,
10942            optionContent: optionContent,
10943            optionSubtext: subtext,
10944            optionIcon: icon
10945          });
10946
10947          mainElements.push(generateLI(generateA(textElement, 'opt ' + optionClass + optGroupClass, inline), index, '', optID));
10948          mainData.push({
10949            content: text,
10950            subtext: subtext,
10951            tokens: tokens,
10952            type: 'option',
10953            optID: optID,
10954            headerIndex: headerIndex,
10955            lastIndex: headerIndex + parent.childElementCount,
10956            originalIndex: index
10957          });
10958
10959          availableOptionsCount++;
10960        } else if (thisData.divider === true) {
10961          mainElements.push(generateLI(false, index, 'divider'));
10962          mainData.push({
10963            type: 'divider',
10964            originalIndex: index
10965          });
10966        } else {
10967          // if previous element is not an optgroup and hideDisabled is true
10968          if (!showDivider && that.options.hideDisabled) {
10969            prevHiddenIndex = thisData.prevHiddenIndex;
10970
10971            if (prevHiddenIndex !== undefined) {
10972              // select the element **before** the first hidden element in the group
10973              var prevHidden = $selectOptions[prevHiddenIndex].previousElementSibling;
10974              
10975              if (prevHidden && prevHidden.tagName === 'OPTGROUP' && !prevHidden.disabled) {
10976                showDivider = true;
10977              }
10978            }
10979          }
10980
10981          if (showDivider && mainData[mainData.length - 1].type !== 'divider') {
10982            liIndex++;
10983            mainElements.push(
10984              generateLI(
10985                false,
10986                null,
10987                classNames.DIVIDER,
10988                optID + 'div'
10989              )
10990            );
10991            mainData.push({
10992              type: 'divider',
10993              optID: optID,
10994              originalIndex: index
10995            });
10996          }
10997
10998          textElement = generateText({
10999            text: text,
11000            optionContent: optionContent,
11001            optionSubtext: subtext,
11002            optionIcon: icon
11003          });
11004
11005          mainElements.push(generateLI(generateA(textElement, optionClass, inline), index));
11006          mainData.push({
11007            content: text,
11008            subtext: subtext,
11009            tokens: tokens,
11010            type: 'option',
11011            originalIndex: index
11012          });
11013
11014          availableOptionsCount++;
11015        }
11016
11017        that.selectpicker.main.map.newIndex[index] = liIndex;
11018        that.selectpicker.main.map.originalIndex[liIndex] = index;
11019
11020        // get the most recent option info added to mainData
11021        var _mainDataLast = mainData[mainData.length - 1];
11022
11023        _mainDataLast.disabled = isDisabled;
11024
11025        var combinedLength = 0;
11026
11027        // count the number of characters in the option - not perfect, but should work in most cases
11028        if (_mainDataLast.content) combinedLength += _mainDataLast.content.length;
11029        if (_mainDataLast.subtext) combinedLength += _mainDataLast.subtext.length;
11030        // if there is an icon, ensure this option's width is checked
11031        if (icon) combinedLength += 1;
11032
11033        if (combinedLength > widestOptionLength) {
11034          widestOptionLength = combinedLength;
11035
11036          // guess which option is the widest
11037          // use this when calculating menu width
11038          // not perfect, but it's fast, and the width will be updating accordingly when scrolling
11039          widestOption = mainElements[mainElements.length - 1];
11040        }
11041      });
11042
11043      this.selectpicker.main.elements = mainElements;
11044      this.selectpicker.main.data = mainData;
11045
11046      this.selectpicker.current = this.selectpicker.main;
11047
11048      this.selectpicker.view.widestOption = widestOption;
11049      this.selectpicker.view.availableOptionsCount = availableOptionsCount; // faster way to get # of available options without filter
11050    },
11051
11052    findLis: function () {
11053      return this.$menuInner.find('.inner > li');
11054    },
11055
11056    render: function () {
11057      var that = this,
11058          $selectOptions = this.$element.find('option'),
11059          selectedItems = [],
11060          selectedItemsInTitle = [];
11061
11062      this.togglePlaceholder();
11063
11064      this.tabIndex();
11065
11066      $selectOptions.each(function (index) {
11067        if (this.selected) {
11068          selectedItems.push(this);
11069
11070          if (selectedItemsInTitle.length < 100 && that.options.selectedTextFormat !== 'count') {
11071            if (that.options.hideDisabled && (this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled)) return;
11072
11073            var $this = $(this),
11074                thisData = $this.data(),
11075                icon = thisData.icon && that.options.showIcon ? '<i class="' + that.options.iconBase + ' ' + thisData.icon + '"></i> ' : '',
11076                subtext,
11077                titleItem;
11078
11079            if (that.options.showSubtext && thisData.subtext && !that.multiple) {
11080              subtext = ' <small class="text-muted">' + thisData.subtext + '</small>';
11081            } else {
11082              subtext = '';
11083            }
11084            if (typeof $this.attr('title') !== 'undefined') {
11085              titleItem = $this.attr('title');
11086            } else if (thisData.content && that.options.showContent) {
11087              titleItem = thisData.content.toString();
11088            } else {
11089              titleItem = icon + $this.html() + subtext;
11090            }
11091
11092            selectedItemsInTitle.push(titleItem);
11093          }
11094        }
11095      });
11096
11097      //Fixes issue in IE10 occurring when no default option is selected and at least one option is disabled
11098      //Convert all the values into a comma delimited string
11099      var title = !this.multiple ? selectedItemsInTitle[0] : selectedItemsInTitle.join(this.options.multipleSeparator);
11100
11101      // add ellipsis
11102      if (selectedItems.length > 100) title += '...';
11103
11104      //If this is multi select, and the selectText type is count, the show 1 of 2 selected etc..
11105      if (this.multiple && this.options.selectedTextFormat.indexOf('count') > -1) {
11106        var max = this.options.selectedTextFormat.split('>');
11107
11108        if ((max.length > 1 && selectedItems.length > max[1]) || (max.length === 1 && selectedItems.length >= 2)) {
11109          var totalCount = this.selectpicker.view.availableOptionsCount,
11110              tr8nText = (typeof this.options.countSelectedText === 'function') ? this.options.countSelectedText(selectedItems.length, totalCount) : this.options.countSelectedText;
11111
11112          title = tr8nText.replace('{0}', selectedItems.length.toString()).replace('{1}', totalCount.toString());
11113        }
11114      }
11115
11116      if (this.options.title == undefined) {
11117        this.options.title = this.$element.attr('title');
11118      }
11119
11120      if (this.options.selectedTextFormat == 'static') {
11121        title = this.options.title;
11122      }
11123
11124      //If we dont have a title, then use the default, or if nothing is set at all, use the not selected text
11125      if (!title) {
11126        title = typeof this.options.title !== 'undefined' ? this.options.title : this.options.noneSelectedText;
11127      }
11128
11129      //strip all HTML tags and trim the result, then unescape any escaped tags
11130      this.$button.attr('title', htmlUnescape($.trim(title.replace(/<[^>]*>?/g, ''))));
11131      this.$button.find('.filter-option-inner').html(title);
11132
11133      this.$element.trigger('rendered.bs.select');
11134    },
11135
11136    /**
11137     * @param [style]
11138     * @param [status]
11139     */
11140    setStyle: function (style, status) {
11141      if (this.$element.attr('class')) {
11142        this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi, ''));
11143      }
11144
11145      var buttonClass = style ? style : this.options.style;
11146
11147      if (status == 'add') {
11148        this.$button.addClass(buttonClass);
11149      } else if (status == 'remove') {
11150        this.$button.removeClass(buttonClass);
11151      } else {
11152        this.$button.removeClass(this.options.style);
11153        this.$button.addClass(buttonClass);
11154      }
11155    },
11156
11157    liHeight: function (refresh) {
11158      if (!refresh && (this.options.size === false || this.sizeInfo)) return;
11159
11160      if (!this.sizeInfo) this.sizeInfo = {};
11161
11162      var newElement = document.createElement('div'),
11163          menu = document.createElement('div'),
11164          menuInner = document.createElement('div'),
11165          menuInnerInner = document.createElement('ul'),
11166          divider = document.createElement('li'),
11167          dropdownHeader = document.createElement('li'),
11168          li = document.createElement('li'),
11169          a = document.createElement('a'),
11170          text = document.createElement('span'),
11171          header = this.options.header && this.$menu.find('.popover-title').length > 0 ? this.$menu.find('.popover-title')[0].cloneNode(true) : null,
11172          search = this.options.liveSearch ? document.createElement('div') : null,
11173          actions = this.options.actionsBox && this.multiple && this.$menu.find('.bs-actionsbox').length > 0 ? this.$menu.find('.bs-actionsbox')[0].cloneNode(true) : null,
11174          doneButton = this.options.doneButton && this.multiple && this.$menu.find('.bs-donebutton').length > 0 ? this.$menu.find('.bs-donebutton')[0].cloneNode(true) : null;
11175
11176      this.sizeInfo.selectWidth = this.$newElement[0].offsetWidth;
11177
11178      text.className = 'text';
11179      a.className = 'dropdown-item';
11180      newElement.className = this.$menu[0].parentNode.className + ' ' + classNames.SHOW;
11181      newElement.style.width = this.sizeInfo.selectWidth + 'px';
11182      menu.className = 'dropdown-menu ' + classNames.SHOW;
11183      menuInner.className = 'inner ' + classNames.SHOW;
11184      menuInnerInner.className = 'dropdown-menu inner ' + (version.major === '4' ? classNames.SHOW : '');
11185      divider.className = classNames.DIVIDER;
11186      dropdownHeader.className = 'dropdown-header';
11187
11188      text.appendChild(document.createTextNode('Inner text'));
vendor: 9,469 bytes, lines 11189-11391
11189      a.appendChild(text);
11190      li.appendChild(a);
11191      dropdownHeader.appendChild(text.cloneNode(true));
11192
11193      if (this.selectpicker.view.widestOption) {
11194        menuInnerInner.appendChild(this.selectpicker.view.widestOption.cloneNode(true));
11195      }
11196
11197      menuInnerInner.appendChild(li);
11198      menuInnerInner.appendChild(divider);
11199      menuInnerInner.appendChild(dropdownHeader);
11200      if (header) menu.appendChild(header);
11201      if (search) {
11202        var input = document.createElement('input');
11203        search.className = 'bs-searchbox';
11204        input.className = 'form-control';
11205        search.appendChild(input);
11206        menu.appendChild(search);
11207      }
11208      if (actions) menu.appendChild(actions);
11209      menuInner.appendChild(menuInnerInner);
11210      menu.appendChild(menuInner);
11211      if (doneButton) menu.appendChild(doneButton);
11212      newElement.appendChild(menu);
11213
11214      document.body.appendChild(newElement);
11215
11216      var liHeight = a.offsetHeight,
11217          dropdownHeaderHeight = dropdownHeader ? dropdownHeader.offsetHeight : 0,
11218          headerHeight = header ? header.offsetHeight : 0,
11219          searchHeight = search ? search.offsetHeight : 0,
11220          actionsHeight = actions ? actions.offsetHeight : 0,
11221          doneButtonHeight = doneButton ? doneButton.offsetHeight : 0,
11222          dividerHeight = $(divider).outerHeight(true),
11223          // fall back to jQuery if getComputedStyle is not supported
11224          menuStyle = window.getComputedStyle ? window.getComputedStyle(menu) : false,
11225          menuWidth = menu.offsetWidth,
11226          $menu = menuStyle ? null : $(menu),
11227          menuPadding = {
11228            vert: toInteger(menuStyle ? menuStyle.paddingTop : $menu.css('paddingTop')) +
11229                  toInteger(menuStyle ? menuStyle.paddingBottom : $menu.css('paddingBottom')) +
11230                  toInteger(menuStyle ? menuStyle.borderTopWidth : $menu.css('borderTopWidth')) +
11231                  toInteger(menuStyle ? menuStyle.borderBottomWidth : $menu.css('borderBottomWidth')),
11232            horiz: toInteger(menuStyle ? menuStyle.paddingLeft : $menu.css('paddingLeft')) +
11233                  toInteger(menuStyle ? menuStyle.paddingRight : $menu.css('paddingRight')) +
11234                  toInteger(menuStyle ? menuStyle.borderLeftWidth : $menu.css('borderLeftWidth')) +
11235                  toInteger(menuStyle ? menuStyle.borderRightWidth : $menu.css('borderRightWidth'))
11236          },
11237          menuExtras =  {
11238            vert: menuPadding.vert +
11239                  toInteger(menuStyle ? menuStyle.marginTop : $menu.css('marginTop')) +
11240                  toInteger(menuStyle ? menuStyle.marginBottom : $menu.css('marginBottom')) + 2,
11241            horiz: menuPadding.horiz +
11242                  toInteger(menuStyle ? menuStyle.marginLeft : $menu.css('marginLeft')) +
11243                  toInteger(menuStyle ? menuStyle.marginRight : $menu.css('marginRight')) + 2
11244          },
11245          scrollBarWidth;
11246
11247      menuInner.style.overflowY = 'scroll';
11248
11249      scrollBarWidth = menu.offsetWidth - menuWidth;
11250
11251      document.body.removeChild(newElement);
11252
11253      this.sizeInfo.liHeight = liHeight;
11254      this.sizeInfo.dropdownHeaderHeight = dropdownHeaderHeight;
11255      this.sizeInfo.headerHeight = headerHeight;
11256      this.sizeInfo.searchHeight = searchHeight;
11257      this.sizeInfo.actionsHeight = actionsHeight;
11258      this.sizeInfo.doneButtonHeight = doneButtonHeight;
11259      this.sizeInfo.dividerHeight = dividerHeight;
11260      this.sizeInfo.menuPadding = menuPadding;
11261      this.sizeInfo.menuExtras = menuExtras;
11262      this.sizeInfo.menuWidth = menuWidth;
11263      this.sizeInfo.totalMenuWidth = this.sizeInfo.menuWidth;
11264      this.sizeInfo.scrollBarWidth = scrollBarWidth;
11265      this.sizeInfo.selectHeight = this.$newElement[0].offsetHeight;
11266
11267      this.setPositionData();
11268    },
11269
11270    getSelectPosition: function () {
11271      var that = this,
11272          $window = $(window),
11273          pos = that.$newElement.offset(),
11274          $container = $(that.options.container),
11275          containerPos;
11276
11277      if (that.options.container && !$container.is('body')) {
11278        containerPos = $container.offset();
11279        containerPos.top += parseInt($container.css('borderTopWidth'));
11280        containerPos.left += parseInt($container.css('borderLeftWidth'));
11281      } else {
11282        containerPos = { top: 0, left: 0 };
11283      }
11284
11285      var winPad = that.options.windowPadding;
11286
11287      this.sizeInfo.selectOffsetTop = pos.top - containerPos.top - $window.scrollTop();
11288      this.sizeInfo.selectOffsetBot = $window.height() - this.sizeInfo.selectOffsetTop - this.sizeInfo['selectHeight'] - containerPos.top - winPad[2];
11289      this.sizeInfo.selectOffsetLeft = pos.left - containerPos.left - $window.scrollLeft();
11290      this.sizeInfo.selectOffsetRight = $window.width() - this.sizeInfo.selectOffsetLeft - this.sizeInfo['selectWidth'] - containerPos.left - winPad[1];
11291      this.sizeInfo.selectOffsetTop -= winPad[0];
11292      this.sizeInfo.selectOffsetLeft -= winPad[3];
11293    },
11294
11295    setMenuSize: function (isAuto) {
11296      this.getSelectPosition();
11297
11298      var selectWidth = this.sizeInfo['selectWidth'],
11299          liHeight = this.sizeInfo['liHeight'],
11300          headerHeight = this.sizeInfo['headerHeight'],
11301          searchHeight = this.sizeInfo['searchHeight'],
11302          actionsHeight = this.sizeInfo['actionsHeight'],
11303          doneButtonHeight = this.sizeInfo['doneButtonHeight'],
11304          divHeight = this.sizeInfo['dividerHeight'],
11305          menuPadding = this.sizeInfo['menuPadding'],
11306          menuInnerHeight,
11307          menuHeight,
11308          divLength = 0,
11309          minHeight,
11310          _minHeight,
11311          maxHeight,
11312          menuInnerMinHeight,
11313          estimate;
11314
11315      if (this.options.dropupAuto) {
11316        // Get the estimated height of the menu without scrollbars.
11317        // This is useful for smaller menus, where there might be plenty of room
11318        // below the button without setting dropup, but we can't know
11319        // the exact height of the menu until createView is called later
11320        estimate = liHeight * this.selectpicker.current.elements.length + menuPadding.vert;
11321        this.$newElement.toggleClass(classNames.DROPUP, this.sizeInfo.selectOffsetTop - this.sizeInfo.selectOffsetBot > this.sizeInfo.menuExtras.vert && estimate + this.sizeInfo.menuExtras.vert + 50 > this.sizeInfo.selectOffsetBot);
11322      }
11323
11324      if (this.options.size === 'auto') {
11325        _minHeight = this.selectpicker.current.elements.length > 3 ? this.sizeInfo.liHeight * 3 + this.sizeInfo.menuExtras.vert - 2 : 0;
11326        menuHeight = this.sizeInfo.selectOffsetBot - this.sizeInfo.menuExtras.vert;
11327        minHeight = _minHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight;
11328        menuInnerMinHeight = Math.max(_minHeight - menuPadding.vert, 0);
11329
11330        if (this.$newElement.hasClass(classNames.DROPUP)) {
11331          menuHeight = this.sizeInfo.selectOffsetTop - this.sizeInfo.menuExtras.vert;
11332        }
11333
11334        maxHeight = menuHeight;
11335        menuInnerHeight = menuHeight - headerHeight - searchHeight - actionsHeight - doneButtonHeight - menuPadding.vert;
11336      } else if (this.options.size && this.options.size != 'auto' && this.selectpicker.current.elements.length > this.options.size) {
11337        for (var i = 0; i < this.options.size; i++) {
11338          if (this.selectpicker.current.data[i].type === 'divider') divLength++;
11339        }
11340
11341        menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding.vert;
11342        menuInnerHeight = menuHeight - menuPadding.vert;
11343        maxHeight = menuHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight;
11344        minHeight = menuInnerMinHeight = '';
11345      }
11346
11347      if (this.options.dropdownAlignRight === 'auto') {
11348        this.$menu.toggleClass(classNames.MENURIGHT, this.sizeInfo.selectOffsetLeft > this.sizeInfo.selectOffsetRight && this.sizeInfo.selectOffsetRight < (this.$menu[0].offsetWidth - selectWidth));
11349      }
11350
11351      this.$menu.css({
11352        'max-height': maxHeight + 'px',
11353        'overflow': 'hidden',
11354        'min-height': minHeight + 'px'
11355      });
11356
11357      this.$menuInner.css({
11358        'max-height': menuInnerHeight + 'px',
11359        'overflow-y': 'auto',
11360        'min-height': menuInnerMinHeight + 'px'
11361      });
11362
11363      this.sizeInfo['menuInnerHeight'] = menuInnerHeight;
11364
11365      if (this.selectpicker.current.data.length && this.selectpicker.current.data[this.selectpicker.current.data.length - 1].position > this.sizeInfo.menuInnerHeight) {
11366        this.sizeInfo.hasScrollBar = true;
11367        this.sizeInfo.totalMenuWidth = this.sizeInfo.menuWidth + this.sizeInfo.scrollBarWidth;
11368
11369        this.$menu.css('min-width', this.sizeInfo.totalMenuWidth);
11370      }
11371
11372      if (this.dropdown) this.dropdown._popper.update();
11373    },
11374
11375    setSize: function (refresh) {
11376      this.liHeight(refresh);
11377
11378      if (this.options.header) this.$menu.css('padding-top', 0);
11379      if (this.options.size === false) return;
11380
11381      var that = this,
11382          $window = $(window),
11383          selectedIndex,
11384          offset = 0;
11385
11386      this.setMenuSize();
11387
11388      if (this.options.size === 'auto') {
11389        this.$searchbox.off('input.setMenuSize propertychange.setMenuSize').on('input.setMenuSize propertychange.setMenuSize', function() {
11390          return that.setMenuSize();
11391        });
11392        $window.off('resize.setMenuSize scroll.setMenuSize').on('resize.setMenuSize scroll.setMenuSize', function() {
11393          return that.setMenuSize();
11394        });
11395      } else if (this.options.size && this.options.size != 'auto' && this.selectpicker.current.elements.length > this.options.size) {
11396        this.$searchbox.off('input.setMenuSize propertychange.setMenuSize');
11397        $window.off('resize.setMenuSize scroll.setMenuSize');
11398      }
11399
11400      if (refresh) {
11401        offset = this.$menuInner[0].scrollTop;
11402      } else if (!that.multiple) {
11403        selectedIndex = that.selectpicker.main.map.newIndex[that.$element[0].selectedIndex];
11404
11405        if (typeof selectedIndex === 'number' && that.options.size !== false) {
11406          offset = that.sizeInfo.liHeight * selectedIndex;
11407          offset = offset - (that.sizeInfo.menuInnerHeight / 2) + (that.sizeInfo.liHeight / 2);
11408        }
11409      }
11410
11411      that.createView(false, offset);
11412    },
11413
11414    setWidth: function () {
11415      var that = this;
11416
11417      if (this.options.width === 'auto') {
11418        requestAnimationFrame(function() {
11419          that.$menu.css('min-width', '0');
11420          that.liHeight();
11421          that.setMenuSize();
11422
11423          // Get correct width if element is hidden
11424          var $selectClone = that.$newElement.clone().appendTo('body'),
11425              btnWidth = $selectClone.css('width', 'auto').children('button').outerWidth();
11426
11427          $selectClone.remove();
11428
11429          // Set width to whatever's larger, button title or longest option
11430          that.sizeInfo.selectWidth = Math.max(that.sizeInfo.totalMenuWidth, btnWidth);
11431          that.$newElement.css('width', that.sizeInfo.selectWidth + 'px');
11432        });
11433      } else if (this.options.width === 'fit') {
11434        // Remove inline min-width so width can be changed from 'auto'
11435        this.$menu.css('min-width', '');
11436        this.$newElement.css('width', '').addClass('fit-width');
11437      } else if (this.options.width) {
11438        // Remove inline min-width so width can be changed from 'auto'
11439        this.$menu.css('min-width', '');
11440        this.$newElement.css('width', this.options.width);
11441      } else {
11442        // Remove inline min-width/width so width can be changed
11443        this.$menu.css('min-width', '');
11444        this.$newElement.css('width', '');
11445      }
11446      // Remove fit-width class if width is changed programmatically
11447      if (this.$newElement.hasClass('fit-width') && this.options.width !== 'fit') {
11448        this.$newElement.removeClass('fit-width');
11449      }
11450    },
11451
11452    selectPosition: function () {
11453      this.$bsContainer = $('<div class="bs-container" />');
11454
11455      var that = this,
11456          $container = $(this.options.container),
11457          pos,
11458          containerPos,
11459          actualHeight,
11460          getPlacement = function ($element) {
11461            var containerPosition = {};
11462
11463            that.$bsContainer.addClass($element.attr('class').replace(/form-control|fit-width/gi, '')).toggleClass(classNames.DROPUP, $element.hasClass(classNames.DROPUP));
11464            pos = $element.offset();
11465
11466            if (!$container.is('body')) {
11467              containerPos = $container.offset();
11468              containerPos.top += parseInt($container.css('borderTopWidth')) - $container.scrollTop();
11469              containerPos.left += parseInt($container.css('borderLeftWidth')) - $container.scrollLeft();
11470            } else {
11471              containerPos = { top: 0, left: 0 };
11472            }
11473
11474            actualHeight = $element.hasClass(classNames.DROPUP) ? 0 : $element[0].offsetHeight;
11475
11476            // Bootstrap 4+ uses Popper for menu positioning
11477            if (version.major < 4) {
11478              containerPosition['top'] = pos.top - containerPos.top + actualHeight;
11479              containerPosition['left'] = pos.left - containerPos.left;
11480            }
11481
11482            containerPosition['width'] = $element[0].offsetWidth;
11483
11484            that.$bsContainer.css(containerPosition);
11485          };
11486
11487      this.$button.on('click.bs.dropdown.data-api', function () {
11488        if (that.isDisabled()) {
11489          return;
11490        }
11491
11492        getPlacement(that.$newElement);
11493
11494        that.$bsContainer
11495          .appendTo(that.options.container)
11496          .toggleClass(classNames.SHOW, !that.$button.hasClass(classNames.SHOW))
11497          .append(that.$menu);
11498      });
11499
11500      $(window).on('resize scroll', function () {
11501        getPlacement(that.$newElement);
11502      });
11503
11504      this.$element.on('hide.bs.select', function () {
11505        that.$menu.data('height', that.$menu.height());
11506        that.$bsContainer.detach();
11507      });
11508    },
11509
11510    setOptionStatus: function () {
11511      var that = this,
11512          $selectOptions = this.$element.find('option');
11513
11514      that.noScroll = false;
11515
11516      if (that.selectpicker.view.visibleElements && that.selectpicker.view.visibleElements.length) {
11517        for (var i = 0; i < that.selectpicker.view.visibleElements.length; i++) {
11518          var index = that.selectpicker.current.map.originalIndex[i + that.selectpicker.view.position0], // faster than $(li).data('originalIndex')
11519              option = $selectOptions[index];
11520
11521          if (option) {
11522            var liIndex = this.selectpicker.main.map.newIndex[index],
11523                li = this.selectpicker.main.elements[liIndex];
11524
11525            that.setDisabled(
11526              index,
11527              option.disabled || option.parentNode.tagName === 'OPTGROUP' && option.parentNode.disabled,
11528              liIndex,
11529              li
11530            );
11531
11532            that.setSelected(
11533              index,
11534              option.selected,
11535              liIndex,
11536              li
11537            );
11538          }
11539        }
11540      }
11541    },
11542
11543    /**
11544     * @param {number} index - the index of the option that is being changed
11545     * @param {boolean} selected - true if the option is being selected, false if being deselected
11546     */
11547    setSelected: function (index, selected, liIndex, li) {
11548      var activeIndexIsSet = this.activeIndex !== undefined,
11549          thisIsActive = this.activeIndex === index,
11550          prevActiveIndex,
11551          prevActive,
11552          a,
11553          keepActive = thisIsActive || selected && !this.multiple && !activeIndexIsSet;
11554
11555      if (!liIndex) liIndex = this.selectpicker.main.map.newIndex[index];
11556      if (!li) li = this.selectpicker.main.elements[liIndex];
11557
11558      a = li.firstChild;
11559
11560      if (selected) {
11561        this.selectedIndex = index;
11562      }
11563
11564      li.classList.toggle('selected', selected);
11565      li.classList.toggle('active', keepActive);
11566
11567      if (keepActive) {
11568        this.selectpicker.view.currentActive = li;
11569        this.activeIndex = index
11570      }
11571
11572      if (a) {
11573        a.classList.toggle('selected', selected);
11574        a.classList.toggle('active', keepActive);
11575        a.setAttribute('aria-selected', selected);
11576      }
11577
11578      if (!keepActive) {
11579        if (!activeIndexIsSet && selected && this.prevActiveIndex) {
11580          prevActiveIndex = this.selectpicker.main.map.newIndex[this.prevActiveIndex];
11581          prevActive = this.selectpicker.main.elements[prevActiveIndex];
11582
11583          prevActive.classList.remove('active');
11584          if (prevActive.firstChild) prevActive.firstChild.classList.remove('active');
11585        }
11586      }
11587    },
11588
11589    /**
11590     * @param {number} index - the index of the option that is being disabled
11591     * @param {boolean} disabled - true if the option is being disabled, false if being enabled
11592     */
11593    setDisabled: function (index, disabled, liIndex, li) {
11594      var a;
11595
11596      if (!liIndex) liIndex = this.selectpicker.main.map.newIndex[index];
11597      if (!li) li = this.selectpicker.main.elements[liIndex];
11598
11599      a = li.firstChild;
11600
11601      li.classList.toggle(classNames.DISABLED, disabled);
11602
11603      if (a) {
11604        if (version.major === '4') a.classList.toggle(classNames.DISABLED, disabled);
11605
11606        a.setAttribute('aria-disabled', disabled);
11607
11608        if (disabled) {
11609          a.setAttribute('tabindex', -1);
11610        } else {
11611          a.setAttribute('tabindex', 0);
11612        }
11613      }
11614    },
11615
11616    isDisabled: function () {
11617      return this.$element[0].disabled;
11618    },
11619
11620    checkDisabled: function () {
11621      var that = this;
11622
11623      if (this.isDisabled()) {
11624        this.$newElement.addClass(classNames.DISABLED);
11625        this.$button.addClass(classNames.DISABLED).attr('tabindex', -1).attr('aria-disabled', true);
11626      } else {
11627        if (this.$button.hasClass(classNames.DISABLED)) {
11628          this.$newElement.removeClass(classNames.DISABLED);
11629          this.$button.removeClass(classNames.DISABLED).attr('aria-disabled', false);
11630        }
11631
11632        if (this.$button.attr('tabindex') == -1 && !this.$element.data('tabindex')) {
11633          this.$button.removeAttr('tabindex');
11634        }
11635      }
11636
11637      this.$button.click(function () {
11638        return !that.isDisabled();
11639      });
11640    },
11641
11642    togglePlaceholder: function () {
11643      // much faster than calling $.val()
11644      var element = this.$element[0],
11645          selectedIndex = element.selectedIndex,
11646          nothingSelected = selectedIndex === -1;
11647
11648      if (!nothingSelected && !element.options[selectedIndex].value) nothingSelected = true;
11649
11650      this.$button.toggleClass('bs-placeholder', nothingSelected);
11651    },
11652
11653    tabIndex: function () {
11654      if (this.$element.data('tabindex') !== this.$element.attr('tabindex') && 
11655        (this.$element.attr('tabindex') !== -98 && this.$element.attr('tabindex') !== '-98')) {
11656        this.$element.data('tabindex', this.$element.attr('tabindex'));
11657        this.$button.attr('tabindex', this.$element.data('tabindex'));
11658      }
11659
11660      this.$element.attr('tabindex', -98);
11661    },
11662
11663    clickListener: function () {
11664      var that = this,
11665          $document = $(document);
11666
11667      $document.data('spaceSelect', false);
11668
11669      this.$button.on('keyup', function (e) {
11670        if (/(32)/.test(e.keyCode.toString(10)) && $document.data('spaceSelect')) {
11671            e.preventDefault();
11672            $document.data('spaceSelect', false);
11673        }
11674      });
11675
11676      this.$newElement.on('show.bs.dropdown', function() {
11677        if (version.major > 3 && !that.dropdown) {
11678          that.dropdown = that.$button.data('bs.dropdown');
11679          that.dropdown._menu = that.$menu[0];
11680        }
11681      });
11682
11683      this.$button.on('click.bs.dropdown.data-api', function () {
11684        if (!that.$newElement.hasClass(classNames.SHOW)) {
11685          that.setSize();
11686        }
11687      });
11688
11689      this.$element.on('shown.bs.select', function () {
11690        if (that.$menuInner[0].scrollTop !== that.selectpicker.view.scrollTop) {
11691          that.$menuInner[0].scrollTop = that.selectpicker.view.scrollTop;
11692        }
11693
11694        if (that.options.liveSearch) {
11695          that.$searchbox.focus();
11696        } else {
11697          that.$menuInner.focus();
11698        }
11699      });
11700
11701      this.$menuInner.on('click', 'li a', function (e, retainActive) {
11702        var $this = $(this),
11703            position0 = that.isVirtual() ? that.selectpicker.view.position0 : 0,
11704            clickedIndex = that.selectpicker.current.map.originalIndex[$this.parent().index() + position0],
11705            prevValue = that.$element.val(),
11706            prevIndex = that.$element.prop('selectedIndex'),
11707            triggerChange = true;
11708
11709        // Don't close on multi choice menu
11710        if (that.multiple && that.options.maxOptions !== 1) {
11711          e.stopPropagation();
11712        }
11713
11714        e.preventDefault();
11715
11716        //Don't run if we have been disabled
11717        if (!that.isDisabled() && !$this.parent().hasClass(classNames.DISABLED)) {
11718          var $options = that.$element.find('option'),
11719              $option = $options.eq(clickedIndex),
11720              state = $option.prop('selected'),
11721              $optgroup = $option.parent('optgroup'),
11722              maxOptions = that.options.maxOptions,
11723              maxOptionsGrp = $optgroup.data('maxOptions') || false;
11724
11725          if (!that.multiple) { // Deselect all others if not multi select box
11726            $options.prop('selected', false);
11727            $option.prop('selected', true);
11728            that.setSelected(clickedIndex, true);
11729          } else { // Toggle the one we have chosen if we are multi select.
11730            $option.prop('selected', !state);
11731
11732            if (clickedIndex === that.activeIndex) retainActive = true;
11733
11734            if (!retainActive) {
11735              that.prevActiveIndex = that.activeIndex;
11736              that.activeIndex = undefined;
11737            }
11738
11739            that.setSelected(clickedIndex, !state);
11740            $this.blur();
11741
11742            if (maxOptions !== false || maxOptionsGrp !== false) {
11743              var maxReached = maxOptions < $options.filter(':selected').length,
11744                  maxReachedGrp = maxOptionsGrp < $optgroup.find('option:selected').length;
11745
11746              if ((maxOptions && maxReached) || (maxOptionsGrp && maxReachedGrp)) {
11747                if (maxOptions && maxOptions == 1) {
11748                  $options.prop('selected', false);
11749                  $option.prop('selected', true);
11750                  that.$menuInner.find('.selected').removeClass('selected');
11751                  that.setSelected(clickedIndex, true);
11752                } else if (maxOptionsGrp && maxOptionsGrp == 1) {
11753                  $optgroup.find('option:selected').prop('selected', false);
11754                  $option.prop('selected', true);
11755                  var optgroupID = that.selectpicker.current.data[$this.parent().index() + that.selectpicker.view.position0].optID;
11756                  that.$menuInner.find('.optgroup-' + optgroupID).removeClass('selected');
11757                  that.setSelected(clickedIndex, true);
11758                } else {
11759                  var maxOptionsText = typeof that.options.maxOptionsText === 'string' ? [that.options.maxOptionsText, that.options.maxOptionsText] : that.options.maxOptionsText,
11760                      maxOptionsArr = typeof maxOptionsText === 'function' ? maxOptionsText(maxOptions, maxOptionsGrp) : maxOptionsText,
11761                      maxTxt = maxOptionsArr[0].replace('{n}', maxOptions),
11762                      maxTxtGrp = maxOptionsArr[1].replace('{n}', maxOptionsGrp),
11763                      $notify = $('<div class="notify"></div>');
11764                  // If {var} is set in array, replace it
11765                  /** @deprecated */
11766                  if (maxOptionsArr[2]) {
11767                    maxTxt = maxTxt.replace('{var}', maxOptionsArr[2][maxOptions > 1 ? 0 : 1]);
11768                    maxTxtGrp = maxTxtGrp.replace('{var}', maxOptionsArr[2][maxOptionsGrp > 1 ? 0 : 1]);
11769                  }
11770
11771                  $option.prop('selected', false);
11772
11773                  that.$menu.append($notify);
11774
11775                  if (maxOptions && maxReached) {
11776                    $notify.append($('<div>' + maxTxt + '</div>'));
11777                    triggerChange = false;
11778                    that.$element.trigger('maxReached.bs.select');
11779                  }
11780
11781                  if (maxOptionsGrp && maxReachedGrp) {
11782                    $notify.append($('<div>' + maxTxtGrp + '</div>'));
11783                    triggerChange = false;
11784                    that.$element.trigger('maxReachedGrp.bs.select');
11785                  }
11786
11787                  setTimeout(function () {
11788                    that.setSelected(clickedIndex, false);
11789                  }, 10);
11790
11791                  $notify.delay(750).fadeOut(300, function () {
11792                    $(this).remove();
11793                  });
11794                }
11795              }
11796            }
11797          }
11798
11799          if (!that.multiple || (that.multiple && that.options.maxOptions === 1)) {
11800            that.$button.focus();
11801          } else if (that.options.liveSearch) {
11802            that.$searchbox.focus();
11803          }
11804
11805          // Trigger select 'change'
11806          if (triggerChange) {
11807            if ((prevValue != that.$element.val() && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) {
11808              // $option.prop('selected') is current option state (selected/unselected). state is previous option state.
11809              changed_arguments = [clickedIndex, $option.prop('selected'), state];
11810              that.$element
11811                .triggerNative('change');
11812            }
11813          }
11814        }
11815      });
11816
11817      this.$menu.on('click', 'li.' + classNames.DISABLED + ' a, .popover-title, .popover-title :not(.close)', function (e) {
11818        if (e.currentTarget == this) {
11819          e.preventDefault();
11820          e.stopPropagation();
11821          if (that.options.liveSearch && !$(e.target).hasClass('close')) {
11822            that.$searchbox.focus();
11823          } else {
11824            that.$button.focus();
11825          }
11826        }
11827      });
11828
11829      this.$menuInner.on('click', '.divider, .dropdown-header', function (e) {
11830        e.preventDefault();
11831        e.stopPropagation();
11832        if (that.options.liveSearch) {
11833          that.$searchbox.focus();
11834        } else {
11835          that.$button.focus();
11836        }
11837      });
11838
11839      this.$menu.on('click', '.popover-title .close', function () {
11840        that.$button.click();
11841      });
11842
11843      this.$searchbox.on('click', function (e) {
11844        e.stopPropagation();
11845      });
11846
11847      this.$menu.on('click', '.actions-btn', function (e) {
11848        if (that.options.liveSearch) {
11849          that.$searchbox.focus();
11850        } else {
11851          that.$button.focus();
11852        }
11853
11854        e.preventDefault();
11855        e.stopPropagation();
11856
11857        if ($(this).hasClass('bs-select-all')) {
11858          that.selectAll();
11859        } else {
11860          that.deselectAll();
11861        }
11862      });
11863
11864      this.$element.on({
11865        'change': function () {
11866          that.render();
11867          that.$element.trigger('changed.bs.select', changed_arguments);
11868          changed_arguments = null;
11869        },
11870        'focus': function () {
11871          that.$button.focus();
11872        }
11873      });
11874    },
11875
11876    liveSearchListener: function () {
11877      var that = this,
11878          no_results = document.createElement('li');
11879
11880      this.$button.on('click.bs.dropdown.data-api', function () {
11881        if (!!that.$searchbox.val()) {
11882          that.$searchbox.val('');
11883        }
11884      });
11885
11886      this.$searchbox.on('click.bs.dropdown.data-api focus.bs.dropdown.data-api touchend.bs.dropdown.data-api', function (e) {
11887        e.stopPropagation();
11888      });
11889
11890      this.$searchbox.on('input propertychange', function () {
11891        var searchValue = that.$searchbox.val();
11892        
11893        that.selectpicker.search.map.newIndex = {};
11894        that.selectpicker.search.map.originalIndex = {};
11895        that.selectpicker.search.elements = [];
11896        that.selectpicker.search.data = [];
11897
11898        if (searchValue) {
11899          var i,
11900              searchMatch = [],
11901              q = searchValue.toUpperCase(),
11902              cache = {},
11903              cacheArr = [],
11904              searchStyle = that._searchStyle(),
11905              normalizeSearch = that.options.liveSearchNormalize;
11906
11907          that._$lisSelected = that.$menuInner.find('.selected');
11908
11909          for (var i = 0; i < that.selectpicker.main.data.length; i++) {
11910            var li = that.selectpicker.main.data[i];
11911
11912            if (!cache[i]) {
11913              cache[i] = stringSearch(li, q, searchStyle, normalizeSearch);
11914            }
11915
11916            if (cache[i] && li.headerIndex !== undefined && cacheArr.indexOf(li.headerIndex) === -1) {
11917              if (li.headerIndex > 0) {
11918                cache[li.headerIndex - 1] = true;
11919                cacheArr.push(li.headerIndex - 1);
11920              }
11921
11922              cache[li.headerIndex] = true;
11923              cacheArr.push(li.headerIndex);
11924              
11925              cache[li.lastIndex + 1] = true;
11926            }
11927
11928            if (cache[i] && li.type !== 'optgroup-label') cacheArr.push(i);
11929          }
11930
11931          for (var i = 0, cacheLen = cacheArr.length; i < cacheLen; i++) {
11932            var index = cacheArr[i],
11933                prevIndex = cacheArr[i - 1],
11934                li = that.selectpicker.main.data[index],
11935                liPrev = that.selectpicker.main.data[prevIndex];
11936                
11937            if ( li.type !== 'divider' || ( li.type === 'divider' && liPrev && liPrev.type !== 'divider' && cacheLen - 1 !== i ) ) {
11938              that.selectpicker.search.data.push(li);
11939              searchMatch.push(that.selectpicker.main.elements[index]);
11940              that.selectpicker.search.map.newIndex[li.originalIndex] = searchMatch.length - 1;
11941              that.selectpicker.search.map.originalIndex[searchMatch.length - 1] = li.originalIndex;
11942            }
11943          }
11944
11945          that.activeIndex = undefined;
11946          that.noScroll = true;
11947          that.$menuInner.scrollTop(0);
11948          that.selectpicker.search.elements = searchMatch;
11949          that.createView(true);
11950
11951          if (!searchMatch.length) {
11952            no_results.className = 'no-results';
11953            no_results.innerHTML = that.options.noneResultsText.replace('{0}', '"' + htmlEscape(searchValue) + '"');
11954            that.$menuInner[0].firstChild.appendChild(no_results);
11955          }
11956        } else {
11957          that.$menuInner.scrollTop(0);
11958          that.createView(false);
11959        }
11960      });
11961    },
11962
11963    _searchStyle: function () {
11964      return this.options.liveSearchStyle || 'contains';
11965    },
11966
11967    val: function (value) {
11968      if (typeof value !== 'undefined') {
11969        this.$element
11970          .val(value)
11971          .triggerNative('change');
11972
11973        return this.$element;
11974      } else {
11975        return this.$element.val();
11976      }
11977    },
11978
11979    changeAll: function (status) {
11980      if (!this.multiple) return;
11981      if (typeof status === 'undefined') status = true;
11982
11983      var $selectOptions = this.$element.find('option'),
11984          previousSelected = 0,
11985          currentSelected = 0;
11986
11987      for (var i = 0; i < this.selectpicker.current.elements.length; i++) {
11988        var index = this.selectpicker.current.map.originalIndex[i], // faster than $(li).data('originalIndex')
11989            option = $selectOptions[index];
11990
11991        if (option) {
11992          if (option.selected) previousSelected++;
11993          option.selected = status;
11994          if (option.selected) currentSelected++;
11995        }
11996      }
11997
11998      if (previousSelected === currentSelected) return;
11999
12000      this.setOptionStatus();
12001
12002      this.togglePlaceholder();
12003
12004      this.$element
12005        .triggerNative('change');
12006    },
12007
12008    selectAll: function () {
12009      return this.changeAll(true);
12010    },
12011
12012    deselectAll: function () {
12013      return this.changeAll(false);
12014    },
12015
12016    toggle: function (e) {
12017      e = e || window.event;
12018
12019      if (e) e.stopPropagation();
12020
12021      this.$button.trigger('click.bs.dropdown.data-api');
12022    },
12023
12024    keydown: function (e) {
12025      var $this = $(this),
12026          $parent = $this.is('input') ? $this.parent().parent() : $this.parent(),
12027          that = $parent.data('this'),
12028          $items = that.findLis(),
12029          index,
12030          isActive,
12031          liActive,
12032          activeLi,
12033          offset,
12034          updateScroll = false,
12035          downOnTab = e.which === keyCodes.TAB && !$this.hasClass('dropdown-toggle') && !that.options.selectOnTab,
12036          isArrowKey = REGEXP_ARROW.test(e.which) || downOnTab,
12037          scrollTop = that.$menuInner[0].scrollTop,
12038          isVirtual = that.isVirtual(),
12039          position0 = isVirtual === true ? that.selectpicker.view.position0 : 0;
12040
12041      isActive = that.$newElement.hasClass(classNames.SHOW);
12042
12043      if (
12044        !isActive &&
12045        (
12046          isArrowKey ||
12047          e.which >= 48 && e.which <= 57 ||
12048          e.which >= 96 && e.which <= 105 ||
12049          e.which >= 65 && e.which <= 90
12050        )
12051      ) {
12052        that.$button.trigger('click.bs.dropdown.data-api');
12053      }
12054
12055      if (e.which === keyCodes.ESCAPE && isActive) {
12056        e.preventDefault();
12057        that.$button.trigger('click.bs.dropdown.data-api').focus();
12058      }
12059
12060      if (isArrowKey) { // if up or down
12061        if (!$items.length) return;
12062
12063        // $items.index/.filter is too slow with a large list and no virtual scroll
12064        index = isVirtual === true ? $items.index($items.filter('.active')) : that.selectpicker.current.map.newIndex[that.activeIndex];
12065
12066        if (index === undefined) index = -1;
12067
12068        if (index !== -1) {
12069          liActive = that.selectpicker.current.elements[index + position0];
12070          liActive.classList.remove('active');
12071          if (liActive.firstChild) liActive.firstChild.classList.remove('active');
12072        }
12073
12074        if (e.which === keyCodes.ARROW_UP) { // up
12075          if (index !== -1) index--;
12076          if (index + position0 < 0) index += $items.length;
12077
12078          if (!that.selectpicker.view.canHighlight[index + position0]) {
12079            index = that.selectpicker.view.canHighlight.slice(0, index + position0).lastIndexOf(true) - position0;
12080            if (index === -1) index = $items.length - 1;
12081          }
12082        } else if (e.which === keyCodes.ARROW_DOWN || downOnTab) { // down
12083          index++;
12084          if (index + position0 >= that.selectpicker.view.canHighlight.length) index = 0;
12085
12086          if (!that.selectpicker.view.canHighlight[index + position0]) {
12087            index = index + 1 + that.selectpicker.view.canHighlight.slice(index + position0 + 1).indexOf(true);
12088          }
12089        }
12090
12091        e.preventDefault();
12092
12093        var liActiveIndex = position0 + index;
12094
12095        if (e.which === keyCodes.ARROW_UP) { // up
12096          // scroll to bottom and highlight last option
12097          if (position0 === 0 && index === $items.length - 1) {
12098            that.$menuInner[0].scrollTop = that.$menuInner[0].scrollHeight;
12099
12100            liActiveIndex = that.selectpicker.current.elements.length - 1;
12101          } else {
12102            activeLi = that.selectpicker.current.data[liActiveIndex];
12103            offset = activeLi.position - activeLi.height;
12104
12105            updateScroll = offset < scrollTop;
12106          }
12107        } else if (e.which === keyCodes.ARROW_DOWN || downOnTab) { // down
12108          // scroll to top and highlight first option
12109          if (position0 !== 0 && index === 0) {
12110            that.$menuInner[0].scrollTop = 0;
12111
12112            liActiveIndex = 0;
12113          } else {
12114            activeLi = that.selectpicker.current.data[liActiveIndex];
12115            offset = activeLi.position - that.sizeInfo.menuInnerHeight;
12116
12117            updateScroll = offset > scrollTop;
12118          }
12119        }
12120
12121        liActive = that.selectpicker.current.elements[liActiveIndex];
12122        liActive.classList.add('active');
12123        if (liActive.firstChild) liActive.firstChild.classList.add('active');
12124        that.activeIndex = that.selectpicker.current.map.originalIndex[liActiveIndex];
12125
12126        that.selectpicker.view.currentActive = liActive;
12127
12128        if (updateScroll) that.$menuInner[0].scrollTop = offset;
12129
12130        if (that.options.liveSearch) {
12131          that.$searchbox.focus();
12132        } else {
12133          $this.focus();
12134        }
12135      } else if (
12136        !$this.is('input') &&
12137        !REGEXP_TAB_OR_ESCAPE.test(e.which) ||
12138        (e.which === keyCodes.SPACE && that.selectpicker.keydown.keyHistory)
12139      ) {
12140        var searchMatch,
12141            matches = [],
12142            keyHistory;
vendor: 7,357 bytes, lines 12143-12367
12143
12144        e.preventDefault();
12145
12146        that.selectpicker.keydown.keyHistory += keyCodeMap[e.which];
12147
12148        if (that.selectpicker.keydown.resetKeyHistory.cancel) clearTimeout(that.selectpicker.keydown.resetKeyHistory.cancel);
12149        that.selectpicker.keydown.resetKeyHistory.cancel = that.selectpicker.keydown.resetKeyHistory.start();
12150
12151        keyHistory = that.selectpicker.keydown.keyHistory;
12152
12153        // if all letters are the same, set keyHistory to just the first character when searching
12154        if (/^(.)\1+$/.test(keyHistory)) {
12155          keyHistory = keyHistory.charAt(0);
12156        }
12157
12158        // find matches
12159        for (var i = 0; i < that.selectpicker.current.data.length; i++) {
12160          var li = that.selectpicker.current.data[i],
12161              hasMatch;
12162
12163          hasMatch = stringSearch(li, keyHistory, 'startsWith', true);
12164
12165          if (hasMatch && that.selectpicker.view.canHighlight[i]) {
12166            li.index = i;
12167            matches.push(li.originalIndex);
12168          }
12169        }
12170
12171        if (matches.length) {
12172          var matchIndex = 0;
12173
12174          $items.removeClass('active').find('a').removeClass('active');
12175
12176          // either only one key has been pressed or they are all the same key
12177          if (keyHistory.length === 1) {
12178            matchIndex = matches.indexOf(that.activeIndex);
12179
12180            if (matchIndex === -1 || matchIndex === matches.length - 1) {
12181              matchIndex = 0;
12182            } else {
12183              matchIndex++;
12184            }
12185          }
12186
12187          searchMatch = that.selectpicker.current.map.newIndex[matches[matchIndex]];
12188
12189          activeLi = that.selectpicker.current.data[searchMatch];
12190
12191          if (scrollTop - activeLi.position > 0) {
12192            offset = activeLi.position - activeLi.height;
12193            updateScroll = true;
12194          } else {
12195            offset = activeLi.position - that.sizeInfo.menuInnerHeight;
12196            // if the option is already visible at the current scroll position, just keep it the same
12197            updateScroll = activeLi.position > scrollTop + that.sizeInfo.menuInnerHeight;         
12198          }
12199
12200          liActive = that.selectpicker.current.elements[searchMatch];
12201          liActive.classList.add('active');
12202          if (liActive.firstChild) liActive.firstChild.classList.add('active');
12203          that.activeIndex = matches[matchIndex];
12204
12205          liActive.firstChild.focus();
12206
12207          if (updateScroll) that.$menuInner[0].scrollTop = offset;
12208
12209          $this.focus();
12210        }
12211      }
12212
12213      // Select focused option if "Enter", "Spacebar" or "Tab" (when selectOnTab is true) are pressed inside the menu.
12214      if (
12215        isActive &&
12216        (
12217          (e.which === keyCodes.SPACE && !that.selectpicker.keydown.keyHistory) ||
12218          e.which === keyCodes.ENTER ||
12219          (e.which === keyCodes.TAB && that.options.selectOnTab)
12220        )
12221      ) {
12222        if (e.which !== keyCodes.SPACE) e.preventDefault();
12223
12224        if (!that.options.liveSearch || e.which !== keyCodes.SPACE) {
12225          that.$menuInner.find('.active a').trigger('click', true); // retain active class
12226          $this.focus();
12227
12228          if (!that.options.liveSearch) {
12229            // Prevent screen from scrolling if the user hits the spacebar
12230            e.preventDefault();
12231            // Fixes spacebar selection of dropdown items in FF & IE
12232            $(document).data('spaceSelect', true);
12233          }
12234        }
12235      }
12236    },
12237
12238    mobile: function () {
12239      this.$element.addClass('mobile-device');
12240    },
12241
12242    refresh: function () {
12243      // update options if data attributes have been changed
12244      var config = $.extend({}, this.options, this.$element.data());
12245      this.options = config;
12246
12247      this.selectpicker.main.map.newIndex = {};
12248      this.selectpicker.main.map.originalIndex = {};
12249      this.createLi();
12250      this.checkDisabled();
12251      this.render();
12252      this.setStyle();
12253      this.setWidth();
12254
12255      this.setSize(true);
12256
12257      this.$element.trigger('refreshed.bs.select');
12258    },
12259
12260    hide: function () {
12261      this.$newElement.hide();
12262    },
12263
12264    show: function () {
12265      this.$newElement.show();
12266    },
12267
12268    remove: function () {
12269      this.$newElement.remove();
12270      this.$element.remove();
12271    },
12272
12273    destroy: function () {
12274      this.$newElement.before(this.$element).remove();
12275
12276      if (this.$bsContainer) {
12277        this.$bsContainer.remove();
12278      } else {
12279        this.$menu.remove();
12280      }
12281
12282      this.$element
12283        .off('.bs.select')
12284        .removeData('selectpicker')
12285        .removeClass('bs-select-hidden selectpicker');
12286    }
12287  };
12288
12289  // SELECTPICKER PLUGIN DEFINITION
12290  // ==============================
12291  function Plugin(option) {
12292    // get the args of the outer function..
12293    var args = arguments;
12294    // The arguments of the function are explicitly re-defined from the argument list, because the shift causes them
12295    // to get lost/corrupted in android 2.3 and IE9 #715 #775
12296    var _option = option;
12297
12298    [].shift.apply(args);
12299
12300    var value;
12301    var chain = this.each(function () {
12302      var $this = $(this);
12303      if ($this.is('select')) {
12304        var data = $this.data('selectpicker'),
12305            options = typeof _option == 'object' && _option;
12306
12307        if (!data) {
12308          var config = $.extend({}, Selectpicker.DEFAULTS, $.fn.selectpicker.defaults || {}, $this.data(), options);
12309          config.template = $.extend({}, Selectpicker.DEFAULTS.template, ($.fn.selectpicker.defaults ? $.fn.selectpicker.defaults.template : {}), $this.data().template, options.template);
12310          $this.data('selectpicker', (data = new Selectpicker(this, config)));
12311        } else if (options) {
12312          for (var i in options) {
12313            if (options.hasOwnProperty(i)) {
12314              data.options[i] = options[i];
12315            }
12316          }
12317        }
12318
12319        if (typeof _option == 'string') {
12320          if (data[_option] instanceof Function) {
12321            value = data[_option].apply(data, args);
12322          } else {
12323            value = data.options[_option];
12324          }
12325        }
12326      }
12327    });
12328
12329    if (typeof value !== 'undefined') {
12330      //noinspection JSUnusedAssignment
12331      return value;
12332    } else {
12333      return chain;
12334    }
12335  }
12336
12337  var old = $.fn.selectpicker;
12338  $.fn.selectpicker = Plugin;
12339  $.fn.selectpicker.Constructor = Selectpicker;
12340
12341  // SELECTPICKER NO CONFLICT
12342  // ========================
12343  $.fn.selectpicker.noConflict = function () {
12344    $.fn.selectpicker = old;
12345    return this;
12346  };
12347
12348  $(document)
12349      .off('keydown.bs.dropdown.data-api')
12350      .on('keydown.bs.select', '.bootstrap-select [data-toggle="dropdown"], .bootstrap-select [role="listbox"], .bs-searchbox input', Selectpicker.prototype.keydown)
12351      .on('focusin.modal', '.bootstrap-select [data-toggle="dropdown"], .bootstrap-select [role="listbox"], .bs-searchbox input', function (e) {
12352        e.stopPropagation();
12353      });
12354
12355  // SELECTPICKER DATA-API
12356  // =====================
12357  $(window).on('load.bs.select.data-api', function () {
12358    $('.selectpicker').each(function () {
12359      var $selectpicker = $(this);
12360      Plugin.call($selectpicker, $selectpicker.data());
12361    })
12362  });
12363})(jQuery);
12364
12365
12366}));
12367
vendor: 32,123 bytes, lines 12368-13253
12368/*!
12369 * typeahead.js 0.11.1
12370 * https://github.com/twitter/typeahead.js
12371 * Copyright 2013-2015 Twitter, Inc. and other contributors; Licensed MIT
12372 */
12373
12374(function(root, factory) {
12375    if (typeof define === "function" && define.amd) {
12376        define("bloodhound", [ "jquery" ], function(a0) {
12377            return root["Bloodhound"] = factory(a0);
12378        });
12379    } else if (typeof exports === "object") {
12380        module.exports = factory(require("jquery"));
12381    } else {
12382        root["Bloodhound"] = factory(jQuery);
12383    }
12384})(this, function($) {
12385    var _ = function() {
12386        "use strict";
12387        return {
12388            isMsie: function() {
12389                return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
12390            },
12391            isBlankString: function(str) {
12392                return !str || /^\s*$/.test(str);
12393            },
12394            escapeRegExChars: function(str) {
12395                return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
12396            },
12397            isString: function(obj) {
12398                return typeof obj === "string";
12399            },
12400            isNumber: function(obj) {
12401                return typeof obj === "number";
12402            },
12403            isArray: $.isArray,
12404            isFunction: $.isFunction,
12405            isObject: $.isPlainObject,
12406            isUndefined: function(obj) {
12407                return typeof obj === "undefined";
12408            },
12409            isElement: function(obj) {
12410                return !!(obj && obj.nodeType === 1);
12411            },
12412            isJQuery: function(obj) {
12413                return obj instanceof $;
12414            },
12415            toStr: function toStr(s) {
12416                return _.isUndefined(s) || s === null ? "" : s + "";
12417            },
12418            bind: $.proxy,
12419            each: function(collection, cb) {
12420                $.each(collection, reverseArgs);
12421                function reverseArgs(index, value) {
12422                    return cb(value, index);
12423                }
12424            },
12425            map: $.map,
12426            filter: $.grep,
12427            every: function(obj, test) {
12428                var result = true;
12429                if (!obj) {
12430                    return result;
12431                }
12432                $.each(obj, function(key, val) {
12433                    if (!(result = test.call(null, val, key, obj))) {
12434                        return false;
12435                    }
12436                });
12437                return !!result;
12438            },
12439            some: function(obj, test) {
12440                var result = false;
12441                if (!obj) {
12442                    return result;
12443                }
12444                $.each(obj, function(key, val) {
12445                    if (result = test.call(null, val, key, obj)) {
12446                        return false;
12447                    }
12448                });
12449                return !!result;
12450            },
12451            mixin: $.extend,
12452            identity: function(x) {
12453                return x;
12454            },
12455            clone: function(obj) {
12456                return $.extend(true, {}, obj);
12457            },
12458            getIdGenerator: function() {
12459                var counter = 0;
12460                return function() {
12461                    return counter++;
12462                };
12463            },
12464            templatify: function templatify(obj) {
12465                return $.isFunction(obj) ? obj : template;
12466                function template() {
12467                    return String(obj);
12468                }
12469            },
12470            defer: function(fn) {
12471                setTimeout(fn, 0);
12472            },
12473            debounce: function(func, wait, immediate) {
12474                var timeout, result;
12475                return function() {
12476                    var context = this, args = arguments, later, callNow;
12477                    later = function() {
12478                        timeout = null;
12479                        if (!immediate) {
12480                            result = func.apply(context, args);
12481                        }
12482                    };
12483                    callNow = immediate && !timeout;
12484                    clearTimeout(timeout);
12485                    timeout = setTimeout(later, wait);
12486                    if (callNow) {
12487                        result = func.apply(context, args);
12488                    }
12489                    return result;
12490                };
12491            },
12492            throttle: function(func, wait) {
12493                var context, args, timeout, result, previous, later;
12494                previous = 0;
12495                later = function() {
12496                    previous = new Date();
12497                    timeout = null;
12498                    result = func.apply(context, args);
12499                };
12500                return function() {
12501                    var now = new Date(), remaining = wait - (now - previous);
12502                    context = this;
12503                    args = arguments;
12504                    if (remaining <= 0) {
12505                        clearTimeout(timeout);
12506                        timeout = null;
12507                        previous = now;
12508                        result = func.apply(context, args);
12509                    } else if (!timeout) {
12510                        timeout = setTimeout(later, remaining);
12511                    }
12512                    return result;
12513                };
12514            },
12515            stringify: function(val) {
12516                return _.isString(val) ? val : JSON.stringify(val);
12517            },
12518            noop: function() {}
12519        };
12520    }();
12521    var VERSION = "0.11.1";
12522    var tokenizers = function() {
12523        "use strict";
12524        return {
12525            nonword: nonword,
12526            whitespace: whitespace,
12527            obj: {
12528                nonword: getObjTokenizer(nonword),
12529                whitespace: getObjTokenizer(whitespace)
12530            }
12531        };
12532        function whitespace(str) {
12533            str = _.toStr(str);
12534            return str ? str.split(/\s+/) : [];
12535        }
12536        function nonword(str) {
12537            str = _.toStr(str);
12538            return str ? str.split(/\W+/) : [];
12539        }
12540        function getObjTokenizer(tokenizer) {
12541            return function setKey(keys) {
12542                keys = _.isArray(keys) ? keys : [].slice.call(arguments, 0);
12543                return function tokenize(o) {
12544                    var tokens = [];
12545                    _.each(keys, function(k) {
12546                        tokens = tokens.concat(tokenizer(_.toStr(o[k])));
12547                    });
12548                    return tokens;
12549                };
12550            };
12551        }
12552    }();
12553    var LruCache = function() {
12554        "use strict";
12555        function LruCache(maxSize) {
12556            this.maxSize = _.isNumber(maxSize) ? maxSize : 100;
12557            this.reset();
12558            if (this.maxSize <= 0) {
12559                this.set = this.get = $.noop;
12560            }
12561        }
12562        _.mixin(LruCache.prototype, {
12563            set: function set(key, val) {
12564                var tailItem = this.list.tail, node;
12565                if (this.size >= this.maxSize) {
12566                    this.list.remove(tailItem);
12567                    delete this.hash[tailItem.key];
12568                    this.size--;
12569                }
12570                if (node = this.hash[key]) {
12571                    node.val = val;
12572                    this.list.moveToFront(node);
12573                } else {
12574                    node = new Node(key, val);
12575                    this.list.add(node);
12576                    this.hash[key] = node;
12577                    this.size++;
12578                }
12579            },
12580            get: function get(key) {
12581                var node = this.hash[key];
12582                if (node) {
12583                    this.list.moveToFront(node);
12584                    return node.val;
12585                }
12586            },
12587            reset: function reset() {
12588                this.size = 0;
12589                this.hash = {};
12590                this.list = new List();
12591            }
12592        });
12593        function List() {
12594            this.head = this.tail = null;
12595        }
12596        _.mixin(List.prototype, {
12597            add: function add(node) {
12598                if (this.head) {
12599                    node.next = this.head;
12600                    this.head.prev = node;
12601                }
12602                this.head = node;
12603                this.tail = this.tail || node;
12604            },
12605            remove: function remove(node) {
12606                node.prev ? node.prev.next = node.next : this.head = node.next;
12607                node.next ? node.next.prev = node.prev : this.tail = node.prev;
12608            },
12609            moveToFront: function(node) {
12610                this.remove(node);
12611                this.add(node);
12612            }
12613        });
12614        function Node(key, val) {
12615            this.key = key;
12616            this.val = val;
12617            this.prev = this.next = null;
12618        }
12619        return LruCache;
12620    }();
12621    var PersistentStorage = function() {
12622        "use strict";
12623        var LOCAL_STORAGE;
12624        try {
12625            LOCAL_STORAGE = window.localStorage;
12626            LOCAL_STORAGE.setItem("~~~", "!");
12627            LOCAL_STORAGE.removeItem("~~~");
12628        } catch (err) {
12629            LOCAL_STORAGE = null;
12630        }
12631        function PersistentStorage(namespace, override) {
12632            this.prefix = [ "__", namespace, "__" ].join("");
12633            this.ttlKey = "__ttl__";
12634            this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix));
12635            this.ls = override || LOCAL_STORAGE;
12636            !this.ls && this._noop();
12637        }
12638        _.mixin(PersistentStorage.prototype, {
12639            _prefix: function(key) {
12640                return this.prefix + key;
12641            },
12642            _ttlKey: function(key) {
12643                return this._prefix(key) + this.ttlKey;
12644            },
12645            _noop: function() {
12646                this.get = this.set = this.remove = this.clear = this.isExpired = _.noop;
12647            },
12648            _safeSet: function(key, val) {
12649                try {
12650                    this.ls.setItem(key, val);
12651                } catch (err) {
12652                    if (err.name === "QuotaExceededError") {
12653                        this.clear();
12654                        this._noop();
12655                    }
12656                }
12657            },
12658            get: function(key) {
12659                if (this.isExpired(key)) {
12660                    this.remove(key);
12661                }
12662                return decode(this.ls.getItem(this._prefix(key)));
12663            },
12664            set: function(key, val, ttl) {
12665                if (_.isNumber(ttl)) {
12666                    this._safeSet(this._ttlKey(key), encode(now() + ttl));
12667                } else {
12668                    this.ls.removeItem(this._ttlKey(key));
12669                }
12670                return this._safeSet(this._prefix(key), encode(val));
12671            },
12672            remove: function(key) {
12673                this.ls.removeItem(this._ttlKey(key));
12674                this.ls.removeItem(this._prefix(key));
12675                return this;
12676            },
12677            clear: function() {
12678                var i, keys = gatherMatchingKeys(this.keyMatcher);
12679                for (i = keys.length; i--; ) {
12680                    this.remove(keys[i]);
12681                }
12682                return this;
12683            },
12684            isExpired: function(key) {
12685                var ttl = decode(this.ls.getItem(this._ttlKey(key)));
12686                return _.isNumber(ttl) && now() > ttl ? true : false;
12687            }
12688        });
12689        return PersistentStorage;
12690        function now() {
12691            return new Date().getTime();
12692        }
12693        function encode(val) {
12694            return JSON.stringify(_.isUndefined(val) ? null : val);
12695        }
12696        function decode(val) {
12697            return $.parseJSON(val);
12698        }
12699        function gatherMatchingKeys(keyMatcher) {
12700            var i, key, keys = [], len = LOCAL_STORAGE.length;
12701            for (i = 0; i < len; i++) {
12702                if ((key = LOCAL_STORAGE.key(i)).match(keyMatcher)) {
12703                    keys.push(key.replace(keyMatcher, ""));
12704                }
12705            }
12706            return keys;
12707        }
12708    }();
12709    var Transport = function() {
12710        "use strict";
12711        var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, sharedCache = new LruCache(10);
12712        function Transport(o) {
12713            o = o || {};
12714            this.cancelled = false;
12715            this.lastReq = null;
12716            this._send = o.transport;
12717            this._get = o.limiter ? o.limiter(this._get) : this._get;
12718            this._cache = o.cache === false ? new LruCache(0) : sharedCache;
12719        }
12720        Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {
12721            maxPendingRequests = num;
12722        };
12723        Transport.resetCache = function resetCache() {
12724            sharedCache.reset();
12725        };
12726        _.mixin(Transport.prototype, {
12727            _fingerprint: function fingerprint(o) {
12728                o = o || {};
12729                return o.url + o.type + $.param(o.data || {});
12730            },
12731            _get: function(o, cb) {
12732                var that = this, fingerprint, jqXhr;
12733                fingerprint = this._fingerprint(o);
12734                if (this.cancelled || fingerprint !== this.lastReq) {
12735                    return;
12736                }
12737                if (jqXhr = pendingRequests[fingerprint]) {
12738                    jqXhr.done(done).fail(fail);
12739                } else if (pendingRequestsCount < maxPendingRequests) {
12740                    pendingRequestsCount++;
12741                    pendingRequests[fingerprint] = this._send(o).done(done).fail(fail).always(always);
12742                } else {
12743                    this.onDeckRequestArgs = [].slice.call(arguments, 0);
12744                }
12745                function done(resp) {
12746                    cb(null, resp);
12747                    that._cache.set(fingerprint, resp);
12748                }
12749                function fail() {
12750                    cb(true);
12751                }
12752                function always() {
12753                    pendingRequestsCount--;
12754                    delete pendingRequests[fingerprint];
12755                    if (that.onDeckRequestArgs) {
12756                        that._get.apply(that, that.onDeckRequestArgs);
12757                        that.onDeckRequestArgs = null;
12758                    }
12759                }
12760            },
12761            get: function(o, cb) {
12762                var resp, fingerprint;
12763                cb = cb || $.noop;
12764                o = _.isString(o) ? {
12765                    url: o
12766                } : o || {};
12767                fingerprint = this._fingerprint(o);
12768                this.cancelled = false;
12769                this.lastReq = fingerprint;
12770                if (resp = this._cache.get(fingerprint)) {
12771                    cb(null, resp);
12772                } else {
12773                    this._get(o, cb);
12774                }
12775            },
12776            cancel: function() {
12777                this.cancelled = true;
12778            }
12779        });
12780        return Transport;
12781    }();
12782    var SearchIndex = window.SearchIndex = function() {
12783        "use strict";
12784        var CHILDREN = "c", IDS = "i";
12785        function SearchIndex(o) {
12786            o = o || {};
12787            if (!o.datumTokenizer || !o.queryTokenizer) {
12788                $.error("datumTokenizer and queryTokenizer are both required");
12789            }
12790            this.identify = o.identify || _.stringify;
12791            this.datumTokenizer = o.datumTokenizer;
12792            this.queryTokenizer = o.queryTokenizer;
12793            this.reset();
12794        }
12795        _.mixin(SearchIndex.prototype, {
12796            bootstrap: function bootstrap(o) {
12797                this.datums = o.datums;
12798                this.trie = o.trie;
12799            },
12800            add: function(data) {
12801                var that = this;
12802                data = _.isArray(data) ? data : [ data ];
12803                _.each(data, function(datum) {
12804                    var id, tokens;
12805                    that.datums[id = that.identify(datum)] = datum;
12806                    tokens = normalizeTokens(that.datumTokenizer(datum));
12807                    _.each(tokens, function(token) {
12808                        var node, chars, ch;
12809                        node = that.trie;
12810                        chars = token.split("");
12811                        while (ch = chars.shift()) {
12812                            node = node[CHILDREN][ch] || (node[CHILDREN][ch] = newNode());
12813                            node[IDS].push(id);
12814                        }
12815                    });
12816                });
12817            },
12818            get: function get(ids) {
12819                var that = this;
12820                return _.map(ids, function(id) {
12821                    return that.datums[id];
12822                });
12823            },
12824            search: function search(query) {
12825                var that = this, tokens, matches;
12826                tokens = normalizeTokens(this.queryTokenizer(query));
12827                _.each(tokens, function(token) {
12828                    var node, chars, ch, ids;
12829                    if (matches && matches.length === 0) {
12830                        return false;
12831                    }
12832                    node = that.trie;
12833                    chars = token.split("");
12834                    while (node && (ch = chars.shift())) {
12835                        node = node[CHILDREN][ch];
12836                    }
12837                    if (node && chars.length === 0) {
12838                        ids = node[IDS].slice(0);
12839                        matches = matches ? getIntersection(matches, ids) : ids;
12840                    } else {
12841                        matches = [];
12842                        return false;
12843                    }
12844                });
12845                return matches ? _.map(unique(matches), function(id) {
12846                    return that.datums[id];
12847                }) : [];
12848            },
12849            all: function all() {
12850                var values = [];
12851                for (var key in this.datums) {
12852                    values.push(this.datums[key]);
12853                }
12854                return values;
12855            },
12856            reset: function reset() {
12857                this.datums = {};
12858                this.trie = newNode();
12859            },
12860            serialize: function serialize() {
12861                return {
12862                    datums: this.datums,
12863                    trie: this.trie
12864                };
12865            }
12866        });
12867        return SearchIndex;
12868        function normalizeTokens(tokens) {
12869            tokens = _.filter(tokens, function(token) {
12870                return !!token;
12871            });
12872            tokens = _.map(tokens, function(token) {
12873                return token.toLowerCase();
12874            });
12875            return tokens;
12876        }
12877        function newNode() {
12878            var node = {};
12879            node[IDS] = [];
12880            node[CHILDREN] = {};
12881            return node;
12882        }
12883        function unique(array) {
12884            var seen = {}, uniques = [];
12885            for (var i = 0, len = array.length; i < len; i++) {
12886                if (!seen[array[i]]) {
12887                    seen[array[i]] = true;
12888                    uniques.push(array[i]);
12889                }
12890            }
12891            return uniques;
12892        }
12893        function getIntersection(arrayA, arrayB) {
12894            var ai = 0, bi = 0, intersection = [];
12895            arrayA = arrayA.sort();
12896            arrayB = arrayB.sort();
12897            var lenArrayA = arrayA.length, lenArrayB = arrayB.length;
12898            while (ai < lenArrayA && bi < lenArrayB) {
12899                if (arrayA[ai] < arrayB[bi]) {
12900                    ai++;
12901                } else if (arrayA[ai] > arrayB[bi]) {
12902                    bi++;
12903                } else {
12904                    intersection.push(arrayA[ai]);
12905                    ai++;
12906                    bi++;
12907                }
12908            }
12909            return intersection;
12910        }
12911    }();
12912    var Prefetch = function() {
12913        "use strict";
12914        var keys;
12915        keys = {
12916            data: "data",
12917            protocol: "protocol",
12918            thumbprint: "thumbprint"
12919        };
12920        function Prefetch(o) {
12921            this.url = o.url;
12922            this.ttl = o.ttl;
12923            this.cache = o.cache;
12924            this.prepare = o.prepare;
12925            this.transform = o.transform;
12926            this.transport = o.transport;
12927            this.thumbprint = o.thumbprint;
12928            this.storage = new PersistentStorage(o.cacheKey);
12929        }
12930        _.mixin(Prefetch.prototype, {
12931            _settings: function settings() {
12932                return {
12933                    url: this.url,
12934                    type: "GET",
12935                    dataType: "json"
12936                };
12937            },
12938            store: function store(data) {
12939                if (!this.cache) {
12940                    return;
12941                }
12942                this.storage.set(keys.data, data, this.ttl);
12943                this.storage.set(keys.protocol, location.protocol, this.ttl);
12944                this.storage.set(keys.thumbprint, this.thumbprint, this.ttl);
12945            },
12946            fromCache: function fromCache() {
12947                var stored = {}, isExpired;
12948                if (!this.cache) {
12949                    return null;
12950                }
12951                stored.data = this.storage.get(keys.data);
12952                stored.protocol = this.storage.get(keys.protocol);
12953                stored.thumbprint = this.storage.get(keys.thumbprint);
12954                isExpired = stored.thumbprint !== this.thumbprint || stored.protocol !== location.protocol;
12955                return stored.data && !isExpired ? stored.data : null;
12956            },
12957            fromNetwork: function(cb) {
12958                var that = this, settings;
12959                if (!cb) {
12960                    return;
12961                }
12962                settings = this.prepare(this._settings());
12963                this.transport(settings).fail(onError).done(onResponse);
12964                function onError() {
12965                    cb(true);
12966                }
12967                function onResponse(resp) {
12968                    cb(null, that.transform(resp));
12969                }
12970            },
12971            clear: function clear() {
12972                this.storage.clear();
12973                return this;
12974            }
12975        });
12976        return Prefetch;
12977    }();
12978    var Remote = function() {
12979        "use strict";
12980        function Remote(o) {
12981            this.url = o.url;
12982            this.prepare = o.prepare;
12983            this.transform = o.transform;
12984            this.transport = new Transport({
12985                cache: o.cache,
12986                limiter: o.limiter,
12987                transport: o.transport
12988            });
12989        }
12990        _.mixin(Remote.prototype, {
12991            _settings: function settings() {
12992                return {
12993                    url: this.url,
12994                    type: "GET",
12995                    dataType: "json"
12996                };
12997            },
12998            get: function get(query, cb) {
12999                var that = this, settings;
13000                if (!cb) {
13001                    return;
13002                }
13003                query = query || "";
13004                settings = this.prepare(query, this._settings());
13005                return this.transport.get(settings, onResponse);
13006                function onResponse(err, resp) {
13007                    err ? cb([]) : cb(that.transform(resp));
13008                }
13009            },
13010            cancelLastRequest: function cancelLastRequest() {
13011                this.transport.cancel();
13012            }
13013        });
13014        return Remote;
13015    }();
13016    var oParser = function() {
13017        "use strict";
13018        return function parse(o) {
13019            var defaults, sorter;
13020            defaults = {
13021                initialize: true,
13022                identify: _.stringify,
13023                datumTokenizer: null,
13024                queryTokenizer: null,
13025                sufficient: 5,
13026                sorter: null,
13027                local: [],
13028                prefetch: null,
13029                remote: null
13030            };
13031            o = _.mixin(defaults, o || {});
13032            !o.datumTokenizer && $.error("datumTokenizer is required");
13033            !o.queryTokenizer && $.error("queryTokenizer is required");
13034            sorter = o.sorter;
13035            o.sorter = sorter ? function(x) {
13036                return x.sort(sorter);
13037            } : _.identity;
13038            o.local = _.isFunction(o.local) ? o.local() : o.local;
13039            o.prefetch = parsePrefetch(o.prefetch);
13040            o.remote = parseRemote(o.remote);
13041            return o;
13042        };
13043        function parsePrefetch(o) {
13044            var defaults;
13045            if (!o) {
13046                return null;
13047            }
13048            defaults = {
13049                url: null,
13050                ttl: 24 * 60 * 60 * 1e3,
13051                cache: true,
13052                cacheKey: null,
13053                thumbprint: "",
13054                prepare: _.identity,
13055                transform: _.identity,
13056                transport: null
13057            };
13058            o = _.isString(o) ? {
13059                url: o
13060            } : o;
13061            o = _.mixin(defaults, o);
13062            !o.url && $.error("prefetch requires url to be set");
13063            o.transform = o.filter || o.transform;
13064            o.cacheKey = o.cacheKey || o.url;
13065            o.thumbprint = VERSION + o.thumbprint;
13066            o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax;
13067            return o;
13068        }
13069        function parseRemote(o) {
13070            var defaults;
13071            if (!o) {
13072                return;
13073            }
13074            defaults = {
13075                url: null,
13076                cache: true,
13077                prepare: null,
13078                replace: null,
13079                wildcard: null,
13080                limiter: null,
13081                rateLimitBy: "debounce",
13082                rateLimitWait: 300,
13083                transform: _.identity,
13084                transport: null
13085            };
13086            o = _.isString(o) ? {
13087                url: o
13088            } : o;
13089            o = _.mixin(defaults, o);
13090            !o.url && $.error("remote requires url to be set");
13091            o.transform = o.filter || o.transform;
13092            o.prepare = toRemotePrepare(o);
13093            o.limiter = toLimiter(o);
13094            o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax;
13095            delete o.replace;
13096            delete o.wildcard;
13097            delete o.rateLimitBy;
13098            delete o.rateLimitWait;
13099            return o;
13100        }
13101        function toRemotePrepare(o) {
13102            var prepare, replace, wildcard;
13103            prepare = o.prepare;
13104            replace = o.replace;
13105            wildcard = o.wildcard;
13106            if (prepare) {
13107                return prepare;
13108            }
13109            if (replace) {
13110                prepare = prepareByReplace;
13111            } else if (o.wildcard) {
13112                prepare = prepareByWildcard;
13113            } else {
13114                prepare = idenityPrepare;
13115            }
13116            return prepare;
13117            function prepareByReplace(query, settings) {
13118                settings.url = replace(settings.url, query);
13119                return settings;
13120            }
13121            function prepareByWildcard(query, settings) {
13122                settings.url = settings.url.replace(wildcard, encodeURIComponent(query));
13123                return settings;
13124            }
13125            function idenityPrepare(query, settings) {
13126                return settings;
13127            }
13128        }
13129        function toLimiter(o) {
13130            var limiter, method, wait;
13131            limiter = o.limiter;
13132            method = o.rateLimitBy;
13133            wait = o.rateLimitWait;
13134            if (!limiter) {
13135                limiter = /^throttle$/i.test(method) ? throttle(wait) : debounce(wait);
13136            }
13137            return limiter;
13138            function debounce(wait) {
13139                return function debounce(fn) {
13140                    return _.debounce(fn, wait);
13141                };
13142            }
13143            function throttle(wait) {
13144                return function throttle(fn) {
13145                    return _.throttle(fn, wait);
13146                };
13147            }
13148        }
13149        function callbackToDeferred(fn) {
13150            return function wrapper(o) {
13151                var deferred = $.Deferred();
13152                fn(o, onSuccess, onError);
13153                return deferred;
13154                function onSuccess(resp) {
13155                    _.defer(function() {
13156                        deferred.resolve(resp);
13157                    });
13158                }
13159                function onError(err) {
13160                    _.defer(function() {
13161                        deferred.reject(err);
13162                    });
13163                }
13164            };
13165        }
13166    }();
13167    var Bloodhound = function() {
13168        "use strict";
13169        var old;
13170        old = window && window.Bloodhound;
13171        function Bloodhound(o) {
13172            o = oParser(o);
13173            this.sorter = o.sorter;
13174            this.identify = o.identify;
13175            this.sufficient = o.sufficient;
13176            this.local = o.local;
13177            this.remote = o.remote ? new Remote(o.remote) : null;
13178            this.prefetch = o.prefetch ? new Prefetch(o.prefetch) : null;
13179            this.index = new SearchIndex({
13180                identify: this.identify,
13181                datumTokenizer: o.datumTokenizer,
13182                queryTokenizer: o.queryTokenizer
13183            });
13184            o.initialize !== false && this.initialize();
13185        }
13186        Bloodhound.noConflict = function noConflict() {
13187            window && (window.Bloodhound = old);
13188            return Bloodhound;
13189        };
13190        Bloodhound.tokenizers = tokenizers;
13191        _.mixin(Bloodhound.prototype, {
13192            __ttAdapter: function ttAdapter() {
13193                var that = this;
13194                return this.remote ? withAsync : withoutAsync;
13195                function withAsync(query, sync, async) {
13196                    return that.search(query, sync, async);
13197                }
13198                function withoutAsync(query, sync) {
13199                    return that.search(query, sync);
13200                }
13201            },
13202            _loadPrefetch: function loadPrefetch() {
13203                var that = this, deferred, serialized;
13204                deferred = $.Deferred();
13205                if (!this.prefetch) {
13206                    deferred.resolve();
13207                } else if (serialized = this.prefetch.fromCache()) {
13208                    this.index.bootstrap(serialized);
13209                    deferred.resolve();
13210                } else {
13211                    this.prefetch.fromNetwork(done);
13212                }
13213                return deferred.promise();
13214                function done(err, data) {
13215                    if (err) {
13216                        return deferred.reject();
13217                    }
13218                    that.add(data);
13219                    that.prefetch.store(that.index.serialize());
13220                    deferred.resolve();
13221                }
13222            },
13223            _initialize: function initialize() {
13224                var that = this, deferred;
13225                this.clear();
13226                (this.initPromise = this._loadPrefetch()).done(addLocalToIndex);
13227                return this.initPromise;
13228                function addLocalToIndex() {
13229                    that.add(that.local);
13230                }
13231            },
13232            initialize: function initialize(force) {
13233                return !this.initPromise || force ? this._initialize() : this.initPromise;
13234            },
13235            add: function add(data) {
13236                this.index.add(data);
13237                return this;
13238            },
13239            get: function get(ids) {
13240                ids = _.isArray(ids) ? ids : [].slice.call(arguments);
13241                return this.index.get(ids);
13242            },
13243            search: function search(query, sync, async) {
13244                var that = this, local;
13245                local = this.sorter(this.index.search(query));
13246                sync(this.remote ? local.slice() : local);
13247                if (this.remote && local.length < this.sufficient) {
13248                    this.remote.get(query, processRemote);
13249                } else if (this.remote) {
13250                    this.remote.cancelLastRequest();
13251                }
13252                return this;
13253                function processRemote(remote) {
vendor: 3,453 bytes, lines 13254-13353
13254                    var nonDuplicates = [];
13255                    _.each(remote, function(r) {
13256                        !_.some(local, function(l) {
13257                            return that.identify(r) === that.identify(l);
13258                        }) && nonDuplicates.push(r);
13259                    });
13260                    async && async(nonDuplicates);
13261                }
13262            },
13263            all: function all() {
13264                return this.index.all();
13265            },
13266            clear: function clear() {
13267                this.index.reset();
13268                return this;
13269            },
13270            clearPrefetchCache: function clearPrefetchCache() {
13271                this.prefetch && this.prefetch.clear();
13272                return this;
13273            },
13274            clearRemoteCache: function clearRemoteCache() {
13275                Transport.resetCache();
13276                return this;
13277            },
13278            ttAdapter: function ttAdapter() {
13279                return this.__ttAdapter();
13280            }
13281        });
13282        return Bloodhound;
13283    }();
13284    return Bloodhound;
13285});
13286
13287(function(root, factory) {
13288    if (typeof define === "function" && define.amd) {
13289        define("typeahead.js", [ "jquery" ], function(a0) {
13290            return factory(a0);
13291        });
13292    } else if (typeof exports === "object") {
13293        module.exports = factory(require("jquery"));
13294    } else {
13295        factory(jQuery);
13296    }
13297})(this, function($) {
13298    var _ = function() {
13299        "use strict";
13300        return {
13301            isMsie: function() {
13302                return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
13303            },
13304            isBlankString: function(str) {
13305                return !str || /^\s*$/.test(str);
13306            },
13307            escapeRegExChars: function(str) {
13308                return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
13309            },
13310            isString: function(obj) {
13311                return typeof obj === "string";
13312            },
13313            isNumber: function(obj) {
13314                return typeof obj === "number";
13315            },
13316            isArray: $.isArray,
13317            isFunction: $.isFunction,
13318            isObject: $.isPlainObject,
13319            isUndefined: function(obj) {
13320                return typeof obj === "undefined";
13321            },
13322            isElement: function(obj) {
13323                return !!(obj && obj.nodeType === 1);
13324            },
13325            isJQuery: function(obj) {
13326                return obj instanceof $;
13327            },
13328            toStr: function toStr(s) {
13329                return _.isUndefined(s) || s === null ? "" : s + "";
13330            },
13331            bind: $.proxy,
13332            each: function(collection, cb) {
13333                $.each(collection, reverseArgs);
13334                function reverseArgs(index, value) {
13335                    return cb(value, index);
13336                }
13337            },
13338            map: $.map,
13339            filter: $.grep,
13340            every: function(obj, test) {
13341                var result = true;
13342                if (!obj) {
13343                    return result;
13344                }
13345                $.each(obj, function(key, val) {
13346                    if (!(result = test.call(null, val, key, obj))) {
13347                        return false;
13348                    }
13349                });
13350                return !!result;
13351            },
13352            some: function(obj, test) {
13353                var result = false;
vendor: 60,610 bytes, lines 13354-14818
13354                if (!obj) {
13355                    return result;
13356                }
13357                $.each(obj, function(key, val) {
13358                    if (result = test.call(null, val, key, obj)) {
13359                        return false;
13360                    }
13361                });
13362                return !!result;
13363            },
13364            mixin: $.extend,
13365            identity: function(x) {
13366                return x;
13367            },
13368            clone: function(obj) {
13369                return $.extend(true, {}, obj);
13370            },
13371            getIdGenerator: function() {
13372                var counter = 0;
13373                return function() {
13374                    return counter++;
13375                };
13376            },
13377            templatify: function templatify(obj) {
13378                return $.isFunction(obj) ? obj : template;
13379                function template() {
13380                    return String(obj);
13381                }
13382            },
13383            defer: function(fn) {
13384                setTimeout(fn, 0);
13385            },
13386            debounce: function(func, wait, immediate) {
13387                var timeout, result;
13388                return function() {
13389                    var context = this, args = arguments, later, callNow;
13390                    later = function() {
13391                        timeout = null;
13392                        if (!immediate) {
13393                            result = func.apply(context, args);
13394                        }
13395                    };
13396                    callNow = immediate && !timeout;
13397                    clearTimeout(timeout);
13398                    timeout = setTimeout(later, wait);
13399                    if (callNow) {
13400                        result = func.apply(context, args);
13401                    }
13402                    return result;
13403                };
13404            },
13405            throttle: function(func, wait) {
13406                var context, args, timeout, result, previous, later;
13407                previous = 0;
13408                later = function() {
13409                    previous = new Date();
13410                    timeout = null;
13411                    result = func.apply(context, args);
13412                };
13413                return function() {
13414                    var now = new Date(), remaining = wait - (now - previous);
13415                    context = this;
13416                    args = arguments;
13417                    if (remaining <= 0) {
13418                        clearTimeout(timeout);
13419                        timeout = null;
13420                        previous = now;
13421                        result = func.apply(context, args);
13422                    } else if (!timeout) {
13423                        timeout = setTimeout(later, remaining);
13424                    }
13425                    return result;
13426                };
13427            },
13428            stringify: function(val) {
13429                return _.isString(val) ? val : JSON.stringify(val);
13430            },
13431            noop: function() {}
13432        };
13433    }();
13434    var WWW = function() {
13435        "use strict";
13436        var defaultClassNames = {
13437            wrapper: "twitter-typeahead",
13438            input: "tt-input",
13439            hint: "tt-hint",
13440            menu: "tt-menu",
13441            dataset: "tt-dataset",
13442            suggestion: "tt-suggestion",
13443            selectable: "tt-selectable",
13444            empty: "tt-empty",
13445            open: "tt-open",
13446            cursor: "tt-cursor",
13447            highlight: "tt-highlight"
13448        };
13449        return build;
13450        function build(o) {
13451            var www, classes;
13452            classes = _.mixin({}, defaultClassNames, o);
13453            www = {
13454                css: buildCss(),
13455                classes: classes,
13456                html: buildHtml(classes),
13457                selectors: buildSelectors(classes)
13458            };
13459            return {
13460                css: www.css,
13461                html: www.html,
13462                classes: www.classes,
13463                selectors: www.selectors,
13464                mixin: function(o) {
13465                    _.mixin(o, www);
13466                }
13467            };
13468        }
13469        function buildHtml(c) {
13470            return {
13471                wrapper: '<span class="' + c.wrapper + '"></span>',
13472                menu: '<div class="' + c.menu + '"></div>'
13473            };
13474        }
13475        function buildSelectors(classes) {
13476            var selectors = {};
13477            _.each(classes, function(v, k) {
13478                selectors[k] = "." + v;
13479            });
13480            return selectors;
13481        }
13482        function buildCss() {
13483            var css = {
13484                wrapper: {
13485                    position: "relative",
13486                    display: "inline-block"
13487                },
13488                hint: {
13489                    position: "absolute",
13490                    top: "0",
13491                    left: "0",
13492                    borderColor: "transparent",
13493                    boxShadow: "none",
13494                    opacity: "1"
13495                },
13496                input: {
13497                    position: "relative",
13498                    verticalAlign: "top",
13499                    backgroundColor: "transparent"
13500                },
13501                inputWithNoHint: {
13502                    position: "relative",
13503                    verticalAlign: "top"
13504                },
13505                menu: {
13506                    position: "absolute",
13507                    top: "100%",
13508                    left: "0",
13509                    zIndex: "100",
13510                    display: "none"
13511                },
13512                ltr: {
13513                    left: "0",
13514                    right: "auto"
13515                },
13516                rtl: {
13517                    left: "auto",
13518                    right: " 0"
13519                }
13520            };
13521            if (_.isMsie()) {
13522                _.mixin(css.input, {
13523                    backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"
13524                });
13525            }
13526            return css;
13527        }
13528    }();
13529    var EventBus = function() {
13530        "use strict";
13531        var namespace, deprecationMap;
13532        namespace = "typeahead:";
13533        deprecationMap = {
13534            render: "rendered",
13535            cursorchange: "cursorchanged",
13536            select: "selected",
13537            autocomplete: "autocompleted"
13538        };
13539        function EventBus(o) {
13540            if (!o || !o.el) {
13541                $.error("EventBus initialized without el");
13542            }
13543            this.$el = $(o.el);
13544        }
13545        _.mixin(EventBus.prototype, {
13546            _trigger: function(type, args) {
13547                var $e;
13548                $e = $.Event(namespace + type);
13549                (args = args || []).unshift($e);
13550                this.$el.trigger.apply(this.$el, args);
13551                return $e;
13552            },
13553            before: function(type) {
13554                var args, $e;
13555                args = [].slice.call(arguments, 1);
13556                $e = this._trigger("before" + type, args);
13557                return $e.isDefaultPrevented();
13558            },
13559            trigger: function(type) {
13560                var deprecatedType;
13561                this._trigger(type, [].slice.call(arguments, 1));
13562                if (deprecatedType = deprecationMap[type]) {
13563                    this._trigger(deprecatedType, [].slice.call(arguments, 1));
13564                }
13565            }
13566        });
13567        return EventBus;
13568    }();
13569    var EventEmitter = function() {
13570        "use strict";
13571        var splitter = /\s+/, nextTick = getNextTick();
13572        return {
13573            onSync: onSync,
13574            onAsync: onAsync,
13575            off: off,
13576            trigger: trigger
13577        };
13578        function on(method, types, cb, context) {
13579            var type;
13580            if (!cb) {
13581                return this;
13582            }
13583            types = types.split(splitter);
13584            cb = context ? bindContext(cb, context) : cb;
13585            this._callbacks = this._callbacks || {};
13586            while (type = types.shift()) {
13587                this._callbacks[type] = this._callbacks[type] || {
13588                    sync: [],
13589                    async: []
13590                };
13591                this._callbacks[type][method].push(cb);
13592            }
13593            return this;
13594        }
13595        function onAsync(types, cb, context) {
13596            return on.call(this, "async", types, cb, context);
13597        }
13598        function onSync(types, cb, context) {
13599            return on.call(this, "sync", types, cb, context);
13600        }
13601        function off(types) {
13602            var type;
13603            if (!this._callbacks) {
13604                return this;
13605            }
13606            types = types.split(splitter);
13607            while (type = types.shift()) {
13608                delete this._callbacks[type];
13609            }
13610            return this;
13611        }
13612        function trigger(types) {
13613            var type, callbacks, args, syncFlush, asyncFlush;
13614            if (!this._callbacks) {
13615                return this;
13616            }
13617            types = types.split(splitter);
13618            args = [].slice.call(arguments, 1);
13619            while ((type = types.shift()) && (callbacks = this._callbacks[type])) {
13620                syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));
13621                asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));
13622                syncFlush() && nextTick(asyncFlush);
13623            }
13624            return this;
13625        }
13626        function getFlush(callbacks, context, args) {
13627            return flush;
13628            function flush() {
13629                var cancelled;
13630                for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) {
13631                    cancelled = callbacks[i].apply(context, args) === false;
13632                }
13633                return !cancelled;
13634            }
13635        }
13636        function getNextTick() {
13637            var nextTickFn;
13638            if (window.setImmediate) {
13639                nextTickFn = function nextTickSetImmediate(fn) {
13640                    setImmediate(function() {
13641                        fn();
13642                    });
13643                };
13644            } else {
13645                nextTickFn = function nextTickSetTimeout(fn) {
13646                    setTimeout(function() {
13647                        fn();
13648                    }, 0);
13649                };
13650            }
13651            return nextTickFn;
13652        }
13653        function bindContext(fn, context) {
13654            return fn.bind ? fn.bind(context) : function() {
13655                fn.apply(context, [].slice.call(arguments, 0));
13656            };
13657        }
13658    }();
13659    var highlight = function(doc) {
13660        "use strict";
13661        var defaults = {
13662            node: null,
13663            pattern: null,
13664            tagName: "strong",
13665            className: null,
13666            wordsOnly: false,
13667            caseSensitive: false
13668        };
13669        return function hightlight(o) {
13670            var regex;
13671            o = _.mixin({}, defaults, o);
13672            if (!o.node || !o.pattern) {
13673                return;
13674            }
13675            o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];
13676            regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);
13677            traverse(o.node, hightlightTextNode);
13678            function hightlightTextNode(textNode) {
13679                var match, patternNode, wrapperNode;
13680                if (match = regex.exec(textNode.data)) {
13681                    wrapperNode = doc.createElement(o.tagName);
13682                    o.className && (wrapperNode.className = o.className);
13683                    patternNode = textNode.splitText(match.index);
13684                    patternNode.splitText(match[0].length);
13685                    wrapperNode.appendChild(patternNode.cloneNode(true));
13686                    textNode.parentNode.replaceChild(wrapperNode, patternNode);
13687                }
13688                return !!match;
13689            }
13690            function traverse(el, hightlightTextNode) {
13691                var childNode, TEXT_NODE_TYPE = 3;
13692                for (var i = 0; i < el.childNodes.length; i++) {
13693                    childNode = el.childNodes[i];
13694                    if (childNode.nodeType === TEXT_NODE_TYPE) {
13695                        i += hightlightTextNode(childNode) ? 1 : 0;
13696                    } else {
13697                        traverse(childNode, hightlightTextNode);
13698                    }
13699                }
13700            }
13701        };
13702        function getRegex(patterns, caseSensitive, wordsOnly) {
13703            var escapedPatterns = [], regexStr;
13704            for (var i = 0, len = patterns.length; i < len; i++) {
13705                escapedPatterns.push(_.escapeRegExChars(patterns[i]));
13706            }
13707            regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")";
13708            return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i");
13709        }
13710    }(window.document);
13711    var Input = function() {
13712        "use strict";
13713        var specialKeyCodeMap;
13714        specialKeyCodeMap = {
13715            9: "tab",
13716            27: "esc",
13717            37: "left",
13718            39: "right",
13719            13: "enter",
13720            38: "up",
13721            40: "down"
13722        };
13723        function Input(o, www) {
13724            o = o || {};
13725            if (!o.input) {
13726                $.error("input is missing");
13727            }
13728            www.mixin(this);
13729            this.$hint = $(o.hint);
13730            this.$input = $(o.input);
13731            this.query = this.$input.val();
13732            this.queryWhenFocused = this.hasFocus() ? this.query : null;
13733            this.$overflowHelper = buildOverflowHelper(this.$input);
13734            this._checkLanguageDirection();
13735            if (this.$hint.length === 0) {
13736                this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;
13737            }
13738        }
13739        Input.normalizeQuery = function(str) {
13740            return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " ");
13741        };
13742        _.mixin(Input.prototype, EventEmitter, {
13743            _onBlur: function onBlur() {
13744                this.resetInputValue();
13745                this.trigger("blurred");
13746            },
13747            _onFocus: function onFocus() {
13748                this.queryWhenFocused = this.query;
13749                this.trigger("focused");
13750            },
13751            _onKeydown: function onKeydown($e) {
13752                var keyName = specialKeyCodeMap[$e.which || $e.keyCode];
13753                this._managePreventDefault(keyName, $e);
13754                if (keyName && this._shouldTrigger(keyName, $e)) {
13755                    this.trigger(keyName + "Keyed", $e);
13756                }
13757            },
13758            _onInput: function onInput() {
13759                this._setQuery(this.getInputValue());
13760                this.clearHintIfInvalid();
13761                this._checkLanguageDirection();
13762            },
13763            _managePreventDefault: function managePreventDefault(keyName, $e) {
13764                var preventDefault;
13765                switch (keyName) {
13766                  case "up":
13767                  case "down":
13768                    preventDefault = !withModifier($e);
13769                    break;
13770
13771                  default:
13772                    preventDefault = false;
13773                }
13774                preventDefault && $e.preventDefault();
13775            },
13776            _shouldTrigger: function shouldTrigger(keyName, $e) {
13777                var trigger;
13778                switch (keyName) {
13779                  case "tab":
13780                    trigger = !withModifier($e);
13781                    break;
13782
13783                  default:
13784                    trigger = true;
13785                }
13786                return trigger;
13787            },
13788            _checkLanguageDirection: function checkLanguageDirection() {
13789                var dir = (this.$input.css("direction") || "ltr").toLowerCase();
13790                if (this.dir !== dir) {
13791                    this.dir = dir;
13792                    this.$hint.attr("dir", dir);
13793                    this.trigger("langDirChanged", dir);
13794                }
13795            },
13796            _setQuery: function setQuery(val, silent) {
13797                var areEquivalent, hasDifferentWhitespace;
13798                areEquivalent = areQueriesEquivalent(val, this.query);
13799                hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false;
13800                this.query = val;
13801                if (!silent && !areEquivalent) {
13802                    this.trigger("queryChanged", this.query);
13803                } else if (!silent && hasDifferentWhitespace) {
13804                    this.trigger("whitespaceChanged", this.query);
13805                }
13806            },
13807            bind: function() {
13808                var that = this, onBlur, onFocus, onKeydown, onInput;
13809                onBlur = _.bind(this._onBlur, this);
13810                onFocus = _.bind(this._onFocus, this);
13811                onKeydown = _.bind(this._onKeydown, this);
13812                onInput = _.bind(this._onInput, this);
13813                this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown);
13814                if (!_.isMsie() || _.isMsie() > 9) {
13815                    this.$input.on("input.tt", onInput);
13816                } else {
13817                    this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) {
13818                        if (specialKeyCodeMap[$e.which || $e.keyCode]) {
13819                            return;
13820                        }
13821                        _.defer(_.bind(that._onInput, that, $e));
13822                    });
13823                }
13824                return this;
13825            },
13826            focus: function focus() {
13827                this.$input.focus();
13828            },
13829            blur: function blur() {
13830                this.$input.blur();
13831            },
13832            getLangDir: function getLangDir() {
13833                return this.dir;
13834            },
13835            getQuery: function getQuery() {
13836                return this.query || "";
13837            },
13838            setQuery: function setQuery(val, silent) {
13839                this.setInputValue(val);
13840                this._setQuery(val, silent);
13841            },
13842            hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() {
13843                return this.query !== this.queryWhenFocused;
13844            },
13845            getInputValue: function getInputValue() {
13846                return this.$input.val();
13847            },
13848            setInputValue: function setInputValue(value) {
13849                this.$input.val(value);
13850                this.clearHintIfInvalid();
13851                this._checkLanguageDirection();
13852            },
13853            resetInputValue: function resetInputValue() {
13854                this.setInputValue(this.query);
13855            },
13856            getHint: function getHint() {
13857                return this.$hint.val();
13858            },
13859            setHint: function setHint(value) {
13860                this.$hint.val(value);
13861            },
13862            clearHint: function clearHint() {
13863                this.setHint("");
13864            },
13865            clearHintIfInvalid: function clearHintIfInvalid() {
13866                var val, hint, valIsPrefixOfHint, isValid;
13867                val = this.getInputValue();
13868                hint = this.getHint();
13869                valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;
13870                isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow();
13871                !isValid && this.clearHint();
13872            },
13873            hasFocus: function hasFocus() {
13874                return this.$input.is(":focus");
13875            },
13876            hasOverflow: function hasOverflow() {
13877                var constraint = this.$input.width() - 2;
13878                this.$overflowHelper.text(this.getInputValue());
13879                return this.$overflowHelper.width() >= constraint;
13880            },
13881            isCursorAtEnd: function() {
13882                var valueLength, selectionStart, range;
13883                valueLength = this.$input.val().length;
13884                selectionStart = this.$input[0].selectionStart;
13885                if (_.isNumber(selectionStart)) {
13886                    return selectionStart === valueLength;
13887                } else if (document.selection) {
13888                    range = document.selection.createRange();
13889                    range.moveStart("character", -valueLength);
13890                    return valueLength === range.text.length;
13891                }
13892                return true;
13893            },
13894            destroy: function destroy() {
13895                this.$hint.off(".tt");
13896                this.$input.off(".tt");
13897                this.$overflowHelper.remove();
13898                this.$hint = this.$input = this.$overflowHelper = $("<div>");
13899            }
13900        });
13901        return Input;
13902        function buildOverflowHelper($input) {
13903            return $('<pre aria-hidden="true"></pre>').css({
13904                position: "absolute",
13905                visibility: "hidden",
13906                whiteSpace: "pre",
13907                fontFamily: $input.css("font-family"),
13908                fontSize: $input.css("font-size"),
13909                fontStyle: $input.css("font-style"),
13910                fontVariant: $input.css("font-variant"),
13911                fontWeight: $input.css("font-weight"),
13912                wordSpacing: $input.css("word-spacing"),
13913                letterSpacing: $input.css("letter-spacing"),
13914                textIndent: $input.css("text-indent"),
13915                textRendering: $input.css("text-rendering"),
13916                textTransform: $input.css("text-transform")
13917            }).insertAfter($input);
13918        }
13919        function areQueriesEquivalent(a, b) {
13920            return Input.normalizeQuery(a) === Input.normalizeQuery(b);
13921        }
13922        function withModifier($e) {
13923            return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;
13924        }
13925    }();
13926    var Dataset = function() {
13927        "use strict";
13928        var keys, nameGenerator;
13929        keys = {
13930            val: "tt-selectable-display",
13931            obj: "tt-selectable-object"
13932        };
13933        nameGenerator = _.getIdGenerator();
13934        function Dataset(o, www) {
13935            o = o || {};
13936            o.templates = o.templates || {};
13937            o.templates.notFound = o.templates.notFound || o.templates.empty;
13938            if (!o.source) {
13939                $.error("missing source");
13940            }
13941            if (!o.node) {
13942                $.error("missing node");
13943            }
13944            if (o.name && !isValidName(o.name)) {
13945                $.error("invalid dataset name: " + o.name);
13946            }
13947            www.mixin(this);
13948            this.highlight = !!o.highlight;
13949            this.name = o.name || nameGenerator();
13950            this.limit = o.limit || 5;
13951            this.displayFn = getDisplayFn(o.display || o.displayKey);
13952            this.templates = getTemplates(o.templates, this.displayFn);
13953            this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source;
13954            this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async;
13955            this._resetLastSuggestion();
13956            this.$el = $(o.node).addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name);
13957        }
13958        Dataset.extractData = function extractData(el) {
13959            var $el = $(el);
13960            if ($el.data(keys.obj)) {
13961                return {
13962                    val: $el.data(keys.val) || "",
13963                    obj: $el.data(keys.obj) || null
13964                };
13965            }
13966            return null;
13967        };
13968        _.mixin(Dataset.prototype, EventEmitter, {
13969            _overwrite: function overwrite(query, suggestions) {
13970                suggestions = suggestions || [];
13971                if (suggestions.length) {
13972                    this._renderSuggestions(query, suggestions);
13973                } else if (this.async && this.templates.pending) {
13974                    this._renderPending(query);
13975                } else if (!this.async && this.templates.notFound) {
13976                    this._renderNotFound(query);
13977                } else {
13978                    this._empty();
13979                }
13980                this.trigger("rendered", this.name, suggestions, false);
13981            },
13982            _append: function append(query, suggestions) {
13983                suggestions = suggestions || [];
13984                if (suggestions.length && this.$lastSuggestion.length) {
13985                    this._appendSuggestions(query, suggestions);
13986                } else if (suggestions.length) {
13987                    this._renderSuggestions(query, suggestions);
13988                } else if (!this.$lastSuggestion.length && this.templates.notFound) {
13989                    this._renderNotFound(query);
13990                }
13991                this.trigger("rendered", this.name, suggestions, true);
13992            },
13993            _renderSuggestions: function renderSuggestions(query, suggestions) {
13994                var $fragment;
13995                $fragment = this._getSuggestionsFragment(query, suggestions);
13996                this.$lastSuggestion = $fragment.children().last();
13997                this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions));
13998            },
13999            _appendSuggestions: function appendSuggestions(query, suggestions) {
14000                var $fragment, $lastSuggestion;
14001                $fragment = this._getSuggestionsFragment(query, suggestions);
14002                $lastSuggestion = $fragment.children().last();
14003                this.$lastSuggestion.after($fragment);
14004                this.$lastSuggestion = $lastSuggestion;
14005            },
14006            _renderPending: function renderPending(query) {
14007                var template = this.templates.pending;
14008                this._resetLastSuggestion();
14009                template && this.$el.html(template({
14010                    query: query,
14011                    dataset: this.name
14012                }));
14013            },
14014            _renderNotFound: function renderNotFound(query) {
14015                var template = this.templates.notFound;
14016                this._resetLastSuggestion();
14017                template && this.$el.html(template({
14018                    query: query,
14019                    dataset: this.name
14020                }));
14021            },
14022            _empty: function empty() {
14023                this.$el.empty();
14024                this._resetLastSuggestion();
14025            },
14026            _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) {
14027                var that = this, fragment;
14028                fragment = document.createDocumentFragment();
14029                _.each(suggestions, function getSuggestionNode(suggestion) {
14030                    var $el, context;
14031                    context = that._injectQuery(query, suggestion);
14032                    $el = $(that.templates.suggestion(context)).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable);
14033                    fragment.appendChild($el[0]);
14034                });
14035                this.highlight && highlight({
14036                    className: this.classes.highlight,
14037                    node: fragment,
14038                    pattern: query
14039                });
14040                return $(fragment);
14041            },
14042            _getFooter: function getFooter(query, suggestions) {
14043                return this.templates.footer ? this.templates.footer({
14044                    query: query,
14045                    suggestions: suggestions,
14046                    dataset: this.name
14047                }) : null;
14048            },
14049            _getHeader: function getHeader(query, suggestions) {
14050                return this.templates.header ? this.templates.header({
14051                    query: query,
14052                    suggestions: suggestions,
14053                    dataset: this.name
14054                }) : null;
14055            },
14056            _resetLastSuggestion: function resetLastSuggestion() {
14057                this.$lastSuggestion = $();
14058            },
14059            _injectQuery: function injectQuery(query, obj) {
14060                return _.isObject(obj) ? _.mixin({
14061                    _query: query
14062                }, obj) : obj;
14063            },
14064            update: function update(query) {
14065                var that = this, canceled = false, syncCalled = false, rendered = 0;
14066                this.cancel();
14067                this.cancel = function cancel() {
14068                    canceled = true;
14069                    that.cancel = $.noop;
14070                    that.async && that.trigger("asyncCanceled", query);
14071                };
14072                this.source(query, sync, async);
14073                !syncCalled && sync([]);
14074                function sync(suggestions) {
14075                    if (syncCalled) {
14076                        return;
14077                    }
14078                    syncCalled = true;
14079                    suggestions = (suggestions || []).slice(0, that.limit);
14080                    rendered = suggestions.length;
14081                    that._overwrite(query, suggestions);
14082                    if (rendered < that.limit && that.async) {
14083                        that.trigger("asyncRequested", query);
14084                    }
14085                }
14086                function async(suggestions) {
14087                    suggestions = suggestions || [];
14088                    if (!canceled && rendered < that.limit) {
14089                        that.cancel = $.noop;
14090                        rendered += suggestions.length;
14091                        that._append(query, suggestions.slice(0, that.limit - rendered));
14092                        that.async && that.trigger("asyncReceived", query);
14093                    }
14094                }
14095            },
14096            cancel: $.noop,
14097            clear: function clear() {
14098                this._empty();
14099                this.cancel();
14100                this.trigger("cleared");
14101            },
14102            isEmpty: function isEmpty() {
14103                return this.$el.is(":empty");
14104            },
14105            destroy: function destroy() {
14106                this.$el = $("<div>");
14107            }
14108        });
14109        return Dataset;
14110        function getDisplayFn(display) {
14111            display = display || _.stringify;
14112            return _.isFunction(display) ? display : displayFn;
14113            function displayFn(obj) {
14114                return obj[display];
14115            }
14116        }
14117        function getTemplates(templates, displayFn) {
14118            return {
14119                notFound: templates.notFound && _.templatify(templates.notFound),
14120                pending: templates.pending && _.templatify(templates.pending),
14121                header: templates.header && _.templatify(templates.header),
14122                footer: templates.footer && _.templatify(templates.footer),
14123                suggestion: templates.suggestion || suggestionTemplate
14124            };
14125            function suggestionTemplate(context) {
14126                return $("<div>").text(displayFn(context));
14127            }
14128        }
14129        function isValidName(str) {
14130            return /^[_a-zA-Z0-9-]+$/.test(str);
14131        }
14132    }();
14133    var Menu = function() {
14134        "use strict";
14135        function Menu(o, www) {
14136            var that = this;
14137            o = o || {};
14138            if (!o.node) {
14139                $.error("node is required");
14140            }
14141            www.mixin(this);
14142            this.$node = $(o.node);
14143            this.query = null;
14144            this.datasets = _.map(o.datasets, initializeDataset);
14145            function initializeDataset(oDataset) {
14146                var node = that.$node.find(oDataset.node).first();
14147                oDataset.node = node.length ? node : $("<div>").appendTo(that.$node);
14148                return new Dataset(oDataset, www);
14149            }
14150        }
14151        _.mixin(Menu.prototype, EventEmitter, {
14152            _onSelectableClick: function onSelectableClick($e) {
14153                this.trigger("selectableClicked", $($e.currentTarget));
14154            },
14155            _onRendered: function onRendered(type, dataset, suggestions, async) {
14156                this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
14157                this.trigger("datasetRendered", dataset, suggestions, async);
14158            },
14159            _onCleared: function onCleared() {
14160                this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
14161                this.trigger("datasetCleared");
14162            },
14163            _propagate: function propagate() {
14164                this.trigger.apply(this, arguments);
14165            },
14166            _allDatasetsEmpty: function allDatasetsEmpty() {
14167                return _.every(this.datasets, isDatasetEmpty);
14168                function isDatasetEmpty(dataset) {
14169                    return dataset.isEmpty();
14170                }
14171            },
14172            _getSelectables: function getSelectables() {
14173                return this.$node.find(this.selectors.selectable);
14174            },
14175            _removeCursor: function _removeCursor() {
14176                var $selectable = this.getActiveSelectable();
14177                $selectable && $selectable.removeClass(this.classes.cursor);
14178            },
14179            _ensureVisible: function ensureVisible($el) {
14180                var elTop, elBottom, nodeScrollTop, nodeHeight;
14181                elTop = $el.position().top;
14182                elBottom = elTop + $el.outerHeight(true);
14183                nodeScrollTop = this.$node.scrollTop();
14184                nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10);
14185                if (elTop < 0) {
14186                    this.$node.scrollTop(nodeScrollTop + elTop);
14187                } else if (nodeHeight < elBottom) {
14188                    this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight));
14189                }
14190            },
14191            bind: function() {
14192                var that = this, onSelectableClick;
14193                onSelectableClick = _.bind(this._onSelectableClick, this);
14194                this.$node.on("click.tt", this.selectors.selectable, onSelectableClick);
14195                _.each(this.datasets, function(dataset) {
14196                    dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that);
14197                });
14198                return this;
14199            },
14200            isOpen: function isOpen() {
14201                return this.$node.hasClass(this.classes.open);
14202            },
14203            open: function open() {
14204                this.$node.addClass(this.classes.open);
14205            },
14206            close: function close() {
14207                this.$node.removeClass(this.classes.open);
14208                this._removeCursor();
14209            },
14210            setLanguageDirection: function setLanguageDirection(dir) {
14211                this.$node.attr("dir", dir);
14212            },
14213            selectableRelativeToCursor: function selectableRelativeToCursor(delta) {
14214                var $selectables, $oldCursor, oldIndex, newIndex;
14215                $oldCursor = this.getActiveSelectable();
14216                $selectables = this._getSelectables();
14217                oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1;
14218                newIndex = oldIndex + delta;
14219                newIndex = (newIndex + 1) % ($selectables.length + 1) - 1;
14220                newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex;
14221                return newIndex === -1 ? null : $selectables.eq(newIndex);
14222            },
14223            setCursor: function setCursor($selectable) {
14224                this._removeCursor();
14225                if ($selectable = $selectable && $selectable.first()) {
14226                    $selectable.addClass(this.classes.cursor);
14227                    this._ensureVisible($selectable);
14228                }
14229            },
14230            getSelectableData: function getSelectableData($el) {
14231                return $el && $el.length ? Dataset.extractData($el) : null;
14232            },
14233            getActiveSelectable: function getActiveSelectable() {
14234                var $selectable = this._getSelectables().filter(this.selectors.cursor).first();
14235                return $selectable.length ? $selectable : null;
14236            },
14237            getTopSelectable: function getTopSelectable() {
14238                var $selectable = this._getSelectables().first();
14239                return $selectable.length ? $selectable : null;
14240            },
14241            update: function update(query) {
14242                var isValidUpdate = query !== this.query;
14243                if (isValidUpdate) {
14244                    this.query = query;
14245                    _.each(this.datasets, updateDataset);
14246                }
14247                return isValidUpdate;
14248                function updateDataset(dataset) {
14249                    dataset.update(query);
14250                }
14251            },
14252            empty: function empty() {
14253                _.each(this.datasets, clearDataset);
14254                this.query = null;
14255                this.$node.addClass(this.classes.empty);
14256                function clearDataset(dataset) {
14257                    dataset.clear();
14258                }
14259            },
14260            destroy: function destroy() {
14261                this.$node.off(".tt");
14262                this.$node = $("<div>");
14263                _.each(this.datasets, destroyDataset);
14264                function destroyDataset(dataset) {
14265                    dataset.destroy();
14266                }
14267            }
14268        });
14269        return Menu;
14270    }();
14271    var DefaultMenu = function() {
14272        "use strict";
14273        var s = Menu.prototype;
14274        function DefaultMenu() {
14275            Menu.apply(this, [].slice.call(arguments, 0));
14276        }
14277        _.mixin(DefaultMenu.prototype, Menu.prototype, {
14278            open: function open() {
14279                !this._allDatasetsEmpty() && this._show();
14280                return s.open.apply(this, [].slice.call(arguments, 0));
14281            },
14282            close: function close() {
14283                this._hide();
14284                return s.close.apply(this, [].slice.call(arguments, 0));
14285            },
14286            _onRendered: function onRendered() {
14287                if (this._allDatasetsEmpty()) {
14288                    this._hide();
14289                } else {
14290                    this.isOpen() && this._show();
14291                }
14292                return s._onRendered.apply(this, [].slice.call(arguments, 0));
14293            },
14294            _onCleared: function onCleared() {
14295                if (this._allDatasetsEmpty()) {
14296                    this._hide();
14297                } else {
14298                    this.isOpen() && this._show();
14299                }
14300                return s._onCleared.apply(this, [].slice.call(arguments, 0));
14301            },
14302            setLanguageDirection: function setLanguageDirection(dir) {
14303                this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl);
14304                return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0));
14305            },
14306            _hide: function hide() {
14307                this.$node.hide();
14308            },
14309            _show: function show() {
14310                this.$node.css("display", "block");
14311            }
14312        });
14313        return DefaultMenu;
14314    }();
14315    var Typeahead = function() {
14316        "use strict";
14317        function Typeahead(o, www) {
14318            var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged;
14319            o = o || {};
14320            if (!o.input) {
14321                $.error("missing input");
14322            }
14323            if (!o.menu) {
14324                $.error("missing menu");
14325            }
14326            if (!o.eventBus) {
14327                $.error("missing event bus");
14328            }
14329            www.mixin(this);
14330            this.eventBus = o.eventBus;
14331            this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
14332            this.input = o.input;
14333            this.menu = o.menu;
14334            this.enabled = true;
14335            this.active = false;
14336            this.input.hasFocus() && this.activate();
14337            this.dir = this.input.getLangDir();
14338            this._hacks();
14339            this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this);
14340            onFocused = c(this, "activate", "open", "_onFocused");
14341            onBlurred = c(this, "deactivate", "_onBlurred");
14342            onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed");
14343            onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed");
14344            onEscKeyed = c(this, "isActive", "_onEscKeyed");
14345            onUpKeyed = c(this, "isActive", "open", "_onUpKeyed");
14346            onDownKeyed = c(this, "isActive", "open", "_onDownKeyed");
14347            onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed");
14348            onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed");
14349            onQueryChanged = c(this, "_openIfActive", "_onQueryChanged");
14350            onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged");
14351            this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this);
14352        }
14353        _.mixin(Typeahead.prototype, {
14354            _hacks: function hacks() {
14355                var $input, $menu;
14356                $input = this.input.$input || $("<div>");
14357                $menu = this.menu.$node || $("<div>");
14358                $input.on("blur.tt", function($e) {
14359                    var active, isActive, hasActive;
14360                    active = document.activeElement;
14361                    isActive = $menu.is(active);
14362                    hasActive = $menu.has(active).length > 0;
14363                    if (_.isMsie() && (isActive || hasActive)) {
14364                        $e.preventDefault();
14365                        $e.stopImmediatePropagation();
14366                        _.defer(function() {
14367                            $input.focus();
14368                        });
14369                    }
14370                });
14371                $menu.on("mousedown.tt", function($e) {
14372                    $e.preventDefault();
14373                });
14374            },
14375            _onSelectableClicked: function onSelectableClicked(type, $el) {
14376                this.select($el);
14377            },
14378            _onDatasetCleared: function onDatasetCleared() {
14379                this._updateHint();
14380            },
14381            _onDatasetRendered: function onDatasetRendered(type, dataset, suggestions, async) {
14382                this._updateHint();
14383                this.eventBus.trigger("render", suggestions, async, dataset);
14384            },
14385            _onAsyncRequested: function onAsyncRequested(type, dataset, query) {
14386                this.eventBus.trigger("asyncrequest", query, dataset);
14387            },
14388            _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) {
14389                this.eventBus.trigger("asynccancel", query, dataset);
14390            },
14391            _onAsyncReceived: function onAsyncReceived(type, dataset, query) {
14392                this.eventBus.trigger("asyncreceive", query, dataset);
14393            },
14394            _onFocused: function onFocused() {
14395                this._minLengthMet() && this.menu.update(this.input.getQuery());
14396            },
14397            _onBlurred: function onBlurred() {
14398                if (this.input.hasQueryChangedSinceLastFocus()) {
14399                    this.eventBus.trigger("change", this.input.getQuery());
14400                }
14401            },
14402            _onEnterKeyed: function onEnterKeyed(type, $e) {
14403                var $selectable;
14404                if ($selectable = this.menu.getActiveSelectable()) {
14405                    this.select($selectable) && $e.preventDefault();
14406                }
14407            },
14408            _onTabKeyed: function onTabKeyed(type, $e) {
14409                var $selectable;
14410                if ($selectable = this.menu.getActiveSelectable()) {
14411                    this.select($selectable) && $e.preventDefault();
14412                } else if ($selectable = this.menu.getTopSelectable()) {
14413                    this.autocomplete($selectable) && $e.preventDefault();
14414                }
14415            },
14416            _onEscKeyed: function onEscKeyed() {
14417                this.close();
14418            },
14419            _onUpKeyed: function onUpKeyed() {
14420                this.moveCursor(-1);
14421            },
14422            _onDownKeyed: function onDownKeyed() {
14423                this.moveCursor(+1);
14424            },
14425            _onLeftKeyed: function onLeftKeyed() {
14426                if (this.dir === "rtl" && this.input.isCursorAtEnd()) {
14427                    this.autocomplete(this.menu.getTopSelectable());
14428                }
14429            },
14430            _onRightKeyed: function onRightKeyed() {
14431                if (this.dir === "ltr" && this.input.isCursorAtEnd()) {
14432                    this.autocomplete(this.menu.getTopSelectable());
14433                }
14434            },
14435            _onQueryChanged: function onQueryChanged(e, query) {
14436                this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty();
14437            },
14438            _onWhitespaceChanged: function onWhitespaceChanged() {
14439                this._updateHint();
14440            },
14441            _onLangDirChanged: function onLangDirChanged(e, dir) {
14442                if (this.dir !== dir) {
14443                    this.dir = dir;
14444                    this.menu.setLanguageDirection(dir);
14445                }
14446            },
14447            _openIfActive: function openIfActive() {
14448                this.isActive() && this.open();
14449            },
14450            _minLengthMet: function minLengthMet(query) {
14451                query = _.isString(query) ? query : this.input.getQuery() || "";
14452                return query.length >= this.minLength;
14453            },
14454            _updateHint: function updateHint() {
14455                var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match;
14456                $selectable = this.menu.getTopSelectable();
14457                data = this.menu.getSelectableData($selectable);
14458                val = this.input.getInputValue();
14459                if (data && !_.isBlankString(val) && !this.input.hasOverflow()) {
14460                    query = Input.normalizeQuery(val);
14461                    escapedQuery = _.escapeRegExChars(query);
14462                    frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i");
14463                    match = frontMatchRegEx.exec(data.val);
14464                    match && this.input.setHint(val + match[1]);
14465                } else {
14466                    this.input.clearHint();
14467                }
14468            },
14469            isEnabled: function isEnabled() {
14470                return this.enabled;
14471            },
14472            enable: function enable() {
14473                this.enabled = true;
14474            },
14475            disable: function disable() {
14476                this.enabled = false;
14477            },
14478            isActive: function isActive() {
14479                return this.active;
14480            },
14481            activate: function activate() {
14482                if (this.isActive()) {
14483                    return true;
14484                } else if (!this.isEnabled() || this.eventBus.before("active")) {
14485                    return false;
14486                } else {
14487                    this.active = true;
14488                    this.eventBus.trigger("active");
14489                    return true;
14490                }
14491            },
14492            deactivate: function deactivate() {
14493                if (!this.isActive()) {
14494                    return true;
14495                } else if (this.eventBus.before("idle")) {
14496                    return false;
14497                } else {
14498                    this.active = false;
14499                    this.close();
14500                    this.eventBus.trigger("idle");
14501                    return true;
14502                }
14503            },
14504            isOpen: function isOpen() {
14505                return this.menu.isOpen();
14506            },
14507            open: function open() {
14508                if (!this.isOpen() && !this.eventBus.before("open")) {
14509                    this.menu.open();
14510                    this._updateHint();
14511                    this.eventBus.trigger("open");
14512                }
14513                return this.isOpen();
14514            },
14515            close: function close() {
14516                if (this.isOpen() && !this.eventBus.before("close")) {
14517                    this.menu.close();
14518                    this.input.clearHint();
14519                    this.input.resetInputValue();
14520                    this.eventBus.trigger("close");
14521                }
14522                return !this.isOpen();
14523            },
14524            setVal: function setVal(val) {
14525                this.input.setQuery(_.toStr(val));
14526            },
14527            getVal: function getVal() {
14528                return this.input.getQuery();
14529            },
14530            select: function select($selectable) {
14531                var data = this.menu.getSelectableData($selectable);
14532                if (data && !this.eventBus.before("select", data.obj)) {
14533                    this.input.setQuery(data.val, true);
14534                    this.eventBus.trigger("select", data.obj);
14535                    this.close();
14536                    return true;
14537                }
14538                return false;
14539            },
14540            autocomplete: function autocomplete($selectable) {
14541                var query, data, isValid;
14542                query = this.input.getQuery();
14543                data = this.menu.getSelectableData($selectable);
14544                isValid = data && query !== data.val;
14545                if (isValid && !this.eventBus.before("autocomplete", data.obj)) {
14546                    this.input.setQuery(data.val);
14547                    this.eventBus.trigger("autocomplete", data.obj);
14548                    return true;
14549                }
14550                return false;
14551            },
14552            moveCursor: function moveCursor(delta) {
14553                var query, $candidate, data, payload, cancelMove;
14554                query = this.input.getQuery();
14555                $candidate = this.menu.selectableRelativeToCursor(delta);
14556                data = this.menu.getSelectableData($candidate);
14557                payload = data ? data.obj : null;
14558                cancelMove = this._minLengthMet() && this.menu.update(query);
14559                if (!cancelMove && !this.eventBus.before("cursorchange", payload)) {
14560                    this.menu.setCursor($candidate);
14561                    if (data) {
14562                        this.input.setInputValue(data.val);
14563                    } else {
14564                        this.input.resetInputValue();
14565                        this._updateHint();
14566                    }
14567                    this.eventBus.trigger("cursorchange", payload);
14568                    return true;
14569                }
14570                return false;
14571            },
14572            destroy: function destroy() {
14573                this.input.destroy();
14574                this.menu.destroy();
14575            }
14576        });
14577        return Typeahead;
14578        function c(ctx) {
14579            var methods = [].slice.call(arguments, 1);
14580            return function() {
14581                var args = [].slice.call(arguments);
14582                _.each(methods, function(method) {
14583                    return ctx[method].apply(ctx, args);
14584                });
14585            };
14586        }
14587    }();
14588    (function() {
14589        "use strict";
14590        var old, keys, methods;
14591        old = $.fn.typeahead;
14592        keys = {
14593            www: "tt-www",
14594            attrs: "tt-attrs",
14595            typeahead: "tt-typeahead"
14596        };
14597        methods = {
14598            initialize: function initialize(o, datasets) {
14599                var www;
14600                datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);
14601                o = o || {};
14602                www = WWW(o.classNames);
14603                return this.each(attach);
14604                function attach() {
14605                    var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, typeahead, MenuConstructor;
14606                    _.each(datasets, function(d) {
14607                        d.highlight = !!o.highlight;
14608                    });
14609                    $input = $(this);
14610                    $wrapper = $(www.html.wrapper);
14611                    $hint = $elOrNull(o.hint);
14612                    $menu = $elOrNull(o.menu);
14613                    defaultHint = o.hint !== false && !$hint;
14614                    defaultMenu = o.menu !== false && !$menu;
14615                    defaultHint && ($hint = buildHintFromInput($input, www));
14616                    defaultMenu && ($menu = $(www.html.menu).css(www.css.menu));
14617                    $hint && $hint.val("");
14618                    $input = prepInput($input, www);
14619                    if (defaultHint || defaultMenu) {
14620                        $wrapper.css(www.css.wrapper);
14621                        $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint);
14622                        $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null);
14623                    }
14624                    MenuConstructor = defaultMenu ? DefaultMenu : Menu;
14625                    eventBus = new EventBus({
14626                        el: $input
14627                    });
14628                    input = new Input({
14629                        hint: $hint,
14630                        input: $input
14631                    }, www);
14632                    menu = new MenuConstructor({
14633                        node: $menu,
14634                        datasets: datasets
14635                    }, www);
14636                    typeahead = new Typeahead({
14637                        input: input,
14638                        menu: menu,
14639                        eventBus: eventBus,
14640                        minLength: o.minLength
14641                    }, www);
14642                    $input.data(keys.www, www);
14643                    $input.data(keys.typeahead, typeahead);
14644                }
14645            },
14646            isEnabled: function isEnabled() {
14647                var enabled;
14648                ttEach(this.first(), function(t) {
14649                    enabled = t.isEnabled();
14650                });
14651                return enabled;
14652            },
14653            enable: function enable() {
14654                ttEach(this, function(t) {
14655                    t.enable();
14656                });
14657                return this;
14658            },
14659            disable: function disable() {
14660                ttEach(this, function(t) {
14661                    t.disable();
14662                });
14663                return this;
14664            },
14665            isActive: function isActive() {
14666                var active;
14667                ttEach(this.first(), function(t) {
14668                    active = t.isActive();
14669                });
14670                return active;
14671            },
14672            activate: function activate() {
14673                ttEach(this, function(t) {
14674                    t.activate();
14675                });
14676                return this;
14677            },
14678            deactivate: function deactivate() {
14679                ttEach(this, function(t) {
14680                    t.deactivate();
14681                });
14682                return this;
14683            },
14684            isOpen: function isOpen() {
14685                var open;
14686                ttEach(this.first(), function(t) {
14687                    open = t.isOpen();
14688                });
14689                return open;
14690            },
14691            open: function open() {
14692                ttEach(this, function(t) {
14693                    t.open();
14694                });
14695                return this;
14696            },
14697            close: function close() {
14698                ttEach(this, function(t) {
14699                    t.close();
14700                });
14701                return this;
14702            },
14703            select: function select(el) {
14704                var success = false, $el = $(el);
14705                ttEach(this.first(), function(t) {
14706                    success = t.select($el);
14707                });
14708                return success;
14709            },
14710            autocomplete: function autocomplete(el) {
14711                var success = false, $el = $(el);
14712                ttEach(this.first(), function(t) {
14713                    success = t.autocomplete($el);
14714                });
14715                return success;
14716            },
14717            moveCursor: function moveCursoe(delta) {
14718                var success = false;
14719                ttEach(this.first(), function(t) {
14720                    success = t.moveCursor(delta);
14721                });
14722                return success;
14723            },
14724            val: function val(newVal) {
14725                var query;
14726                if (!arguments.length) {
14727                    ttEach(this.first(), function(t) {
14728                        query = t.getVal();
14729                    });
14730                    return query;
14731                } else {
14732                    ttEach(this, function(t) {
14733                        t.setVal(newVal);
14734                    });
14735                    return this;
14736                }
14737            },
14738            destroy: function destroy() {
14739                ttEach(this, function(typeahead, $input) {
14740                    revert($input);
14741                    typeahead.destroy();
14742                });
14743                return this;
14744            }
14745        };
14746        $.fn.typeahead = function(method) {
14747            if (methods[method]) {
14748                return methods[method].apply(this, [].slice.call(arguments, 1));
14749            } else {
14750                return methods.initialize.apply(this, arguments);
14751            }
14752        };
14753        $.fn.typeahead.noConflict = function noConflict() {
14754            $.fn.typeahead = old;
14755            return this;
14756        };
14757        function ttEach($els, fn) {
14758            $els.each(function() {
14759                var $input = $(this), typeahead;
14760                (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input);
14761            });
14762        }
14763        function buildHintFromInput($input, www) {
14764            return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({
14765                autocomplete: "off",
14766                spellcheck: "false",
14767                tabindex: -1
14768            });
14769        }
14770        function prepInput($input, www) {
14771            $input.data(keys.attrs, {
14772                dir: $input.attr("dir"),
14773                autocomplete: $input.attr("autocomplete"),
14774                spellcheck: $input.attr("spellcheck"),
14775                style: $input.attr("style")
14776            });
14777            $input.addClass(www.classes.input).attr({
14778                autocomplete: "off",
14779                spellcheck: false
14780            });
14781            try {
14782                !$input.attr("dir") && $input.attr("dir", "auto");
14783            } catch (e) {}
14784            return $input;
14785        }
14786        function getBackgroundStyles($el) {
14787            return {
14788                backgroundAttachment: $el.css("background-attachment"),
14789                backgroundClip: $el.css("background-clip"),
14790                backgroundColor: $el.css("background-color"),
14791                backgroundImage: $el.css("background-image"),
14792                backgroundOrigin: $el.css("background-origin"),
14793                backgroundPosition: $el.css("background-position"),
14794                backgroundRepeat: $el.css("background-repeat"),
14795                backgroundSize: $el.css("background-size")
14796            };
14797        }
14798        function revert($input) {
14799            var www, $wrapper;
14800            www = $input.data(keys.www);
14801            $wrapper = $input.parent().filter(www.selectors.wrapper);
14802            _.each($input.data(keys.attrs), function(val, key) {
14803                _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);
14804            });
14805            $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input);
14806            if ($wrapper.length) {
14807                $input.detach().insertAfter($wrapper);
14808                $wrapper.remove();
14809            }
14810        }
14811        function $elOrNull(obj) {
14812            var isValid, $el;
14813            isValid = _.isJQuery(obj) || _.isElement(obj);
14814            $el = isValid ? $(obj).first() : [];
14815            return $el.length ? $el : null;
14816        }
14817    })();
14818});
vendor: 47,604 bytes, lines 14818-16448
14818
14819/**!
14820
14821 @license
14822 handlebars v4.0.10
14823
14824Copyright (C) 2011-2016 by Yehuda Katz
14825
14826Permission is hereby granted, free of charge, to any person obtaining a copy
14827of this software and associated documentation files (the "Software"), to deal
14828in the Software without restriction, including without limitation the rights
14829to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14830copies of the Software, and to permit persons to whom the Software is
14831furnished to do so, subject to the following conditions:
14832
14833The above copyright notice and this permission notice shall be included in
14834all copies or substantial portions of the Software.
14835
14836THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14837IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14838FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14839AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14840LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
14841OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
14842THE SOFTWARE.
14843
14844*/
14845(function webpackUniversalModuleDefinition(root, factory) {
14846	if(typeof exports === 'object' && typeof module === 'object')
14847		module.exports = factory();
14848	else if(typeof define === 'function' && define.amd)
14849		define([], factory);
14850	else if(typeof exports === 'object')
14851		exports["Handlebars"] = factory();
14852	else
14853		root["Handlebars"] = factory();
14854})(this, function() {
14855return /******/ (function(modules) { // webpackBootstrap
14856/******/ 	// The module cache
14857/******/ 	var installedModules = {};
14858
14859/******/ 	// The require function
14860/******/ 	function __webpack_require__(moduleId) {
14861
14862/******/ 		// Check if module is in cache
14863/******/ 		if(installedModules[moduleId])
14864/******/ 			return installedModules[moduleId].exports;
14865
14866/******/ 		// Create a new module (and put it into the cache)
14867/******/ 		var module = installedModules[moduleId] = {
14868/******/ 			exports: {},
14869/******/ 			id: moduleId,
14870/******/ 			loaded: false
14871/******/ 		};
14872
14873/******/ 		// Execute the module function
14874/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
14875
14876/******/ 		// Flag the module as loaded
14877/******/ 		module.loaded = true;
14878
14879/******/ 		// Return the exports of the module
14880/******/ 		return module.exports;
14881/******/ 	}
14882
14883
14884/******/ 	// expose the modules object (__webpack_modules__)
14885/******/ 	__webpack_require__.m = modules;
14886
14887/******/ 	// expose the module cache
14888/******/ 	__webpack_require__.c = installedModules;
14889
14890/******/ 	// __webpack_public_path__
14891/******/ 	__webpack_require__.p = "";
14892
14893/******/ 	// Load entry module and return exports
14894/******/ 	return __webpack_require__(0);
14895/******/ })
14896/************************************************************************/
14897/******/ ([
14898/* 0 */
14899/***/ (function(module, exports, __webpack_require__) {
14900
14901	'use strict';
14902
14903	var _interopRequireDefault = __webpack_require__(1)['default'];
14904
14905	exports.__esModule = true;
14906
14907	var _handlebarsRuntime = __webpack_require__(2);
14908
14909	var _handlebarsRuntime2 = _interopRequireDefault(_handlebarsRuntime);
14910
14911	// Compiler imports
14912
14913	var _handlebarsCompilerAst = __webpack_require__(35);
14914
14915	var _handlebarsCompilerAst2 = _interopRequireDefault(_handlebarsCompilerAst);
14916
14917	var _handlebarsCompilerBase = __webpack_require__(36);
14918
14919	var _handlebarsCompilerCompiler = __webpack_require__(41);
14920
14921	var _handlebarsCompilerJavascriptCompiler = __webpack_require__(42);
14922
14923	var _handlebarsCompilerJavascriptCompiler2 = _interopRequireDefault(_handlebarsCompilerJavascriptCompiler);
14924
14925	var _handlebarsCompilerVisitor = __webpack_require__(39);
14926
14927	var _handlebarsCompilerVisitor2 = _interopRequireDefault(_handlebarsCompilerVisitor);
14928
14929	var _handlebarsNoConflict = __webpack_require__(34);
14930
14931	var _handlebarsNoConflict2 = _interopRequireDefault(_handlebarsNoConflict);
14932
14933	var _create = _handlebarsRuntime2['default'].create;
14934	function create() {
14935	  var hb = _create();
14936
14937	  hb.compile = function (input, options) {
14938	    return _handlebarsCompilerCompiler.compile(input, options, hb);
14939	  };
14940	  hb.precompile = function (input, options) {
14941	    return _handlebarsCompilerCompiler.precompile(input, options, hb);
14942	  };
14943
14944	  hb.AST = _handlebarsCompilerAst2['default'];
14945	  hb.Compiler = _handlebarsCompilerCompiler.Compiler;
14946	  hb.JavaScriptCompiler = _handlebarsCompilerJavascriptCompiler2['default'];
14947	  hb.Parser = _handlebarsCompilerBase.parser;
14948	  hb.parse = _handlebarsCompilerBase.parse;
14949
14950	  return hb;
14951	}
14952
14953	var inst = create();
14954	inst.create = create;
14955
14956	_handlebarsNoConflict2['default'](inst);
14957
14958	inst.Visitor = _handlebarsCompilerVisitor2['default'];
14959
14960	inst['default'] = inst;
14961
14962	exports['default'] = inst;
14963	module.exports = exports['default'];
14964
14965/***/ }),
14966/* 1 */
14967/***/ (function(module, exports) {
14968
14969	"use strict";
14970
14971	exports["default"] = function (obj) {
14972	  return obj && obj.__esModule ? obj : {
14973	    "default": obj
14974	  };
14975	};
14976
14977	exports.__esModule = true;
14978
14979/***/ }),
14980/* 2 */
14981/***/ (function(module, exports, __webpack_require__) {
14982
14983	'use strict';
14984
14985	var _interopRequireWildcard = __webpack_require__(3)['default'];
14986
14987	var _interopRequireDefault = __webpack_require__(1)['default'];
14988
14989	exports.__esModule = true;
14990
14991	var _handlebarsBase = __webpack_require__(4);
14992
14993	var base = _interopRequireWildcard(_handlebarsBase);
14994
14995	// Each of these augment the Handlebars object. No need to setup here.
14996	// (This is done to easily share code between commonjs and browse envs)
14997
14998	var _handlebarsSafeString = __webpack_require__(21);
14999
15000	var _handlebarsSafeString2 = _interopRequireDefault(_handlebarsSafeString);
15001
15002	var _handlebarsException = __webpack_require__(6);
15003
15004	var _handlebarsException2 = _interopRequireDefault(_handlebarsException);
15005
15006	var _handlebarsUtils = __webpack_require__(5);
15007
15008	var Utils = _interopRequireWildcard(_handlebarsUtils);
15009
15010	var _handlebarsRuntime = __webpack_require__(22);
15011
15012	var runtime = _interopRequireWildcard(_handlebarsRuntime);
15013
15014	var _handlebarsNoConflict = __webpack_require__(34);
15015
15016	var _handlebarsNoConflict2 = _interopRequireDefault(_handlebarsNoConflict);
15017
15018	// For compatibility and usage outside of module systems, make the Handlebars object a namespace
15019	function create() {
15020	  var hb = new base.HandlebarsEnvironment();
15021
15022	  Utils.extend(hb, base);
15023	  hb.SafeString = _handlebarsSafeString2['default'];
15024	  hb.Exception = _handlebarsException2['default'];
15025	  hb.Utils = Utils;
15026	  hb.escapeExpression = Utils.escapeExpression;
15027
15028	  hb.VM = runtime;
15029	  hb.template = function (spec) {
15030	    return runtime.template(spec, hb);
15031	  };
15032
15033	  return hb;
15034	}
15035
15036	var inst = create();
15037	inst.create = create;
15038
15039	_handlebarsNoConflict2['default'](inst);
15040
15041	inst['default'] = inst;
15042
15043	exports['default'] = inst;
15044	module.exports = exports['default'];
15045
15046/***/ }),
15047/* 3 */
15048/***/ (function(module, exports) {
15049
15050	"use strict";
15051
15052	exports["default"] = function (obj) {
15053	  if (obj && obj.__esModule) {
15054	    return obj;
15055	  } else {
15056	    var newObj = {};
15057
15058	    if (obj != null) {
15059	      for (var key in obj) {
15060	        if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key];
15061	      }
15062	    }
15063
15064	    newObj["default"] = obj;
15065	    return newObj;
15066	  }
15067	};
15068
15069	exports.__esModule = true;
15070
15071/***/ }),
15072/* 4 */
15073/***/ (function(module, exports, __webpack_require__) {
15074
15075	'use strict';
15076
15077	var _interopRequireDefault = __webpack_require__(1)['default'];
15078
15079	exports.__esModule = true;
15080	exports.HandlebarsEnvironment = HandlebarsEnvironment;
15081
15082	var _utils = __webpack_require__(5);
15083
15084	var _exception = __webpack_require__(6);
15085
15086	var _exception2 = _interopRequireDefault(_exception);
15087
15088	var _helpers = __webpack_require__(10);
15089
15090	var _decorators = __webpack_require__(18);
15091
15092	var _logger = __webpack_require__(20);
15093
15094	var _logger2 = _interopRequireDefault(_logger);
15095
15096	var VERSION = '4.0.10';
15097	exports.VERSION = VERSION;
15098	var COMPILER_REVISION = 7;
15099
15100	exports.COMPILER_REVISION = COMPILER_REVISION;
15101	var REVISION_CHANGES = {
15102	  1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
15103	  2: '== 1.0.0-rc.3',
15104	  3: '== 1.0.0-rc.4',
15105	  4: '== 1.x.x',
15106	  5: '== 2.0.0-alpha.x',
15107	  6: '>= 2.0.0-beta.1',
15108	  7: '>= 4.0.0'
15109	};
15110
15111	exports.REVISION_CHANGES = REVISION_CHANGES;
15112	var objectType = '[object Object]';
15113
15114	function HandlebarsEnvironment(helpers, partials, decorators) {
15115	  this.helpers = helpers || {};
15116	  this.partials = partials || {};
15117	  this.decorators = decorators || {};
15118
15119	  _helpers.registerDefaultHelpers(this);
15120	  _decorators.registerDefaultDecorators(this);
15121	}
15122
15123	HandlebarsEnvironment.prototype = {
15124	  constructor: HandlebarsEnvironment,
15125
15126	  logger: _logger2['default'],
15127	  log: _logger2['default'].log,
15128
15129	  registerHelper: function registerHelper(name, fn) {
15130	    if (_utils.toString.call(name) === objectType) {
15131	      if (fn) {
15132	        throw new _exception2['default']('Arg not supported with multiple helpers');
15133	      }
15134	      _utils.extend(this.helpers, name);
15135	    } else {
15136	      this.helpers[name] = fn;
15137	    }
15138	  },
15139	  unregisterHelper: function unregisterHelper(name) {
15140	    delete this.helpers[name];
15141	  },
15142
15143	  registerPartial: function registerPartial(name, partial) {
15144	    if (_utils.toString.call(name) === objectType) {
15145	      _utils.extend(this.partials, name);
15146	    } else {
15147	      if (typeof partial === 'undefined') {
15148	        throw new _exception2['default']('Attempting to register a partial called "' + name + '" as undefined');
15149	      }
15150	      this.partials[name] = partial;
15151	    }
15152	  },
15153	  unregisterPartial: function unregisterPartial(name) {
15154	    delete this.partials[name];
15155	  },
15156
15157	  registerDecorator: function registerDecorator(name, fn) {
15158	    if (_utils.toString.call(name) === objectType) {
15159	      if (fn) {
15160	        throw new _exception2['default']('Arg not supported with multiple decorators');
15161	      }
15162	      _utils.extend(this.decorators, name);
15163	    } else {
15164	      this.decorators[name] = fn;
15165	    }
15166	  },
15167	  unregisterDecorator: function unregisterDecorator(name) {
15168	    delete this.decorators[name];
15169	  }
15170	};
15171
15172	var log = _logger2['default'].log;
15173
15174	exports.log = log;
15175	exports.createFrame = _utils.createFrame;
15176	exports.logger = _logger2['default'];
15177
15178/***/ }),
15179/* 5 */
15180/***/ (function(module, exports) {
15181
15182	'use strict';
15183
15184	exports.__esModule = true;
15185	exports.extend = extend;
15186	exports.indexOf = indexOf;
15187	exports.escapeExpression = escapeExpression;
15188	exports.isEmpty = isEmpty;
15189	exports.createFrame = createFrame;
15190	exports.blockParams = blockParams;
15191	exports.appendContextPath = appendContextPath;
15192	var escape = {
15193	  '&': '&amp;',
15194	  '<': '&lt;',
15195	  '>': '&gt;',
15196	  '"': '&quot;',
15197	  "'": '&#x27;',
15198	  '`': '&#x60;',
15199	  '=': '&#x3D;'
15200	};
15201
15202	var badChars = /[&<>"'`=]/g,
15203	    possible = /[&<>"'`=]/;
15204
15205	function escapeChar(chr) {
15206	  return escape[chr];
15207	}
15208
15209	function extend(obj /* , ...source */) {
15210	  for (var i = 1; i < arguments.length; i++) {
15211	    for (var key in arguments[i]) {
15212	      if (Object.prototype.hasOwnProperty.call(arguments[i], key)) {
15213	        obj[key] = arguments[i][key];
15214	      }
15215	    }
15216	  }
15217
15218	  return obj;
15219	}
15220
15221	var toString = Object.prototype.toString;
15222
15223	exports.toString = toString;
15224	// Sourced from lodash
15225	// https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
15226	/* eslint-disable func-style */
15227	var isFunction = function isFunction(value) {
15228	  return typeof value === 'function';
15229	};
15230	// fallback for older versions of Chrome and Safari
15231	/* istanbul ignore next */
15232	if (isFunction(/x/)) {
15233	  exports.isFunction = isFunction = function (value) {
15234	    return typeof value === 'function' && toString.call(value) === '[object Function]';
15235	  };
15236	}
15237	exports.isFunction = isFunction;
15238
15239	/* eslint-enable func-style */
15240
15241	/* istanbul ignore next */
15242	var isArray = Array.isArray || function (value) {
15243	  return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false;
15244	};
15245
15246	exports.isArray = isArray;
15247	// Older IE versions do not directly support indexOf so we must implement our own, sadly.
15248
15249	function indexOf(array, value) {
15250	  for (var i = 0, len = array.length; i < len; i++) {
15251	    if (array[i] === value) {
15252	      return i;
15253	    }
15254	  }
15255	  return -1;
15256	}
15257
15258	function escapeExpression(string) {
15259	  if (typeof string !== 'string') {
15260	    // don't escape SafeStrings, since they're already safe
15261	    if (string && string.toHTML) {
15262	      return string.toHTML();
15263	    } else if (string == null) {
15264	      return '';
15265	    } else if (!string) {
15266	      return string + '';
15267	    }
15268
15269	    // Force a string conversion as this will be done by the append regardless and
15270	    // the regex test will do this transparently behind the scenes, causing issues if
15271	    // an object's to string has escaped characters in it.
15272	    string = '' + string;
15273	  }
15274
15275	  if (!possible.test(string)) {
15276	    return string;
15277	  }
15278	  return string.replace(badChars, escapeChar);
15279	}
15280
15281	function isEmpty(value) {
15282	  if (!value && value !== 0) {
15283	    return true;
15284	  } else if (isArray(value) && value.length === 0) {
15285	    return true;
15286	  } else {
15287	    return false;
15288	  }
15289	}
15290
15291	function createFrame(object) {
15292	  var frame = extend({}, object);
15293	  frame._parent = object;
15294	  return frame;
15295	}
15296
15297	function blockParams(params, ids) {
15298	  params.path = ids;
15299	  return params;
15300	}
15301
15302	function appendContextPath(contextPath, id) {
15303	  return (contextPath ? contextPath + '.' : '') + id;
15304	}
15305
15306/***/ }),
15307/* 6 */
15308/***/ (function(module, exports, __webpack_require__) {
15309
15310	'use strict';
15311
15312	var _Object$defineProperty = __webpack_require__(7)['default'];
15313
15314	exports.__esModule = true;
15315
15316	var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
15317
15318	function Exception(message, node) {
15319	  var loc = node && node.loc,
15320	      line = undefined,
15321	      column = undefined;
15322	  if (loc) {
15323	    line = loc.start.line;
15324	    column = loc.start.column;
15325
15326	    message += ' - ' + line + ':' + column;
15327	  }
15328
15329	  var tmp = Error.prototype.constructor.call(this, message);
15330
15331	  // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
15332	  for (var idx = 0; idx < errorProps.length; idx++) {
15333	    this[errorProps[idx]] = tmp[errorProps[idx]];
15334	  }
15335
15336	  /* istanbul ignore else */
15337	  if (Error.captureStackTrace) {
15338	    Error.captureStackTrace(this, Exception);
15339	  }
15340
15341	  try {
15342	    if (loc) {
15343	      this.lineNumber = line;
15344
15345	      // Work around issue under safari where we can't directly set the column value
15346	      /* istanbul ignore next */
15347	      if (_Object$defineProperty) {
15348	        Object.defineProperty(this, 'column', {
15349	          value: column,
15350	          enumerable: true
15351	        });
15352	      } else {
15353	        this.column = column;
15354	      }
15355	    }
15356	  } catch (nop) {
15357	    /* Ignore if the browser is very particular */
15358	  }
15359	}
15360
15361	Exception.prototype = new Error();
15362
15363	exports['default'] = Exception;
15364	module.exports = exports['default'];
15365
15366/***/ }),
15367/* 7 */
15368/***/ (function(module, exports, __webpack_require__) {
15369
15370	module.exports = { "default": __webpack_require__(8), __esModule: true };
15371
15372/***/ }),
15373/* 8 */
15374/***/ (function(module, exports, __webpack_require__) {
15375
15376	var $ = __webpack_require__(9);
15377	module.exports = function defineProperty(it, key, desc){
15378	  return $.setDesc(it, key, desc);
15379	};
15380
15381/***/ }),
15382/* 9 */
15383/***/ (function(module, exports) {
15384
15385	var $Object = Object;
15386	module.exports = {
15387	  create:     $Object.create,
15388	  getProto:   $Object.getPrototypeOf,
15389	  isEnum:     {}.propertyIsEnumerable,
15390	  getDesc:    $Object.getOwnPropertyDescriptor,
15391	  setDesc:    $Object.defineProperty,
15392	  setDescs:   $Object.defineProperties,
15393	  getKeys:    $Object.keys,
15394	  getNames:   $Object.getOwnPropertyNames,
15395	  getSymbols: $Object.getOwnPropertySymbols,
15396	  each:       [].forEach
15397	};
15398
15399/***/ }),
15400/* 10 */
15401/***/ (function(module, exports, __webpack_require__) {
15402
15403	'use strict';
15404
15405	var _interopRequireDefault = __webpack_require__(1)['default'];
15406
15407	exports.__esModule = true;
15408	exports.registerDefaultHelpers = registerDefaultHelpers;
15409
15410	var _helpersBlockHelperMissing = __webpack_require__(11);
15411
15412	var _helpersBlockHelperMissing2 = _interopRequireDefault(_helpersBlockHelperMissing);
15413
15414	var _helpersEach = __webpack_require__(12);
15415
15416	var _helpersEach2 = _interopRequireDefault(_helpersEach);
15417
15418	var _helpersHelperMissing = __webpack_require__(13);
15419
15420	var _helpersHelperMissing2 = _interopRequireDefault(_helpersHelperMissing);
15421
15422	var _helpersIf = __webpack_require__(14);
15423
15424	var _helpersIf2 = _interopRequireDefault(_helpersIf);
15425
15426	var _helpersLog = __webpack_require__(15);
15427
15428	var _helpersLog2 = _interopRequireDefault(_helpersLog);
15429
15430	var _helpersLookup = __webpack_require__(16);
15431
15432	var _helpersLookup2 = _interopRequireDefault(_helpersLookup);
15433
15434	var _helpersWith = __webpack_require__(17);
15435
15436	var _helpersWith2 = _interopRequireDefault(_helpersWith);
15437
15438	function registerDefaultHelpers(instance) {
15439	  _helpersBlockHelperMissing2['default'](instance);
15440	  _helpersEach2['default'](instance);
15441	  _helpersHelperMissing2['default'](instance);
15442	  _helpersIf2['default'](instance);
15443	  _helpersLog2['default'](instance);
15444	  _helpersLookup2['default'](instance);
15445	  _helpersWith2['default'](instance);
15446	}
15447
15448/***/ }),
15449/* 11 */
15450/***/ (function(module, exports, __webpack_require__) {
15451
15452	'use strict';
15453
15454	exports.__esModule = true;
15455
15456	var _utils = __webpack_require__(5);
15457
15458	exports['default'] = function (instance) {
15459	  instance.registerHelper('blockHelperMissing', function (context, options) {
15460	    var inverse = options.inverse,
15461	        fn = options.fn;
15462
15463	    if (context === true) {
15464	      return fn(this);
15465	    } else if (context === false || context == null) {
15466	      return inverse(this);
15467	    } else if (_utils.isArray(context)) {
15468	      if (context.length > 0) {
15469	        if (options.ids) {
15470	          options.ids = [options.name];
15471	        }
15472
15473	        return instance.helpers.each(context, options);
15474	      } else {
15475	        return inverse(this);
15476	      }
15477	    } else {
15478	      if (options.data && options.ids) {
15479	        var data = _utils.createFrame(options.data);
15480	        data.contextPath = _utils.appendContextPath(options.data.contextPath, options.name);
15481	        options = { data: data };
15482	      }
15483
15484	      return fn(context, options);
15485	    }
15486	  });
15487	};
15488
15489	module.exports = exports['default'];
15490
15491/***/ }),
15492/* 12 */
15493/***/ (function(module, exports, __webpack_require__) {
15494
15495	'use strict';
15496
15497	var _interopRequireDefault = __webpack_require__(1)['default'];
15498
15499	exports.__esModule = true;
15500
15501	var _utils = __webpack_require__(5);
15502
15503	var _exception = __webpack_require__(6);
15504
15505	var _exception2 = _interopRequireDefault(_exception);
15506
15507	exports['default'] = function (instance) {
15508	  instance.registerHelper('each', function (context, options) {
15509	    if (!options) {
15510	      throw new _exception2['default']('Must pass iterator to #each');
15511	    }
15512
15513	    var fn = options.fn,
15514	        inverse = options.inverse,
15515	        i = 0,
15516	        ret = '',
15517	        data = undefined,
15518	        contextPath = undefined;
15519
15520	    if (options.data && options.ids) {
15521	      contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.';
15522	    }
15523
15524	    if (_utils.isFunction(context)) {
15525	      context = context.call(this);
15526	    }
15527
15528	    if (options.data) {
15529	      data = _utils.createFrame(options.data);
15530	    }
15531
15532	    function execIteration(field, index, last) {
15533	      if (data) {
15534	        data.key = field;
15535	        data.index = index;
15536	        data.first = index === 0;
15537	        data.last = !!last;
15538
15539	        if (contextPath) {
15540	          data.contextPath = contextPath + field;
15541	        }
15542	      }
15543
15544	      ret = ret + fn(context[field], {
15545	        data: data,
15546	        blockParams: _utils.blockParams([context[field], field], [contextPath + field, null])
15547	      });
15548	    }
15549
15550	    if (context && typeof context === 'object') {
15551	      if (_utils.isArray(context)) {
15552	        for (var j = context.length; i < j; i++) {
15553	          if (i in context) {
15554	            execIteration(i, i, i === context.length - 1);
15555	          }
15556	        }
15557	      } else {
15558	        var priorKey = undefined;
15559
15560	        for (var key in context) {
15561	          if (context.hasOwnProperty(key)) {
15562	            // We're running the iterations one step out of sync so we can detect
15563	            // the last iteration without have to scan the object twice and create
15564	            // an itermediate keys array.
15565	            if (priorKey !== undefined) {
15566	              execIteration(priorKey, i - 1);
15567	            }
15568	            priorKey = key;
15569	            i++;
15570	          }
15571	        }
15572	        if (priorKey !== undefined) {
15573	          execIteration(priorKey, i - 1, true);
15574	        }
15575	      }
15576	    }
15577
15578	    if (i === 0) {
15579	      ret = inverse(this);
15580	    }
15581
15582	    return ret;
15583	  });
15584	};
15585
15586	module.exports = exports['default'];
15587
15588/***/ }),
15589/* 13 */
15590/***/ (function(module, exports, __webpack_require__) {
15591
15592	'use strict';
15593
15594	var _interopRequireDefault = __webpack_require__(1)['default'];
15595
15596	exports.__esModule = true;
15597
15598	var _exception = __webpack_require__(6);
15599
15600	var _exception2 = _interopRequireDefault(_exception);
15601
15602	exports['default'] = function (instance) {
15603	  instance.registerHelper('helperMissing', function () /* [args, ]options */{
15604	    if (arguments.length === 1) {
15605	      // A missing field in a {{foo}} construct.
15606	      return undefined;
15607	    } else {
15608	      // Someone is actually trying to call something, blow up.
15609	      throw new _exception2['default']('Missing helper: "' + arguments[arguments.length - 1].name + '"');
15610	    }
15611	  });
15612	};
15613
15614	module.exports = exports['default'];
15615
15616/***/ }),
15617/* 14 */
15618/***/ (function(module, exports, __webpack_require__) {
15619
15620	'use strict';
15621
15622	exports.__esModule = true;
15623
15624	var _utils = __webpack_require__(5);
15625
15626	exports['default'] = function (instance) {
15627	  instance.registerHelper('if', function (conditional, options) {
15628	    if (_utils.isFunction(conditional)) {
15629	      conditional = conditional.call(this);
15630	    }
15631
15632	    // Default behavior is to render the positive path if the value is truthy and not empty.
15633	    // The `includeZero` option may be set to treat the condtional as purely not empty based on the
15634	    // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
15635	    if (!options.hash.includeZero && !conditional || _utils.isEmpty(conditional)) {
15636	      return options.inverse(this);
15637	    } else {
15638	      return options.fn(this);
15639	    }
15640	  });
15641
15642	  instance.registerHelper('unless', function (conditional, options) {
15643	    return instance.helpers['if'].call(this, conditional, { fn: options.inverse, inverse: options.fn, hash: options.hash });
15644	  });
15645	};
15646
15647	module.exports = exports['default'];
15648
15649/***/ }),
15650/* 15 */
15651/***/ (function(module, exports) {
15652
15653	'use strict';
15654
15655	exports.__esModule = true;
15656
15657	exports['default'] = function (instance) {
15658	  instance.registerHelper('log', function () /* message, options */{
15659	    var args = [undefined],
15660	        options = arguments[arguments.length - 1];
15661	    for (var i = 0; i < arguments.length - 1; i++) {
15662	      args.push(arguments[i]);
15663	    }
15664
15665	    var level = 1;
15666	    if (options.hash.level != null) {
15667	      level = options.hash.level;
15668	    } else if (options.data && options.data.level != null) {
15669	      level = options.data.level;
15670	    }
15671	    args[0] = level;
15672
15673	    instance.log.apply(instance, args);
15674	  });
15675	};
15676
15677	module.exports = exports['default'];
15678
15679/***/ }),
15680/* 16 */
15681/***/ (function(module, exports) {
15682
15683	'use strict';
15684
15685	exports.__esModule = true;
15686
15687	exports['default'] = function (instance) {
15688	  instance.registerHelper('lookup', function (obj, field) {
15689	    return obj && obj[field];
15690	  });
15691	};
15692
15693	module.exports = exports['default'];
15694
15695/***/ }),
15696/* 17 */
15697/***/ (function(module, exports, __webpack_require__) {
15698
15699	'use strict';
15700
15701	exports.__esModule = true;
15702
15703	var _utils = __webpack_require__(5);
15704
15705	exports['default'] = function (instance) {
15706	  instance.registerHelper('with', function (context, options) {
15707	    if (_utils.isFunction(context)) {
15708	      context = context.call(this);
15709	    }
15710
15711	    var fn = options.fn;
15712
15713	    if (!_utils.isEmpty(context)) {
15714	      var data = options.data;
15715	      if (options.data && options.ids) {
15716	        data = _utils.createFrame(options.data);
15717	        data.contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]);
15718	      }
15719
15720	      return fn(context, {
15721	        data: data,
15722	        blockParams: _utils.blockParams([context], [data && data.contextPath])
15723	      });
15724	    } else {
15725	      return options.inverse(this);
15726	    }
15727	  });
15728	};
15729
15730	module.exports = exports['default'];
15731
15732/***/ }),
15733/* 18 */
15734/***/ (function(module, exports, __webpack_require__) {
15735
15736	'use strict';
15737
15738	var _interopRequireDefault = __webpack_require__(1)['default'];
15739
15740	exports.__esModule = true;
15741	exports.registerDefaultDecorators = registerDefaultDecorators;
15742
15743	var _decoratorsInline = __webpack_require__(19);
15744
15745	var _decoratorsInline2 = _interopRequireDefault(_decoratorsInline);
15746
15747	function registerDefaultDecorators(instance) {
15748	  _decoratorsInline2['default'](instance);
15749	}
15750
15751/***/ }),
15752/* 19 */
15753/***/ (function(module, exports, __webpack_require__) {
15754
15755	'use strict';
15756
15757	exports.__esModule = true;
15758
15759	var _utils = __webpack_require__(5);
15760
15761	exports['default'] = function (instance) {
15762	  instance.registerDecorator('inline', function (fn, props, container, options) {
15763	    var ret = fn;
15764	    if (!props.partials) {
15765	      props.partials = {};
15766	      ret = function (context, options) {
15767	        // Create a new partials stack frame prior to exec.
15768	        var original = container.partials;
15769	        container.partials = _utils.extend({}, original, props.partials);
15770	        var ret = fn(context, options);
15771	        container.partials = original;
15772	        return ret;
15773	      };
15774	    }
15775
15776	    props.partials[options.args[0]] = options.fn;
15777
15778	    return ret;
15779	  });
15780	};
15781
15782	module.exports = exports['default'];
15783
15784/***/ }),
15785/* 20 */
15786/***/ (function(module, exports, __webpack_require__) {
15787
15788	'use strict';
15789
15790	exports.__esModule = true;
15791
15792	var _utils = __webpack_require__(5);
15793
15794	var logger = {
15795	  methodMap: ['debug', 'info', 'warn', 'error'],
15796	  level: 'info',
15797
15798	  // Maps a given level value to the `methodMap` indexes above.
15799	  lookupLevel: function lookupLevel(level) {
15800	    if (typeof level === 'string') {
15801	      var levelMap = _utils.indexOf(logger.methodMap, level.toLowerCase());
15802	      if (levelMap >= 0) {
15803	        level = levelMap;
15804	      } else {
15805	        level = parseInt(level, 10);
15806	      }
15807	    }
15808
15809	    return level;
15810	  },
15811
15812	  // Can be overridden in the host environment
15813	  log: function log(level) {
15814	    level = logger.lookupLevel(level);
15815
15816	    if (typeof console !== 'undefined' && logger.lookupLevel(logger.level) <= level) {
15817	      var method = logger.methodMap[level];
15818	      if (!console[method]) {
15819	        // eslint-disable-line no-console
15820	        method = 'log';
15821	      }
15822
15823	      for (var _len = arguments.length, message = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
15824	        message[_key - 1] = arguments[_key];
15825	      }
15826
15827	      console[method].apply(console, message); // eslint-disable-line no-console
15828	    }
15829	  }
15830	};
15831
15832	exports['default'] = logger;
15833	module.exports = exports['default'];
15834
15835/***/ }),
15836/* 21 */
15837/***/ (function(module, exports) {
15838
15839	// Build out our basic SafeString type
15840	'use strict';
15841
15842	exports.__esModule = true;
15843	function SafeString(string) {
15844	  this.string = string;
15845	}
15846
15847	SafeString.prototype.toString = SafeString.prototype.toHTML = function () {
15848	  return '' + this.string;
15849	};
15850
15851	exports['default'] = SafeString;
15852	module.exports = exports['default'];
15853
15854/***/ }),
15855/* 22 */
15856/***/ (function(module, exports, __webpack_require__) {
15857
15858	'use strict';
15859
15860	var _Object$seal = __webpack_require__(23)['default'];
15861
15862	var _interopRequireWildcard = __webpack_require__(3)['default'];
15863
15864	var _interopRequireDefault = __webpack_require__(1)['default'];
15865
15866	exports.__esModule = true;
15867	exports.checkRevision = checkRevision;
15868	exports.template = template;
15869	exports.wrapProgram = wrapProgram;
15870	exports.resolvePartial = resolvePartial;
15871	exports.invokePartial = invokePartial;
15872	exports.noop = noop;
15873
15874	var _utils = __webpack_require__(5);
15875
15876	var Utils = _interopRequireWildcard(_utils);
15877
15878	var _exception = __webpack_require__(6);
15879
15880	var _exception2 = _interopRequireDefault(_exception);
15881
15882	var _base = __webpack_require__(4);
15883
15884	function checkRevision(compilerInfo) {
15885	  var compilerRevision = compilerInfo && compilerInfo[0] || 1,
15886	      currentRevision = _base.COMPILER_REVISION;
15887
15888	  if (compilerRevision !== currentRevision) {
15889	    if (compilerRevision < currentRevision) {
15890	      var runtimeVersions = _base.REVISION_CHANGES[currentRevision],
15891	          compilerVersions = _base.REVISION_CHANGES[compilerRevision];
15892	      throw new _exception2['default']('Template was precompiled with an older version of Handlebars than the current runtime. ' + 'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').');
15893	    } else {
15894	      // Use the embedded version info since the runtime doesn't know about this revision yet
15895	      throw new _exception2['default']('Template was precompiled with a newer version of Handlebars than the current runtime. ' + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').');
15896	    }
15897	  }
15898	}
15899
15900	function template(templateSpec, env) {
15901	  /* istanbul ignore next */
15902	  if (!env) {
15903	    throw new _exception2['default']('No environment passed to template');
15904	  }
15905	  if (!templateSpec || !templateSpec.main) {
15906	    throw new _exception2['default']('Unknown template object: ' + typeof templateSpec);
15907	  }
15908
15909	  templateSpec.main.decorator = templateSpec.main_d;
15910
15911	  // Note: Using env.VM references rather than local var references throughout this section to allow
15912	  // for external users to override these as psuedo-supported APIs.
15913	  env.VM.checkRevision(templateSpec.compiler);
15914
15915	  function invokePartialWrapper(partial, context, options) {
15916	    if (options.hash) {
15917	      context = Utils.extend({}, context, options.hash);
15918	      if (options.ids) {
15919	        options.ids[0] = true;
15920	      }
15921	    }
15922
15923	    partial = env.VM.resolvePartial.call(this, partial, context, options);
15924	    var result = env.VM.invokePartial.call(this, partial, context, options);
15925
15926	    if (result == null && env.compile) {
15927	      options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env);
15928	      result = options.partials[options.name](context, options);
15929	    }
15930	    if (result != null) {
15931	      if (options.indent) {
15932	        var lines = result.split('\n');
15933	        for (var i = 0, l = lines.length; i < l; i++) {
15934	          if (!lines[i] && i + 1 === l) {
15935	            break;
15936	          }
15937
15938	          lines[i] = options.indent + lines[i];
15939	        }
15940	        result = lines.join('\n');
15941	      }
15942	      return result;
15943	    } else {
15944	      throw new _exception2['default']('The partial ' + options.name + ' could not be compiled when running in runtime-only mode');
15945	    }
15946	  }
15947
15948	  // Just add water
15949	  var container = {
15950	    strict: function strict(obj, name) {
15951	      if (!(name in obj)) {
15952	        throw new _exception2['default']('"' + name + '" not defined in ' + obj);
15953	      }
15954	      return obj[name];
15955	    },
15956	    lookup: function lookup(depths, name) {
15957	      var len = depths.length;
15958	      for (var i = 0; i < len; i++) {
15959	        if (depths[i] && depths[i][name] != null) {
15960	          return depths[i][name];
15961	        }
15962	      }
15963	    },
15964	    lambda: function lambda(current, context) {
15965	      return typeof current === 'function' ? current.call(context) : current;
15966	    },
15967
15968	    escapeExpression: Utils.escapeExpression,
15969	    invokePartial: invokePartialWrapper,
15970
15971	    fn: function fn(i) {
15972	      var ret = templateSpec[i];
15973	      ret.decorator = templateSpec[i + '_d'];
15974	      return ret;
15975	    },
15976
15977	    programs: [],
15978	    program: function program(i, data, declaredBlockParams, blockParams, depths) {
15979	      var programWrapper = this.programs[i],
15980	          fn = this.fn(i);
15981	      if (data || depths || blockParams || declaredBlockParams) {
15982	        programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths);
15983	      } else if (!programWrapper) {
15984	        programWrapper = this.programs[i] = wrapProgram(this, i, fn);
15985	      }
15986	      return programWrapper;
15987	    },
15988
15989	    data: function data(value, depth) {
15990	      while (value && depth--) {
15991	        value = value._parent;
15992	      }
15993	      return value;
15994	    },
15995	    merge: function merge(param, common) {
15996	      var obj = param || common;
15997
15998	      if (param && common && param !== common) {
15999	        obj = Utils.extend({}, common, param);
16000	      }
16001
16002	      return obj;
16003	    },
16004	    // An empty object to use as replacement for null-contexts
16005	    nullContext: _Object$seal({}),
16006
16007	    noop: env.VM.noop,
16008	    compilerInfo: templateSpec.compiler
16009	  };
16010
16011	  function ret(context) {
16012	    var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
16013
16014	    var data = options.data;
16015
16016	    ret._setup(options);
16017	    if (!options.partial && templateSpec.useData) {
16018	      data = initData(context, data);
16019	    }
16020	    var depths = undefined,
16021	        blockParams = templateSpec.useBlockParams ? [] : undefined;
16022	    if (templateSpec.useDepths) {
16023	      if (options.depths) {
16024	        depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths;
16025	      } else {
16026	        depths = [context];
16027	      }
16028	    }
16029
16030	    function main(context /*, options*/) {
16031	      return '' + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths);
16032	    }
16033	    main = executeDecorators(templateSpec.main, main, container, options.depths || [], data, blockParams);
16034	    return main(context, options);
16035	  }
16036	  ret.isTop = true;
16037
16038	  ret._setup = function (options) {
16039	    if (!options.partial) {
16040	      container.helpers = container.merge(options.helpers, env.helpers);
16041
16042	      if (templateSpec.usePartial) {
16043	        container.partials = container.merge(options.partials, env.partials);
16044	      }
16045	      if (templateSpec.usePartial || templateSpec.useDecorators) {
16046	        container.decorators = container.merge(options.decorators, env.decorators);
16047	      }
16048	    } else {
16049	      container.helpers = options.helpers;
16050	      container.partials = options.partials;
16051	      container.decorators = options.decorators;
16052	    }
16053	  };
16054
16055	  ret._child = function (i, data, blockParams, depths) {
16056	    if (templateSpec.useBlockParams && !blockParams) {
16057	      throw new _exception2['default']('must pass block params');
16058	    }
16059	    if (templateSpec.useDepths && !depths) {
16060	      throw new _exception2['default']('must pass parent depths');
16061	    }
16062
16063	    return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths);
16064	  };
16065	  return ret;
16066	}
16067
16068	function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) {
16069	  function prog(context) {
16070	    var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
16071
16072	    var currentDepths = depths;
16073	    if (depths && context != depths[0] && !(context === container.nullContext && depths[0] === null)) {
16074	      currentDepths = [context].concat(depths);
16075	    }
16076
16077	    return fn(container, context, container.helpers, container.partials, options.data || data, blockParams && [options.blockParams].concat(blockParams), currentDepths);
16078	  }
16079
16080	  prog = executeDecorators(fn, prog, container, depths, data, blockParams);
16081
16082	  prog.program = i;
16083	  prog.depth = depths ? depths.length : 0;
16084	  prog.blockParams = declaredBlockParams || 0;
16085	  return prog;
16086	}
16087
16088	function resolvePartial(partial, context, options) {
16089	  if (!partial) {
16090	    if (options.name === '@partial-block') {
16091	      partial = options.data['partial-block'];
16092	    } else {
16093	      partial = options.partials[options.name];
16094	    }
16095	  } else if (!partial.call && !options.name) {
16096	    // This is a dynamic partial that returned a string
16097	    options.name = partial;
16098	    partial = options.partials[partial];
16099	  }
16100	  return partial;
16101	}
16102
16103	function invokePartial(partial, context, options) {
16104	  // Use the current closure context to save the partial-block if this partial
16105	  var currentPartialBlock = options.data && options.data['partial-block'];
16106	  options.partial = true;
16107	  if (options.ids) {
16108	    options.data.contextPath = options.ids[0] || options.data.contextPath;
16109	  }
16110
16111	  var partialBlock = undefined;
16112	  if (options.fn && options.fn !== noop) {
16113	    (function () {
16114	      options.data = _base.createFrame(options.data);
16115	      // Wrapper function to get access to currentPartialBlock from the closure
16116	      var fn = options.fn;
16117	      partialBlock = options.data['partial-block'] = function partialBlockWrapper(context) {
16118	        var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
16119
16120	        // Restore the partial-block from the closure for the execution of the block
16121	        // i.e. the part inside the block of the partial call.
16122	        options.data = _base.createFrame(options.data);
16123	        options.data['partial-block'] = currentPartialBlock;
16124	        return fn(context, options);
16125	      };
16126	      if (fn.partials) {
16127	        options.partials = Utils.extend({}, options.partials, fn.partials);
16128	      }
16129	    })();
16130	  }
16131
16132	  if (partial === undefined && partialBlock) {
16133	    partial = partialBlock;
16134	  }
16135
16136	  if (partial === undefined) {
16137	    throw new _exception2['default']('The partial ' + options.name + ' could not be found');
16138	  } else if (partial instanceof Function) {
16139	    return partial(context, options);
16140	  }
16141	}
16142
16143	function noop() {
16144	  return '';
16145	}
16146
16147	function initData(context, data) {
16148	  if (!data || !('root' in data)) {
16149	    data = data ? _base.createFrame(data) : {};
16150	    data.root = context;
16151	  }
16152	  return data;
16153	}
16154
16155	function executeDecorators(fn, prog, container, depths, data, blockParams) {
16156	  if (fn.decorator) {
16157	    var props = {};
16158	    prog = fn.decorator(prog, props, container, depths && depths[0], data, blockParams, depths);
16159	    Utils.extend(prog, props);
16160	  }
16161	  return prog;
16162	}
16163
16164/***/ }),
16165/* 23 */
16166/***/ (function(module, exports, __webpack_require__) {
16167
16168	module.exports = { "default": __webpack_require__(24), __esModule: true };
16169
16170/***/ }),
16171/* 24 */
16172/***/ (function(module, exports, __webpack_require__) {
16173
16174	__webpack_require__(25);
16175	module.exports = __webpack_require__(30).Object.seal;
16176
16177/***/ }),
16178/* 25 */
16179/***/ (function(module, exports, __webpack_require__) {
16180
16181	// 19.1.2.17 Object.seal(O)
16182	var isObject = __webpack_require__(26);
16183
16184	__webpack_require__(27)('seal', function($seal){
16185	  return function seal(it){
16186	    return $seal && isObject(it) ? $seal(it) : it;
16187	  };
16188	});
16189
16190/***/ }),
16191/* 26 */
16192/***/ (function(module, exports) {
16193
16194	module.exports = function(it){
16195	  return typeof it === 'object' ? it !== null : typeof it === 'function';
16196	};
16197
16198/***/ }),
16199/* 27 */
16200/***/ (function(module, exports, __webpack_require__) {
16201
16202	// most Object methods by ES6 should accept primitives
16203	var $export = __webpack_require__(28)
16204	  , core    = __webpack_require__(30)
16205	  , fails   = __webpack_require__(33);
16206	module.exports = function(KEY, exec){
16207	  var fn  = (core.Object || {})[KEY] || Object[KEY]
16208	    , exp = {};
16209	  exp[KEY] = exec(fn);
16210	  $export($export.S + $export.F * fails(function(){ fn(1); }), 'Object', exp);
16211	};
16212
16213/***/ }),
16214/* 28 */
16215/***/ (function(module, exports, __webpack_require__) {
16216
16217	var global    = __webpack_require__(29)
16218	  , core      = __webpack_require__(30)
16219	  , ctx       = __webpack_require__(31)
16220	  , PROTOTYPE = 'prototype';
16221
16222	var $export = function(type, name, source){
16223	  var IS_FORCED = type & $export.F
16224	    , IS_GLOBAL = type & $export.G
16225	    , IS_STATIC = type & $export.S
16226	    , IS_PROTO  = type & $export.P
16227	    , IS_BIND   = type & $export.B
16228	    , IS_WRAP   = type & $export.W
16229	    , exports   = IS_GLOBAL ? core : core[name] || (core[name] = {})
16230	    , target    = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE]
16231	    , key, own, out;
16232	  if(IS_GLOBAL)source = name;
16233	  for(key in source){
16234	    // contains in native
16235	    own = !IS_FORCED && target && key in target;
16236	    if(own && key in exports)continue;
16237	    // export native or passed
16238	    out = own ? target[key] : source[key];
16239	    // prevent global pollution for namespaces
16240	    exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key]
16241	    // bind timers to global for call from export context
16242	    : IS_BIND && own ? ctx(out, global)
16243	    // wrap global constructors for prevent change them in library
16244	    : IS_WRAP && target[key] == out ? (function(C){
16245	      var F = function(param){
16246	        return this instanceof C ? new C(param) : C(param);
16247	      };
16248	      F[PROTOTYPE] = C[PROTOTYPE];
16249	      return F;
16250	    // make static versions for prototype methods
16251	    })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;
16252	    if(IS_PROTO)(exports[PROTOTYPE] || (exports[PROTOTYPE] = {}))[key] = out;
16253	  }
16254	};
16255	// type bitmap
16256	$export.F = 1;  // forced
16257	$export.G = 2;  // global
16258	$export.S = 4;  // static
16259	$export.P = 8;  // proto
16260	$export.B = 16; // bind
16261	$export.W = 32; // wrap
16262	module.exports = $export;
16263
16264/***/ }),
16265/* 29 */
16266/***/ (function(module, exports) {
16267
16268	// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
16269	var global = module.exports = typeof window != 'undefined' && window.Math == Math
16270	  ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')();
16271	if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef
16272
16273/***/ }),
16274/* 30 */
16275/***/ (function(module, exports) {
16276
16277	var core = module.exports = {version: '1.2.6'};
16278	if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef
16279
16280/***/ }),
16281/* 31 */
16282/***/ (function(module, exports, __webpack_require__) {
16283
16284	// optional / simple context binding
16285	var aFunction = __webpack_require__(32);
16286	module.exports = function(fn, that, length){
16287	  aFunction(fn);
16288	  if(that === undefined)return fn;
16289	  switch(length){
16290	    case 1: return function(a){
16291	      return fn.call(that, a);
16292	    };
16293	    case 2: return function(a, b){
16294	      return fn.call(that, a, b);
16295	    };
16296	    case 3: return function(a, b, c){
16297	      return fn.call(that, a, b, c);
16298	    };
16299	  }
16300	  return function(/* ...args */){
16301	    return fn.apply(that, arguments);
16302	  };
16303	};
16304
16305/***/ }),
16306/* 32 */
16307/***/ (function(module, exports) {
16308
16309	module.exports = function(it){
16310	  if(typeof it != 'function')throw TypeError(it + ' is not a function!');
16311	  return it;
16312	};
16313
16314/***/ }),
16315/* 33 */
16316/***/ (function(module, exports) {
16317
16318	module.exports = function(exec){
16319	  try {
16320	    return !!exec();
16321	  } catch(e){
16322	    return true;
16323	  }
16324	};
16325
16326/***/ }),
16327/* 34 */
16328/***/ (function(module, exports) {
16329
16330	/* WEBPACK VAR INJECTION */(function(global) {/* global window */
16331	'use strict';
16332
16333	exports.__esModule = true;
16334
16335	exports['default'] = function (Handlebars) {
16336	  /* istanbul ignore next */
16337	  var root = typeof global !== 'undefined' ? global : window,
16338	      $Handlebars = root.Handlebars;
16339	  /* istanbul ignore next */
16340	  Handlebars.noConflict = function () {
16341	    if (root.Handlebars === Handlebars) {
16342	      root.Handlebars = $Handlebars;
16343	    }
16344	    return Handlebars;
16345	  };
16346	};
16347
16348	module.exports = exports['default'];
16349	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
16350
16351/***/ }),
16352/* 35 */
16353/***/ (function(module, exports) {
16354
16355	'use strict';
16356
16357	exports.__esModule = true;
16358	var AST = {
16359	  // Public API used to evaluate derived attributes regarding AST nodes
16360	  helpers: {
16361	    // a mustache is definitely a helper if:
16362	    // * it is an eligible helper, and
16363	    // * it has at least one parameter or hash segment
16364	    helperExpression: function helperExpression(node) {
16365	      return node.type === 'SubExpression' || (node.type === 'MustacheStatement' || node.type === 'BlockStatement') && !!(node.params && node.params.length || node.hash);
16366	    },
16367
16368	    scopedId: function scopedId(path) {
16369	      return (/^\.|this\b/.test(path.original)
16370	      );
16371	    },
16372
16373	    // an ID is simple if it only has one part, and that part is not
16374	    // `..` or `this`.
16375	    simpleId: function simpleId(path) {
16376	      return path.parts.length === 1 && !AST.helpers.scopedId(path) && !path.depth;
16377	    }
16378	  }
16379	};
16380
16381	// Must be exported as an object rather than the root of the module as the jison lexer
16382	// must modify the object to operate properly.
16383	exports['default'] = AST;
16384	module.exports = exports['default'];
16385
16386/***/ }),
16387/* 36 */
16388/***/ (function(module, exports, __webpack_require__) {
16389
16390	'use strict';
16391
16392	var _interopRequireDefault = __webpack_require__(1)['default'];
16393
16394	var _interopRequireWildcard = __webpack_require__(3)['default'];
16395
16396	exports.__esModule = true;
16397	exports.parse = parse;
16398
16399	var _parser = __webpack_require__(37);
16400
16401	var _parser2 = _interopRequireDefault(_parser);
16402
16403	var _whitespaceControl = __webpack_require__(38);
16404
16405	var _whitespaceControl2 = _interopRequireDefault(_whitespaceControl);
16406
16407	var _helpers = __webpack_require__(40);
16408
16409	var Helpers = _interopRequireWildcard(_helpers);
16410
16411	var _utils = __webpack_require__(5);
16412
16413	exports.parser = _parser2['default'];
16414
16415	var yy = {};
16416	_utils.extend(yy, Helpers);
16417
16418	function parse(input, options) {
16419	  // Just return if an already-compiled AST was passed in.
16420	  if (input.type === 'Program') {
16421	    return input;
16422	  }
16423
16424	  _parser2['default'].yy = yy;
16425
16426	  // Altering the shared object here, but this is ok as parser is a sync operation
16427	  yy.locInfo = function (locInfo) {
16428	    return new yy.SourceLocation(options && options.srcName, locInfo);
16429	  };
16430
16431	  var strip = new _whitespaceControl2['default'](options);
16432	  return strip.accept(_parser2['default'].parse(input));
16433	}
16434
16435/***/ }),
16436/* 37 */
16437/***/ (function(module, exports) {
16438
16439	// File ignored in coverage tests via setting in .istanbul.yml
16440	/* Jison generated parser */
16441	"use strict";
16442
16443	exports.__esModule = true;
16444	var handlebars = (function () {
16445	    var parser = { trace: function trace() {},
16446	        yy: {},
16447	        symbols_: { "error": 2, "root": 3, "program": 4, "EOF": 5, "program_repetition0": 6, "statement": 7, "mustache": 8, "block": 9, "rawBlock": 10, "partial": 11, "partialBlock": 12, "content": 13, "COMMENT": 14, "CONTENT": 15, "openRawBlock": 16, "rawBlock_repetition_plus0": 17, "END_RAW_BLOCK": 18, "OPEN_RAW_BLOCK": 19, "helperName": 20, "openRawBlock_repetition0": 21, "openRawBlock_option0": 22, "CLOSE_RAW_BLOCK": 23, "openBlock": 24, "block_option0": 25, "closeBlock": 26, "openInverse": 27, "block_option1": 28, "OPEN_BLOCK": 29, "openBlock_repetition0": 30, "openBlock_option0": 31, "openBlock_option1": 32, "CLOSE": 33, "OPEN_INVERSE": 34, "openInverse_repetition0": 35, "openInverse_option0": 36, "openInverse_option1": 37, "openInverseChain": 38, "OPEN_INVERSE_CHAIN": 39, "openInverseChain_repetition0": 40, "openInverseChain_option0": 41, "openInverseChain_option1": 42, "inverseAndProgram": 43, "INVERSE": 44, "inverseChain": 45, "inverseChain_option0": 46, "OPEN_ENDBLOCK": 47, "OPEN": 48, "mustache_repetition0": 49, "mustache_option0": 50, "OPEN_UNESCAPED": 51, "mustache_repetition1": 52, "mustache_option1": 53, "CLOSE_UNESCAPED": 54, "OPEN_PARTIAL": 55, "partialName": 56, "partial_repetition0": 57, "partial_option0": 58, "openPartialBlock": 59, "OPEN_PARTIAL_BLOCK": 60, "openPartialBlock_repetition0": 61, "openPartialBlock_option0": 62, "param": 63, "sexpr": 64, "OPEN_SEXPR": 65, "sexpr_repetition0": 66, "sexpr_option0": 67, "CLOSE_SEXPR": 68, "hash": 69, "hash_repetition_plus0": 70, "hashSegment": 71, "ID": 72, "EQUALS": 73, "blockParams": 74, "OPEN_BLOCK_PARAMS": 75, "blockParams_repetition_plus0": 76, "CLOSE_BLOCK_PARAMS": 77, "path": 78, "dataName": 79, "STRING": 80, "NUMBER": 81, "BOOLEAN": 82, "UNDEFINED": 83, "NULL": 84, "DATA": 85, "pathSegments": 86, "SEP": 87, "$accept": 0, "$end": 1 },
16448	        terminals_: { 2: "error", 5: "EOF", 14: "COMMENT", 15: "CONTENT", 
vendor: 26,539 bytes, lines 16448-16704
1644818: "END_RAW_BLOCK", 19: "OPEN_RAW_BLOCK", 23: "CLOSE_RAW_BLOCK", 29: "OPEN_BLOCK", 33: "CLOSE", 34: "OPEN_INVERSE", 39: "OPEN_INVERSE_CHAIN", 44: "INVERSE", 47: "OPEN_ENDBLOCK", 48: "OPEN", 51: "OPEN_UNESCAPED", 54: "CLOSE_UNESCAPED", 55: "OPEN_PARTIAL", 60: "OPEN_PARTIAL_BLOCK", 65: "OPEN_SEXPR", 68: "CLOSE_SEXPR", 72: "ID", 73: "EQUALS", 75: "OPEN_BLOCK_PARAMS", 77: "CLOSE_BLOCK_PARAMS", 80: "STRING", 81: "NUMBER", 82: "BOOLEAN", 83: "UNDEFINED", 84: "NULL", 85: "DATA", 87: "SEP" },
16449	        productions_: [0, [3, 2], [4, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [13, 1], [10, 3], [16, 5], [9, 4], [9, 4], [24, 6], [27, 6], [38, 6], [43, 2], [45, 3], [45, 1], [26, 3], [8, 5], [8, 5], [11, 5], [12, 3], [59, 5], [63, 1], [63, 1], [64, 5], [69, 1], [71, 3], [74, 3], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [56, 1], [56, 1], [79, 2], [78, 1], [86, 3], [86, 1], [6, 0], [6, 2], [17, 1], [17, 2], [21, 0], [21, 2], [22, 0], [22, 1], [25, 0], [25, 1], [28, 0], [28, 1], [30, 0], [30, 2], [31, 0], [31, 1], [32, 0], [32, 1], [35, 0], [35, 2], [36, 0], [36, 1], [37, 0], [37, 1], [40, 0], [40, 2], [41, 0], [41, 1], [42, 0], [42, 1], [46, 0], [46, 1], [49, 0], [49, 2], [50, 0], [50, 1], [52, 0], [52, 2], [53, 0], [53, 1], [57, 0], [57, 2], [58, 0], [58, 1], [61, 0], [61, 2], [62, 0], [62, 1], [66, 0], [66, 2], [67, 0], [67, 1], [70, 1], [70, 2], [76, 1], [76, 2]],
16450	        performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$
16451	        /**/) {
16452
16453	            var $0 = $$.length - 1;
16454	            switch (yystate) {
16455	                case 1:
16456	                    return $$[$0 - 1];
16457	                    break;
16458	                case 2:
16459	                    this.$ = yy.prepareProgram($$[$0]);
16460	                    break;
16461	                case 3:
16462	                    this.$ = $$[$0];
16463	                    break;
16464	                case 4:
16465	                    this.$ = $$[$0];
16466	                    break;
16467	                case 5:
16468	                    this.$ = $$[$0];
16469	                    break;
16470	                case 6:
16471	                    this.$ = $$[$0];
16472	                    break;
16473	                case 7:
16474	                    this.$ = $$[$0];
16475	                    break;
16476	                case 8:
16477	                    this.$ = $$[$0];
16478	                    break;
16479	                case 9:
16480	                    this.$ = {
16481	                        type: 'CommentStatement',
16482	                        value: yy.stripComment($$[$0]),
16483	                        strip: yy.stripFlags($$[$0], $$[$0]),
16484	                        loc: yy.locInfo(this._$)
16485	                    };
16486
16487	                    break;
16488	                case 10:
16489	                    this.$ = {
16490	                        type: 'ContentStatement',
16491	                        original: $$[$0],
16492	                        value: $$[$0],
16493	                        loc: yy.locInfo(this._$)
16494	                    };
16495
16496	                    break;
16497	                case 11:
16498	                    this.$ = yy.prepareRawBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$);
16499	                    break;
16500	                case 12:
16501	                    this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1] };
16502	                    break;
16503	                case 13:
16504	                    this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], false, this._$);
16505	                    break;
16506	                case 14:
16507	                    this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], true, this._$);
16508	                    break;
16509	                case 15:
16510	                    this.$ = { open: $$[$0 - 5], path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
16511	                    break;
16512	                case 16:
16513	                    this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
16514	                    break;
16515	                case 17:
16516	                    this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
16517	                    break;
16518	                case 18:
16519	                    this.$ = { strip: yy.stripFlags($$[$0 - 1], $$[$0 - 1]), program: $$[$0] };
16520	                    break;
16521	                case 19:
16522	                    var inverse = yy.prepareBlock($$[$0 - 2], $$[$0 - 1], $$[$0], $$[$0], false, this._$),
16523	                        program = yy.prepareProgram([inverse], $$[$0 - 1].loc);
16524	                    program.chained = true;
16525
16526	                    this.$ = { strip: $$[$0 - 2].strip, program: program, chain: true };
16527
16528	                    break;
16529	                case 20:
16530	                    this.$ = $$[$0];
16531	                    break;
16532	                case 21:
16533	                    this.$ = { path: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 2], $$[$0]) };
16534	                    break;
16535	                case 22:
16536	                    this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$);
16537	                    break;
16538	                case 23:
16539	                    this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$);
16540	                    break;
16541	                case 24:
16542	                    this.$ = {
16543	                        type: 'PartialStatement',
16544	                        name: $$[$0 - 3],
16545	                        params: $$[$0 - 2],
16546	                        hash: $$[$0 - 1],
16547	                        indent: '',
16548	                        strip: yy.stripFlags($$[$0 - 4], $$[$0]),
16549	                        loc: yy.locInfo(this._$)
16550	                    };
16551
16552	                    break;
16553	                case 25:
16554	                    this.$ = yy.preparePartialBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$);
16555	                    break;
16556	                case 26:
16557	                    this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 4], $$[$0]) };
16558	                    break;
16559	                case 27:
16560	                    this.$ = $$[$0];
16561	                    break;
16562	                case 28:
16563	                    this.$ = $$[$0];
16564	                    break;
16565	                case 29:
16566	                    this.$ = {
16567	                        type: 'SubExpression',
16568	                        path: $$[$0 - 3],
16569	                        params: $$[$0 - 2],
16570	                        hash: $$[$0 - 1],
16571	                        loc: yy.locInfo(this._$)
16572	                    };
16573
16574	                    break;
16575	                case 30:
16576	                    this.$ = { type: 'Hash', pairs: $$[$0], loc: yy.locInfo(this._$) };
16577	                    break;
16578	                case 31:
16579	                    this.$ = { type: 'HashPair', key: yy.id($$[$0 - 2]), value: $$[$0], loc: yy.locInfo(this._$) };
16580	                    break;
16581	                case 32:
16582	                    this.$ = yy.id($$[$0 - 1]);
16583	                    break;
16584	                case 33:
16585	                    this.$ = $$[$0];
16586	                    break;
16587	                case 34:
16588	                    this.$ = $$[$0];
16589	                    break;
16590	                case 35:
16591	                    this.$ = { type: 'StringLiteral', value: $$[$0], original: $$[$0], loc: yy.locInfo(this._$) };
16592	                    break;
16593	                case 36:
16594	                    this.$ = { type: 'NumberLiteral', value: Number($$[$0]), original: Number($$[$0]), loc: yy.locInfo(this._$) };
16595	                    break;
16596	                case 37:
16597	                    this.$ = { type: 'BooleanLiteral', value: $$[$0] === 'true', original: $$[$0] === 'true', loc: yy.locInfo(this._$) };
16598	                    break;
16599	                case 38:
16600	                    this.$ = { type: 'UndefinedLiteral', original: undefined, value: undefined, loc: yy.locInfo(this._$) };
16601	                    break;
16602	                case 39:
16603	                    this.$ = { type: 'NullLiteral', original: null, value: null, loc: yy.locInfo(this._$) };
16604	                    break;
16605	                case 40:
16606	                    this.$ = $$[$0];
16607	                    break;
16608	                case 41:
16609	                    this.$ = $$[$0];
16610	                    break;
16611	                case 42:
16612	                    this.$ = yy.preparePath(true, $$[$0], this._$);
16613	                    break;
16614	                case 43:
16615	                    this.$ = yy.preparePath(false, $$[$0], this._$);
16616	                    break;
16617	                case 44:
16618	                    $$[$0 - 2].push({ part: yy.id($$[$0]), original: $$[$0], separator: $$[$0 - 1] });this.$ = $$[$0 - 2];
16619	                    break;
16620	                case 45:
16621	                    this.$ = [{ part: yy.id($$[$0]), original: $$[$0] }];
16622	                    break;
16623	                case 46:
16624	                    this.$ = [];
16625	                    break;
16626	                case 47:
16627	                    $$[$0 - 1].push($$[$0]);
16628	                    break;
16629	                case 48:
16630	                    this.$ = [$$[$0]];
16631	                    break;
16632	                case 49:
16633	                    $$[$0 - 1].push($$[$0]);
16634	                    break;
16635	                case 50:
16636	                    this.$ = [];
16637	                    break;
16638	                case 51:
16639	                    $$[$0 - 1].push($$[$0]);
16640	                    break;
16641	                case 58:
16642	                    this.$ = [];
16643	                    break;
16644	                case 59:
16645	                    $$[$0 - 1].push($$[$0]);
16646	                    break;
16647	                case 64:
16648	                    this.$ = [];
16649	                    break;
16650	                case 65:
16651	                    $$[$0 - 1].push($$[$0]);
16652	                    break;
16653	                case 70:
16654	                    this.$ = [];
16655	                    break;
16656	                case 71:
16657	                    $$[$0 - 1].push($$[$0]);
16658	                    break;
16659	                case 78:
16660	                    this.$ = [];
16661	                    break;
16662	                case 79:
16663	                    $$[$0 - 1].push($$[$0]);
16664	                    break;
16665	                case 82:
16666	                    this.$ = [];
16667	                    break;
16668	                case 83:
16669	                    $$[$0 - 1].push($$[$0]);
16670	                    break;
16671	                case 86:
16672	                    this.$ = [];
16673	                    break;
16674	                case 87:
16675	                    $$[$0 - 1].push($$[$0]);
16676	                    break;
16677	                case 90:
16678	                    this.$ = [];
16679	                    break;
16680	                case 91:
16681	                    $$[$0 - 1].push($$[$0]);
16682	                    break;
16683	                case 94:
16684	                    this.$ = [];
16685	                    break;
16686	                case 95:
16687	                    $$[$0 - 1].push($$[$0]);
16688	                    break;
16689	                case 98:
16690	                    this.$ = [$$[$0]];
16691	                    break;
16692	                case 99:
16693	                    $$[$0 - 1].push($$[$0]);
16694	                    break;
16695	                case 100:
16696	                    this.$ = [$$[$0]];
16697	                    break;
16698	                case 101:
16699	                    $$[$0 - 1].push($$[$0]);
16700	                    break;
16701	            }
16702	        },
16703	        table: [{ 3: 1, 4: 2, 5: [2, 46], 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 1: [3] }, { 5: [1, 4] }, { 5: [2, 2], 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 13: 11, 14: [1, 12], 15: [1, 20], 16: 17, 19: [1, 23], 24: 15, 27: 16, 29: [1, 21], 34: [1, 22], 39: [2, 2], 44: [2, 2], 47: [2, 2], 48: [1, 13], 51: [1, 14], 55: [1, 18], 59: 19, 60: [1, 24] }, { 1: [2, 1] }, { 5: [2, 47], 14: [2, 47], 15: [2, 47], 19: [2, 47], 29: [2, 47], 34: [2, 47], 39: [2, 47], 44: [2, 47], 47: [2, 47], 48: [2, 47], 51: [2, 47], 55: [2, 47], 60: [2, 47] }, { 5: [2, 3], 14: [2, 3], 15: [2, 3], 19: [2, 3], 29: [2, 3], 34: [2, 3], 39: [2, 3], 44: [2, 3], 47: [2, 3], 48: [2, 3], 51: [2, 3], 55: [2, 3], 60: [2, 3] }, { 5: [2, 4], 14: [2, 4], 15: [2, 4], 19: [2, 4], 29: [2, 4], 34: [2, 4], 39: [2, 4], 44: [2, 4], 47: [2, 4], 48: [2, 4], 51: [2, 4], 55: [2, 4], 60: [2, 4] }, { 5: [2, 5], 14: [2, 5], 15: [2, 5], 19: [2, 5], 29: [2, 5], 34: [2, 5], 39: [2, 5], 44: [2, 5], 47: [2, 5], 48: [2, 5], 51: [2, 5], 55: [2, 5], 60: [2, 5] }, { 5: [2, 6], 14: [2, 6], 15: [2, 6], 19: [2, 6], 29: [2, 6], 34: [2, 6], 39: [2, 6], 44: [2, 6], 47: [2, 6], 48: [2, 6], 51: [2, 6], 55: [2, 6], 60: [2, 6] }, { 5: [2, 7], 14: [2, 7], 15: [2, 7], 19: [2, 7], 29: [2, 7], 34: [2, 7], 39: [2, 7], 44: [2, 7], 47: [2, 7], 48: [2, 7], 51: [2, 7], 55: [2, 7], 60: [2, 7] }, { 5: [2, 8], 14: [2, 8], 15: [2, 8], 19: [2, 8], 29: [2, 8], 34: [2, 8], 39: [2, 8], 44: [2, 8], 47: [2, 8], 48: [2, 8], 51: [2, 8], 55: [2, 8], 60: [2, 8] }, { 5: [2, 9], 14: [2, 9], 15: [2, 9], 19: [2, 9], 29: [2, 9], 34: [2, 9], 39: [2, 9], 44: [2, 9], 47: [2, 9], 48: [2, 9], 51: [2, 9], 55: [2, 9], 60: [2, 9] }, { 20: 25, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 36, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 37, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 4: 38, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 13: 40, 15: [1, 20], 17: 39 }, { 20: 42, 56: 41, 64: 43, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 45, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 5: [2, 10], 14: [2, 10], 15: [2, 10], 18: [2, 10], 19: [2, 10], 29: [2, 10], 34: [2, 10], 39: [2, 10], 44: [2, 10], 47: [2, 10], 48: [2, 10], 51: [2, 10], 55: [2, 10], 60: [2, 10] }, { 20: 46, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 47, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 48, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 42, 56: 49, 64: 43, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [2, 78], 49: 50, 65: [2, 78], 72: [2, 78], 80: [2, 78], 81: [2, 78], 82: [2, 78], 83: [2, 78], 84: [2, 78], 85: [2, 78] }, { 23: [2, 33], 33: [2, 33], 54: [2, 33], 65: [2, 33], 68: [2, 33], 72: [2, 33], 75: [2, 33], 80: [2, 33], 81: [2, 33], 82: [2, 33], 83: [2, 33], 84: [2, 33], 85: [2, 33] }, { 23: [2, 34], 33: [2, 34], 54: [2, 34], 65: [2, 34], 68: [2, 34], 72: [2, 34], 75: [2, 34], 80: [2, 34], 81: [2, 34], 82: [2, 34], 83: [2, 34], 84: [2, 34], 85: [2, 34] }, { 23: [2, 35], 33: [2, 35], 54: [2, 35], 65: [2, 35], 68: [2, 35], 72: [2, 35], 75: [2, 35], 80: [2, 35], 81: [2, 35], 82: [2, 35], 83: [2, 35], 84: [2, 35], 85: [2, 35] }, { 23: [2, 36], 33: [2, 36], 54: [2, 36], 65: [2, 36], 68: [2, 36], 72: [2, 36], 75: [2, 36], 80: [2, 36], 81: [2, 36], 82: [2, 36], 83: [2, 36], 84: [2, 36], 85: [2, 36] }, { 23: [2, 37], 33: [2, 37], 54: [2, 37], 65: [2, 37], 68: [2, 37], 72: [2, 37], 75: [2, 37], 80: [2, 37], 81: [2, 37], 82: [2, 37], 83: [2, 37], 84: [2, 37], 85: [2, 37] }, { 23: [2, 38], 33: [2, 38], 54: [2, 38], 65: [2, 38], 68: [2, 38], 72: [2, 38], 75: [2, 38], 80: [2, 38], 81: [2, 38], 82: [2, 38], 83: [2, 38], 84: [2, 38], 85: [2, 38] }, { 23: [2, 39], 33: [2, 39], 54: [2, 39], 65: [2, 39], 68: [2, 39], 72: [2, 39], 75: [2, 39], 80: [2, 39], 81: [2, 39], 82: [2, 39], 83: [2, 39], 84: [2, 39], 85: [2, 39] }, { 23: [2, 43], 33: [2, 43], 54: [2, 43], 65: [2, 43], 68: [2, 43], 72: [2, 43], 75: [2, 43], 80: [2, 43], 81: [2, 43], 82: [2, 43], 83: [2, 43], 84: [2, 43], 85: [2, 43], 87: [1, 51] }, { 72: [1, 35], 86: 52 }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 52: 53, 54: [2, 82], 65: [2, 82], 72: [2, 82], 80: [2, 82], 81: [2, 82], 82: [2, 82], 83: [2, 82], 84: [2, 82], 85: [2, 82] }, { 25: 54, 38: 56, 39: [1, 58], 43: 57, 44: [1, 59], 45: 55, 47: [2, 54] }, { 28: 60, 43: 61, 44: [1, 59], 47: [2, 56] }, { 13: 63, 15: [1, 20], 18: [1, 62] }, { 15: [2, 48], 18: [2, 48] }, { 33: [2, 86], 57: 64, 65: [2, 86], 72: [2, 86], 80: [2, 86], 81: [2, 86], 82: [2, 86], 83: [2, 86], 84: [2, 86], 85: [2, 86] }, { 33: [2, 40], 65: [2, 40], 72: [2, 40], 80: [2, 40], 81: [2, 40], 82: [2, 40], 83: [2, 40], 84: [2, 40], 85: [2, 40] }, { 33: [2, 41], 65: [2, 41], 72: [2, 41], 80: [2, 41], 81: [2, 41], 82: [2, 41], 83: [2, 41], 84: [2, 41], 85: [2, 41] }, { 20: 65, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 66, 47: [1, 67] }, { 30: 68, 33: [2, 58], 65: [2, 58], 72: [2, 58], 75: [2, 58], 80: [2, 58], 81: [2, 58], 82: [2, 58], 83: [2, 58], 84: [2, 58], 85: [2, 58] }, { 33: [2, 64], 35: 69, 65: [2, 64], 72: [2, 64], 75: [2, 64], 80: [2, 64], 81: [2, 64], 82: [2, 64], 83: [2, 64], 84: [2, 64], 85: [2, 64] }, { 21: 70, 23: [2, 50], 65: [2, 50], 72: [2, 50], 80: [2, 50], 81: [2, 50], 82: [2, 50], 83: [2, 50], 84: [2, 50], 85: [2, 50] }, { 33: [2, 90], 61: 71, 65: [2, 90], 72: [2, 90], 80: [2, 90], 81: [2, 90], 82: [2, 90], 83: [2, 90], 84: [2, 90], 85: [2, 90] }, { 20: 75, 33: [2, 80], 50: 72, 63: 73, 64: 76, 65: [1, 44], 69: 74, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 72: [1, 80] }, { 23: [2, 42], 33: [2, 42], 54: [2, 42], 65: [2, 42], 68: [2, 42], 72: [2, 42], 75: [2, 42], 80: [2, 42], 81: [2, 42], 82: [2, 42], 83: [2, 42], 84: [2, 42], 85: [2, 42], 87: [1, 51] }, { 20: 75, 53: 81, 54: [2, 84], 63: 82, 64: 76, 65: [1, 44], 69: 83, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 84, 47: [1, 67] }, { 47: [2, 55] }, { 4: 85, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 47: [2, 20] }, { 20: 86, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 87, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 26: 88, 47: [1, 67] }, { 47: [2, 57] }, { 5: [2, 11], 14: [2, 11], 15: [2, 11], 19: [2, 11], 29: [2, 11], 34: [2, 11], 39: [2, 11], 44: [2, 11], 47: [2, 11], 48: [2, 11], 51: [2, 11], 55: [2, 11], 60: [2, 11] }, { 15: [2, 49], 18: [2, 49] }, { 20: 75, 33: [2, 88], 58: 89, 63: 90, 64: 76, 65: [1, 44], 69: 91, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 65: [2, 94], 66: 92, 68: [2, 94], 72: [2, 94], 80: [2, 94], 81: [2, 94], 82: [2, 94], 83: [2, 94], 84: [2, 94], 85: [2, 94] }, { 5: [2, 25], 14: [2, 25], 15: [2, 25], 19: [2, 25], 29: [2, 25], 34: [2, 25], 39: [2, 25], 44: [2, 25], 47: [2, 25], 48: [2, 25], 51: [2, 25], 55: [2, 25], 60: [2, 25] }, { 20: 93, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 31: 94, 33: [2, 60], 63: 95, 64: 76, 65: [1, 44], 69: 96, 70: 77, 71: 78, 72: [1, 79], 75: [2, 60], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 33: [2, 66], 36: 97, 63: 98, 64: 76, 65: [1, 44], 69: 99, 70: 77, 71: 78, 72: [1, 79], 75: [2, 66], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 22: 100, 23: [2, 52], 63: 101, 64: 76, 65: [1, 44], 69: 102, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 33: [2, 92], 62: 103, 63: 104, 64: 76, 65: [1, 44], 69: 105, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 106] }, { 33: [2, 79], 65: [2, 79], 72: [2, 79], 80: [2, 79], 81: [2, 79], 82: [2, 79], 83: [2, 79], 84: [2, 79], 85: [2, 79] }, { 33: [2, 81] }, { 23: [2, 27], 33: [2, 27], 54: [2, 27], 65: [2, 27], 68: [2, 27], 72: [2, 27], 75: [2, 27], 80: [2, 27], 81: [2, 27], 82: [2, 27], 83: [2, 27], 84: [2, 27], 85: [2, 27] }, { 23: [2, 28], 33: [2, 28], 54: [2, 28], 65: [2, 28], 68: [2, 28], 72: [2, 28], 75: [2, 28], 80: [2, 28], 81: [2, 28], 82: [2, 28], 83: [2, 28], 84: [2, 28], 85: [2, 28] }, { 23: [2, 30], 33: [2, 30], 54: [2, 30], 68: [2, 30], 71: 107, 72: [1, 108], 75: [2, 30] }, { 23: [2, 98], 33: [2, 98], 54: [2, 98], 68: [2, 98], 72: [2, 98], 75: [2, 98] }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 73: [1, 109], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 23: [2, 44], 33: [2, 44], 54: [2, 44], 65: [2, 44], 68: [2, 44], 72: [2, 44], 75: [2, 44], 80: [2, 44], 81: [2, 44], 82: [2, 44], 83: [2, 44], 84: [2, 44], 85: [2, 44], 87: [2, 44] }, { 54: [1, 110] }, { 54: [2, 83], 65: [2, 83], 72: [2, 83], 80: [2, 83], 81: [2, 83], 82: [2, 83], 83: [2, 83], 84: [2, 83], 85: [2, 83] }, { 54: [2, 85] }, { 5: [2, 13], 14: [2, 13], 15: [2, 13], 19: [2, 13], 29: [2, 13], 34: [2, 13], 39: [2, 13], 44: [2, 13], 47: [2, 13], 48: [2, 13], 51: [2, 13], 55: [2, 13], 60: [2, 13] }, { 38: 56, 39: [1, 58], 43: 57, 44: [1, 59], 45: 112, 46: 111, 47: [2, 76] }, { 33: [2, 70], 40: 113, 65: [2, 70], 72: [2, 70], 75: [2, 70], 80: [2, 70], 81: [2, 70], 82: [2, 70], 83: [2, 70], 84: [2, 70], 85: [2, 70] }, { 47: [2, 18] }, { 5: [2, 14], 14: [2, 14], 15: [2, 14], 19: [2, 14], 29: [2, 14], 34: [2, 14], 39: [2, 14], 44: [2, 14], 47: [2, 14], 48: [2, 14], 51: [2, 14], 55: [2, 14], 60: [2, 14] }, { 33: [1, 114] }, { 33: [2, 87], 65: [2, 87], 72: [2, 87], 80: [2, 87], 81: [2, 87], 82: [2, 87], 83: [2, 87], 84: [2, 87], 85: [2, 87] }, { 33: [2, 89] }, { 20: 75, 63: 116, 64: 76, 65: [1, 44], 67: 115, 68: [2, 96], 69: 117, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 118] }, { 32: 119, 33: [2, 62], 74: 120, 75: [1, 121] }, { 33: [2, 59], 65: [2, 59], 72: [2, 59], 75: [2, 59], 80: [2, 59], 81: [2, 59], 82: [2, 59], 83: [2, 59], 84: [2, 59], 85: [2, 59] }, { 33: [2, 61], 75: [2, 61] }, { 33: [2, 68], 37: 122, 74: 123, 75: [1, 121] }, { 33: [2, 65], 65: [2, 65], 72: [2, 65], 75: [2, 65], 80: [2, 65], 81: [2, 65], 82: [2, 65], 83: [2, 65], 84: [2, 65], 85: [2, 65] }, { 33: [2, 67], 75: [2, 67] }, { 23: [1, 124] }, { 23: [2, 51], 65: [2, 51], 72: [2, 51], 80: [2, 51], 81: [2, 51], 82: [2, 51], 83: [2, 51], 84: [2, 51], 85: [2, 51] }, { 23: [2, 53] }, { 33: [1, 125] }, { 33: [2, 91], 65: [2, 91], 72: [2, 91], 80: [2, 91], 81: [2, 91], 82: [2, 91], 83: [2, 91], 84: [2, 91], 85: [2, 91] }, { 33: [2, 93] }, { 5: [2, 22], 14: [2, 22], 15: [2, 22], 19: [2, 22], 29: [2, 22], 34: [2, 22], 39: [2, 22], 44: [2, 22], 47: [2, 22], 48: [2, 22], 51: [2, 22], 55: [2, 22], 60: [2, 22] }, { 23: [2, 99], 33: [2, 99], 54: [2, 99], 68: [2, 99], 72: [2, 99], 75: [2, 99] }, { 73: [1, 109] }, { 20: 75, 63: 126, 64: 76, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 23], 14: [2, 23], 15: [2, 23], 19: [2, 23], 29: [2, 23], 34: [2, 23], 39: [2, 23], 44: [2, 23], 47: [2, 23], 48: [2, 23], 51: [2, 23], 55: [2, 23], 60: [2, 23] }, { 47: [2, 19] }, { 47: [2, 77] }, { 20: 75, 33: [2, 72], 41: 127, 63: 128, 64: 76, 65: [1, 44], 69: 129, 70: 77, 71: 78, 72: [1, 79], 75: [2, 72], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 24], 14: [2, 24], 15: [2, 24], 19: [2, 24], 29: [2, 24], 34: [2, 24], 39: [2, 24], 44: [2, 24], 47: [2, 24], 48: [2, 24], 51: [2, 24], 55: [2, 24], 60: [2, 24] }, { 68: [1, 130] }, { 65: [2, 95], 68: [2, 95], 72: [2, 95], 80: [2, 95], 81: [2, 95], 82: [2, 95], 83: [2, 95], 84: [2, 95], 85: [2, 95] }, { 68: [2, 97] }, { 5: [2, 21], 14: [2, 21], 15: [2, 21], 19: [2, 21], 29: [2, 21], 34: [2, 21], 39: [2, 21], 44: [2, 21], 47: [2, 21], 48: [2, 21], 51: [2, 21], 55: [2, 21], 60: [2, 21] }, { 33: [1, 131] }, { 33: [2, 63] }, { 72: [1, 133], 76: 132 }, { 33: [1, 134] }, { 33: [2, 69] }, { 15: [2, 12] }, { 14: [2, 26], 15: [2, 26], 19: [2, 26], 29: [2, 26], 34: [2, 26], 47: [2, 26], 48: [2, 26], 51: [2, 26], 55: [2, 26], 60: [2, 26] }, { 23: [2, 31], 33: [2, 31], 54: [2, 31], 68: [2, 31], 72: [2, 31], 75: [2, 31] }, { 33: [2, 74], 42: 135, 74: 136, 75: [1, 121] }, { 33: [2, 71], 65: [2, 71], 72: [2, 71], 75: [2, 71], 80: [2, 71], 81: [2, 71], 82: [2, 71], 83: [2, 71], 84: [2, 71], 85: [2, 71] }, { 33: [2, 73], 75: [2, 73] }, { 23: [2, 29], 33: [2, 29], 54: [2, 29], 65: [2, 29], 68: [2, 29], 72: [2, 29], 75: [2, 29], 80: [2, 29], 81: [2, 29], 82: [2, 29], 83: [2, 29], 84: [2, 29], 85: [2, 29] }, { 14: [2, 15], 15: [2, 15], 19: [2, 15], 29: [2, 15], 34: [2, 15], 39: [2, 15], 44: [2, 15], 47: [2, 15], 48: [2, 15], 51: [2, 15], 55: [2, 15], 60: [2, 15] }, { 72: [1, 138], 77: [1, 137] }, { 72: [2, 100], 77: [2, 100] }, { 14: [2, 16], 15: [2, 16], 19: [2, 16], 29: [2, 16], 34: [2, 16], 44: [2, 16], 47: [2, 16], 48: [2, 16], 51: [2, 16], 55: [2, 16], 60: [2, 16] }, { 33: [1, 139] }, { 33: [2, 75] }, { 33: [2, 32] }, { 72: [2, 101], 77: [2, 101] }, { 14: [2, 17], 15: [2, 17], 19: [2, 17], 29: [2, 17], 34: [2, 17], 39: [2, 17], 44: [2, 17], 47: [2, 17], 48: [2, 17], 51: [2, 17], 55: [2, 17], 60: [2, 17] }],
16704	        defaultActions: { 4: [2, 1], 55: [2, 55], 57: [2, 20], 61: [2, 57], 74: [2, 81], 83: [2, 85], 87: [2, 18], 91: [2, 89], 102: [2, 53], 105: [2, 93], 111: [2, 19], 112: [2, 77], 117: [2, 97
16704], 120: [2, 63], 123: [2, 69], 124: [2, 12], 136: [2, 75], 137
vendor: 13,423 bytes, lines 16704-16988
16704: [2, 32] },
16705	        parseError: function parseError(str, hash) {
16706	            throw new Error(str);
16707	        },
16708	        parse: function parse(input) {
16709	            var self = this,
16710	                stack = [0],
16711	                vstack = [null],
16712	                lstack = [],
16713	                table = this.table,
16714	                yytext = "",
16715	                yylineno = 0,
16716	                yyleng = 0,
16717	                recovering = 0,
16718	                TERROR = 2,
16719	                EOF = 1;
16720	            this.lexer.setInput(input);
16721	            this.lexer.yy = this.yy;
16722	            this.yy.lexer = this.lexer;
16723	            this.yy.parser = this;
16724	            if (typeof this.lexer.yylloc == "undefined") this.lexer.yylloc = {};
16725	            var yyloc = this.lexer.yylloc;
16726	            lstack.push(yyloc);
16727	            var ranges = this.lexer.options && this.lexer.options.ranges;
16728	            if (typeof this.yy.parseError === "function") this.parseError = this.yy.parseError;
16729	            function popStack(n) {
16730	                stack.length = stack.length - 2 * n;
16731	                vstack.length = vstack.length - n;
16732	                lstack.length = lstack.length - n;
16733	            }
16734	            function lex() {
16735	                var token;
16736	                token = self.lexer.lex() || 1;
16737	                if (typeof token !== "number") {
16738	                    token = self.symbols_[token] || token;
16739	                }
16740	                return token;
16741	            }
16742	            var symbol,
16743	                preErrorSymbol,
16744	                state,
16745	                action,
16746	                a,
16747	                r,
16748	                yyval = {},
16749	                p,
16750	                len,
16751	                newState,
16752	                expected;
16753	            while (true) {
16754	                state = stack[stack.length - 1];
16755	                if (this.defaultActions[state]) {
16756	                    action = this.defaultActions[state];
16757	                } else {
16758	                    if (symbol === null || typeof symbol == "undefined") {
16759	                        symbol = lex();
16760	                    }
16761	                    action = table[state] && table[state][symbol];
16762	                }
16763	                if (typeof action === "undefined" || !action.length || !action[0]) {
16764	                    var errStr = "";
16765	                    if (!recovering) {
16766	                        expected = [];
16767	                        for (p in table[state]) if (this.terminals_[p] && p > 2) {
16768	                            expected.push("'" + this.terminals_[p] + "'");
16769	                        }
16770	                        if (this.lexer.showPosition) {
16771	                            errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
16772	                        } else {
16773	                            errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1 ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'");
16774	                        }
16775	                        this.parseError(errStr, { text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected });
16776	                    }
16777	                }
16778	                if (action[0] instanceof Array && action.length > 1) {
16779	                    throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
16780	                }
16781	                switch (action[0]) {
16782	                    case 1:
16783	                        stack.push(symbol);
16784	                        vstack.push(this.lexer.yytext);
16785	                        lstack.push(this.lexer.yylloc);
16786	                        stack.push(action[1]);
16787	                        symbol = null;
16788	                        if (!preErrorSymbol) {
16789	                            yyleng = this.lexer.yyleng;
16790	                            yytext = this.lexer.yytext;
16791	                            yylineno = this.lexer.yylineno;
16792	                            yyloc = this.lexer.yylloc;
16793	                            if (recovering > 0) recovering--;
16794	                        } else {
16795	                            symbol = preErrorSymbol;
16796	                            preErrorSymbol = null;
16797	                        }
16798	                        break;
16799	                    case 2:
16800	                        len = this.productions_[action[1]][1];
16801	                        yyval.$ = vstack[vstack.length - len];
16802	                        yyval._$ = { first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column };
16803	                        if (ranges) {
16804	                            yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
16805	                        }
16806	                        r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
16807	                        if (typeof r !== "undefined") {
16808	                            return r;
16809	                        }
16810	                        if (len) {
16811	                            stack = stack.slice(0, -1 * len * 2);
16812	                            vstack = vstack.slice(0, -1 * len);
16813	                            lstack = lstack.slice(0, -1 * len);
16814	                        }
16815	                        stack.push(this.productions_[action[1]][0]);
16816	                        vstack.push(yyval.$);
16817	                        lstack.push(yyval._$);
16818	                        newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
16819	                        stack.push(newState);
16820	                        break;
16821	                    case 3:
16822	                        return true;
16823	                }
16824	            }
16825	            return true;
16826	        }
16827	    };
16828	    /* Jison generated lexer */
16829	    var lexer = (function () {
16830	        var lexer = { EOF: 1,
16831	            parseError: function parseError(str, hash) {
16832	                if (this.yy.parser) {
16833	                    this.yy.parser.parseError(str, hash);
16834	                } else {
16835	                    throw new Error(str);
16836	                }
16837	            },
16838	            setInput: function setInput(input) {
16839	                this._input = input;
16840	                this._more = this._less = this.done = false;
16841	                this.yylineno = this.yyleng = 0;
16842	                this.yytext = this.matched = this.match = '';
16843	                this.conditionStack = ['INITIAL'];
16844	                this.yylloc = { first_line: 1, first_column: 0, last_line: 1, last_column: 0 };
16845	                if (this.options.ranges) this.yylloc.range = [0, 0];
16846	                this.offset = 0;
16847	                return this;
16848	            },
16849	            input: function input() {
16850	                var ch = this._input[0];
16851	                this.yytext += ch;
16852	                this.yyleng++;
16853	                this.offset++;
16854	                this.match += ch;
16855	                this.matched += ch;
16856	                var lines = ch.match(/(?:\r\n?|\n).*/g);
16857	                if (lines) {
16858	                    this.yylineno++;
16859	                    this.yylloc.last_line++;
16860	                } else {
16861	                    this.yylloc.last_column++;
16862	                }
16863	                if (this.options.ranges) this.yylloc.range[1]++;
16864
16865	                this._input = this._input.slice(1);
16866	                return ch;
16867	            },
16868	            unput: function unput(ch) {
16869	                var len = ch.length;
16870	                var lines = ch.split(/(?:\r\n?|\n)/g);
16871
16872	                this._input = ch + this._input;
16873	                this.yytext = this.yytext.substr(0, this.yytext.length - len - 1);
16874	                //this.yyleng -= len;
16875	                this.offset -= len;
16876	                var oldLines = this.match.split(/(?:\r\n?|\n)/g);
16877	                this.match = this.match.substr(0, this.match.length - 1);
16878	                this.matched = this.matched.substr(0, this.matched.length - 1);
16879
16880	                if (lines.length - 1) this.yylineno -= lines.length - 1;
16881	                var r = this.yylloc.range;
16882
16883	                this.yylloc = { first_line: this.yylloc.first_line,
16884	                    last_line: this.yylineno + 1,
16885	                    first_column: this.yylloc.first_column,
16886	                    last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
16887	                };
16888
16889	                if (this.options.ranges) {
16890	                    this.yylloc.range = [r[0], r[0] + this.yyleng - len];
16891	                }
16892	                return this;
16893	            },
16894	            more: function more() {
16895	                this._more = true;
16896	                return this;
16897	            },
16898	            less: function less(n) {
16899	                this.unput(this.match.slice(n));
16900	            },
16901	            pastInput: function pastInput() {
16902	                var past = this.matched.substr(0, this.matched.length - this.match.length);
16903	                return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
16904	            },
16905	            upcomingInput: function upcomingInput() {
16906	                var next = this.match;
16907	                if (next.length < 20) {
16908	                    next += this._input.substr(0, 20 - next.length);
16909	                }
16910	                return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
16911	            },
16912	            showPosition: function showPosition() {
16913	                var pre = this.pastInput();
16914	                var c = new Array(pre.length + 1).join("-");
16915	                return pre + this.upcomingInput() + "\n" + c + "^";
16916	            },
16917	            next: function next() {
16918	                if (this.done) {
16919	                    return this.EOF;
16920	                }
16921	                if (!this._input) this.done = true;
16922
16923	                var token, match, tempMatch, index, col, lines;
16924	                if (!this._more) {
16925	                    this.yytext = '';
16926	                    this.match = '';
16927	                }
16928	                var rules = this._currentRules();
16929	                for (var i = 0; i < rules.length; i++) {
16930	                    tempMatch = this._input.match(this.rules[rules[i]]);
16931	                    if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
16932	                        match = tempMatch;
16933	                        index = i;
16934	                        if (!this.options.flex) break;
16935	                    }
16936	                }
16937	                if (match) {
16938	                    lines = match[0].match(/(?:\r\n?|\n).*/g);
16939	                    if (lines) this.yylineno += lines.length;
16940	                    this.yylloc = { first_line: this.yylloc.last_line,
16941	                        last_line: this.yylineno + 1,
16942	                        first_column: this.yylloc.last_column,
16943	                        last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length };
16944	                    this.yytext += match[0];
16945	                    this.match += match[0];
16946	                    this.matches = match;
16947	                    this.yyleng = this.yytext.length;
16948	                    if (this.options.ranges) {
16949	                        this.yylloc.range = [this.offset, this.offset += this.yyleng];
16950	                    }
16951	                    this._more = false;
16952	                    this._input = this._input.slice(match[0].length);
16953	                    this.matched += match[0];
16954	                    token = this.performAction.call(this, this.yy, this, rules[index], this.conditionStack[this.conditionStack.length - 1]);
16955	                    if (this.done && this._input) this.done = false;
16956	                    if (token) return token;else return;
16957	                }
16958	                if (this._input === "") {
16959	                    return this.EOF;
16960	                } else {
16961	                    return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { text: "", token: null, line: this.yylineno });
16962	                }
16963	            },
16964	            lex: function lex() {
16965	                var r = this.next();
16966	                if (typeof r !== 'undefined') {
16967	                    return r;
16968	                } else {
16969	                    return this.lex();
16970	                }
16971	            },
16972	            begin: function begin(condition) {
16973	                this.conditionStack.push(condition);
16974	            },
16975	            popState: function popState() {
16976	                return this.conditionStack.pop();
16977	            },
16978	            _currentRules: function _currentRules() {
16979	                return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
16980	            },
16981	            topState: function topState() {
16982	                return this.conditionStack[this.conditionStack.length - 2];
16983	            },
16984	            pushState: function begin(condition) {
16985	                this.begin(condition);
16986	            } };
16987	        lexer.options = {};
16988	        lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START
vendor: 7,146 bytes, lines 16988-17168
16988
16989	        /**/) {
16990
16991	            function strip(start, end) {
16992	                return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng - end);
16993	            }
16994
16995	            var YYSTATE = YY_START;
16996	            switch ($avoiding_name_collisions) {
16997	                case 0:
16998	                    if (yy_.yytext.slice(-2) === "\\\\") {
16999	                        strip(0, 1);
17000	                        this.begin("mu");
17001	                    } else if (yy_.yytext.slice(-1) === "\\") {
17002	                        strip(0, 1);
17003	                        this.begin("emu");
17004	                    } else {
17005	                        this.begin("mu");
17006	                    }
17007	                    if (yy_.yytext) return 15;
17008
17009	                    break;
17010	                case 1:
17011	                    return 15;
17012	                    break;
17013	                case 2:
17014	                    this.popState();
17015	                    return 15;
17016
17017	                    break;
17018	                case 3:
17019	                    this.begin('raw');return 15;
17020	                    break;
17021	                case 4:
17022	                    this.popState();
17023	                    // Should be using `this.topState()` below, but it currently
17024	                    // returns the second top instead of the first top. Opened an
17025	                    // issue about it at https://github.com/zaach/jison/issues/291
17026	                    if (this.conditionStack[this.conditionStack.length - 1] === 'raw') {
17027	                        return 15;
17028	                    } else {
17029	                        yy_.yytext = yy_.yytext.substr(5, yy_.yyleng - 9);
17030	                        return 'END_RAW_BLOCK';
17031	                    }
17032
17033	                    break;
17034	                case 5:
17035	                    return 15;
17036	                    break;
17037	                case 6:
17038	                    this.popState();
17039	                    return 14;
17040
17041	                    break;
17042	                case 7:
17043	                    return 65;
17044	                    break;
17045	                case 8:
17046	                    return 68;
17047	                    break;
17048	                case 9:
17049	                    return 19;
17050	                    break;
17051	                case 10:
17052	                    this.popState();
17053	                    this.begin('raw');
17054	                    return 23;
17055
17056	                    break;
17057	                case 11:
17058	                    return 55;
17059	                    break;
17060	                case 12:
17061	                    return 60;
17062	                    break;
17063	                case 13:
17064	                    return 29;
17065	                    break;
17066	                case 14:
17067	                    return 47;
17068	                    break;
17069	                case 15:
17070	                    this.popState();return 44;
17071	                    break;
17072	                case 16:
17073	                    this.popState();return 44;
17074	                    break;
17075	                case 17:
17076	                    return 34;
17077	                    break;
17078	                case 18:
17079	                    return 39;
17080	                    break;
17081	                case 19:
17082	                    return 51;
17083	                    break;
17084	                case 20:
17085	                    return 48;
17086	                    break;
17087	                case 21:
17088	                    this.unput(yy_.yytext);
17089	                    this.popState();
17090	                    this.begin('com');
17091
17092	                    break;
17093	                case 22:
17094	                    this.popState();
17095	                    return 14;
17096
17097	                    break;
17098	                case 23:
17099	                    return 48;
17100	                    break;
17101	                case 24:
17102	                    return 73;
17103	                    break;
17104	                case 25:
17105	                    return 72;
17106	                    break;
17107	                case 26:
17108	                    return 72;
17109	                    break;
17110	                case 27:
17111	                    return 87;
17112	                    break;
17113	                case 28:
17114	                    // ignore whitespace
17115	                    break;
17116	                case 29:
17117	                    this.popState();return 54;
17118	                    break;
17119	                case 30:
17120	                    this.popState();return 33;
17121	                    break;
17122	                case 31:
17123	                    yy_.yytext = strip(1, 2).replace(/\\"/g, '"');return 80;
17124	                    break;
17125	                case 32:
17126	                    yy_.yytext = strip(1, 2).replace(/\\'/g, "'");return 80;
17127	                    break;
17128	                case 33:
17129	                    return 85;
17130	                    break;
17131	                case 34:
17132	                    return 82;
17133	                    break;
17134	                case 35:
17135	                    return 82;
17136	                    break;
17137	                case 36:
17138	                    return 83;
17139	                    break;
17140	                case 37:
17141	                    return 84;
17142	                    break;
17143	                case 38:
17144	                    return 81;
17145	                    break;
17146	                case 39:
17147	                    return 75;
17148	                    break;
17149	                case 40:
17150	                    return 77;
17151	                    break;
17152	                case 41:
17153	                    return 72;
17154	                    break;
17155	                case 42:
17156	                    yy_.yytext = yy_.yytext.replace(/\\([\\\]])/g, '$1');return 72;
17157	                    break;
17158	                case 43:
17159	                    return 'INVALID';
17160	                    break;
17161	                case 44:
17162	                    return 5;
17163	                    break;
17164	            }
17165	        };
17166	        lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/, /^(?:[^\x00]+)/, /^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/, /^(?:\{\{\{\{(?=[^\/]))/, /^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/, /^(?:[^\x00]*?(?=(\{\{\{\{)))/, /^(?:[\s\S]*?--(~)?\}\})/, /^(?:\()/, /^(?:\))/, /^(?:\{\{\{\{)/, /^(?:\}\}\}\})/, /^(?:\{\{(~)?>)/, /^(?:\{\{(~)?#>)/, /^(?:\{\{(~)?#\*?)/, /^(?:\{\{(~)?\/)/, /^(?:\{\{(~)?\^\s*(~)?\}\})/, /^(?:\{\{(~)?\s*else\s*(~)?\}\})/, /^(?:\{\{(~)?\^)/, /^(?:\{\{(~)?\s*else\b)/, /^(?:\{\{(~)?\{)/, /^(?:\{\{(~)?&)/, /^(?:\{\{(~)?!--)/, /^(?:\{\{(~)?![\s\S]*?\}\})/, /^(?:\{\{(~)?\*?)/, /^(?:=)/, /^(?:\.\.)/, /^(?:\.(?=([=~}\s\/.)|])))/, /^(?:[\/.])/, /^(?:\s+)/, /^(?:\}(~)?\}\})/, /^(?:(~)?\}\})/, /^(?:"(\\["]|[^"])*")/, /^(?:'(\\[']|[^'])*')/, /^(?:@)/, /^(?:true(?=([~}\s)])))/, /^(?:false(?=([~}\s)])))/, /^(?:undefined(?=([~}\s)])))/, /^(?:null(?=([~}\s)])))/, /^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/, /^(?:as\s+\|)/, /^(?:\|)/, /^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/, /^(?:\[(\\\]|[^\]])*\])/, /^(?:.)/, /^(?:$)/];
17167	        lexer.conditions = { "mu": { "rules": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44], "inclusive": false }, "emu": { "rules": [2], "inclusive": false }, "com": { "rules": [6], "inclusive": false }, "raw": { "rules": [3, 4, 5], "inclusive": false }, "INITIAL": { "rules": [0, 1, 44], "inclusive": true } };
17168	        return lexer;
vendor: 13,265 bytes, lines 17169-17631
17169	    })();
17170	    parser.lexer = lexer;
17171	    function Parser() {
17172	        this.yy = {};
17173	    }Parser.prototype = parser;parser.Parser = Parser;
17174	    return new Parser();
17175	})();exports["default"] = handlebars;
17176	module.exports = exports["default"];
17177
17178/***/ }),
17179/* 38 */
17180/***/ (function(module, exports, __webpack_require__) {
17181
17182	'use strict';
17183
17184	var _interopRequireDefault = __webpack_require__(1)['default'];
17185
17186	exports.__esModule = true;
17187
17188	var _visitor = __webpack_require__(39);
17189
17190	var _visitor2 = _interopRequireDefault(_visitor);
17191
17192	function WhitespaceControl() {
17193	  var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
17194
17195	  this.options = options;
17196	}
17197	WhitespaceControl.prototype = new _visitor2['default']();
17198
17199	WhitespaceControl.prototype.Program = function (program) {
17200	  var doStandalone = !this.options.ignoreStandalone;
17201
17202	  var isRoot = !this.isRootSeen;
17203	  this.isRootSeen = true;
17204
17205	  var body = program.body;
17206	  for (var i = 0, l = body.length; i < l; i++) {
17207	    var current = body[i],
17208	        strip = this.accept(current);
17209
17210	    if (!strip) {
17211	      continue;
17212	    }
17213
17214	    var _isPrevWhitespace = isPrevWhitespace(body, i, isRoot),
17215	        _isNextWhitespace = isNextWhitespace(body, i, isRoot),
17216	        openStandalone = strip.openStandalone && _isPrevWhitespace,
17217	        closeStandalone = strip.closeStandalone && _isNextWhitespace,
17218	        inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace;
17219
17220	    if (strip.close) {
17221	      omitRight(body, i, true);
17222	    }
17223	    if (strip.open) {
17224	      omitLeft(body, i, true);
17225	    }
17226
17227	    if (doStandalone && inlineStandalone) {
17228	      omitRight(body, i);
17229
17230	      if (omitLeft(body, i)) {
17231	        // If we are on a standalone node, save the indent info for partials
17232	        if (current.type === 'PartialStatement') {
17233	          // Pull out the whitespace from the final line
17234	          current.indent = /([ \t]+$)/.exec(body[i - 1].original)[1];
17235	        }
17236	      }
17237	    }
17238	    if (doStandalone && openStandalone) {
17239	      omitRight((current.program || current.inverse).body);
17240
17241	      // Strip out the previous content node if it's whitespace only
17242	      omitLeft(body, i);
17243	    }
17244	    if (doStandalone && closeStandalone) {
17245	      // Always strip the next node
17246	      omitRight(body, i);
17247
17248	      omitLeft((current.inverse || current.program).body);
17249	    }
17250	  }
17251
17252	  return program;
17253	};
17254
17255	WhitespaceControl.prototype.BlockStatement = WhitespaceControl.prototype.DecoratorBlock = WhitespaceControl.prototype.PartialBlockStatement = function (block) {
17256	  this.accept(block.program);
17257	  this.accept(block.inverse);
17258
17259	  // Find the inverse program that is involed with whitespace stripping.
17260	  var program = block.program || block.inverse,
17261	      inverse = block.program && block.inverse,
17262	      firstInverse = inverse,
17263	      lastInverse = inverse;
17264
17265	  if (inverse && inverse.chained) {
17266	    firstInverse = inverse.body[0].program;
17267
17268	    // Walk the inverse chain to find the last inverse that is actually in the chain.
17269	    while (lastInverse.chained) {
17270	      lastInverse = lastInverse.body[lastInverse.body.length - 1].program;
17271	    }
17272	  }
17273
17274	  var strip = {
17275	    open: block.openStrip.open,
17276	    close: block.closeStrip.close,
17277
17278	    // Determine the standalone candiacy. Basically flag our content as being possibly standalone
17279	    // so our parent can determine if we actually are standalone
17280	    openStandalone: isNextWhitespace(program.body),
17281	    closeStandalone: isPrevWhitespace((firstInverse || program).body)
17282	  };
17283
17284	  if (block.openStrip.close) {
17285	    omitRight(program.body, null, true);
17286	  }
17287
17288	  if (inverse) {
17289	    var inverseStrip = block.inverseStrip;
17290
17291	    if (inverseStrip.open) {
17292	      omitLeft(program.body, null, true);
17293	    }
17294
17295	    if (inverseStrip.close) {
17296	      omitRight(firstInverse.body, null, true);
17297	    }
17298	    if (block.closeStrip.open) {
17299	      omitLeft(lastInverse.body, null, true);
17300	    }
17301
17302	    // Find standalone else statments
17303	    if (!this.options.ignoreStandalone && isPrevWhitespace(program.body) && isNextWhitespace(firstInverse.body)) {
17304	      omitLeft(program.body);
17305	      omitRight(firstInverse.body);
17306	    }
17307	  } else if (block.closeStrip.open) {
17308	    omitLeft(program.body, null, true);
17309	  }
17310
17311	  return strip;
17312	};
17313
17314	WhitespaceControl.prototype.Decorator = WhitespaceControl.prototype.MustacheStatement = function (mustache) {
17315	  return mustache.strip;
17316	};
17317
17318	WhitespaceControl.prototype.PartialStatement = WhitespaceControl.prototype.CommentStatement = function (node) {
17319	  /* istanbul ignore next */
17320	  var strip = node.strip || {};
17321	  return {
17322	    inlineStandalone: true,
17323	    open: strip.open,
17324	    close: strip.close
17325	  };
17326	};
17327
17328	function isPrevWhitespace(body, i, isRoot) {
17329	  if (i === undefined) {
17330	    i = body.length;
17331	  }
17332
17333	  // Nodes that end with newlines are considered whitespace (but are special
17334	  // cased for strip operations)
17335	  var prev = body[i - 1],
17336	      sibling = body[i - 2];
17337	  if (!prev) {
17338	    return isRoot;
17339	  }
17340
17341	  if (prev.type === 'ContentStatement') {
17342	    return (sibling || !isRoot ? /\r?\n\s*?$/ : /(^|\r?\n)\s*?$/).test(prev.original);
17343	  }
17344	}
17345	function isNextWhitespace(body, i, isRoot) {
17346	  if (i === undefined) {
17347	    i = -1;
17348	  }
17349
17350	  var next = body[i + 1],
17351	      sibling = body[i + 2];
17352	  if (!next) {
17353	    return isRoot;
17354	  }
17355
17356	  if (next.type === 'ContentStatement') {
17357	    return (sibling || !isRoot ? /^\s*?\r?\n/ : /^\s*?(\r?\n|$)/).test(next.original);
17358	  }
17359	}
17360
17361	// Marks the node to the right of the position as omitted.
17362	// I.e. {{foo}}' ' will mark the ' ' node as omitted.
17363	//
17364	// If i is undefined, then the first child will be marked as such.
17365	//
17366	// If mulitple is truthy then all whitespace will be stripped out until non-whitespace
17367	// content is met.
17368	function omitRight(body, i, multiple) {
17369	  var current = body[i == null ? 0 : i + 1];
17370	  if (!current || current.type !== 'ContentStatement' || !multiple && current.rightStripped) {
17371	    return;
17372	  }
17373
17374	  var original = current.value;
17375	  current.value = current.value.replace(multiple ? /^\s+/ : /^[ \t]*\r?\n?/, '');
17376	  current.rightStripped = current.value !== original;
17377	}
17378
17379	// Marks the node to the left of the position as omitted.
17380	// I.e. ' '{{foo}} will mark the ' ' node as omitted.
17381	//
17382	// If i is undefined then the last child will be marked as such.
17383	//
17384	// If mulitple is truthy then all whitespace will be stripped out until non-whitespace
17385	// content is met.
17386	function omitLeft(body, i, multiple) {
17387	  var current = body[i == null ? body.length - 1 : i - 1];
17388	  if (!current || current.type !== 'ContentStatement' || !multiple && current.leftStripped) {
17389	    return;
17390	  }
17391
17392	  // We omit the last node if it's whitespace only and not preceeded by a non-content node.
17393	  var original = current.value;
17394	  current.value = current.value.replace(multiple ? /\s+$/ : /[ \t]+$/, '');
17395	  current.leftStripped = current.value !== original;
17396	  return current.leftStripped;
17397	}
17398
17399	exports['default'] = WhitespaceControl;
17400	module.exports = exports['default'];
17401
17402/***/ }),
17403/* 39 */
17404/***/ (function(module, exports, __webpack_require__) {
17405
17406	'use strict';
17407
17408	var _interopRequireDefault = __webpack_require__(1)['default'];
17409
17410	exports.__esModule = true;
17411
17412	var _exception = __webpack_require__(6);
17413
17414	var _exception2 = _interopRequireDefault(_exception);
17415
17416	function Visitor() {
17417	  this.parents = [];
17418	}
17419
17420	Visitor.prototype = {
17421	  constructor: Visitor,
17422	  mutating: false,
17423
17424	  // Visits a given value. If mutating, will replace the value if necessary.
17425	  acceptKey: function acceptKey(node, name) {
17426	    var value = this.accept(node[name]);
17427	    if (this.mutating) {
17428	      // Hacky sanity check: This may have a few false positives for type for the helper
17429	      // methods but will generally do the right thing without a lot of overhead.
17430	      if (value && !Visitor.prototype[value.type]) {
17431	        throw new _exception2['default']('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type);
17432	      }
17433	      node[name] = value;
17434	    }
17435	  },
17436
17437	  // Performs an accept operation with added sanity check to ensure
17438	  // required keys are not removed.
17439	  acceptRequired: function acceptRequired(node, name) {
17440	    this.acceptKey(node, name);
17441
17442	    if (!node[name]) {
17443	      throw new _exception2['default'](node.type + ' requires ' + name);
17444	    }
17445	  },
17446
17447	  // Traverses a given array. If mutating, empty respnses will be removed
17448	  // for child elements.
17449	  acceptArray: function acceptArray(array) {
17450	    for (var i = 0, l = array.length; i < l; i++) {
17451	      this.acceptKey(array, i);
17452
17453	      if (!array[i]) {
17454	        array.splice(i, 1);
17455	        i--;
17456	        l--;
17457	      }
17458	    }
17459	  },
17460
17461	  accept: function accept(object) {
17462	    if (!object) {
17463	      return;
17464	    }
17465
17466	    /* istanbul ignore next: Sanity code */
17467	    if (!this[object.type]) {
17468	      throw new _exception2['default']('Unknown type: ' + object.type, object);
17469	    }
17470
17471	    if (this.current) {
17472	      this.parents.unshift(this.current);
17473	    }
17474	    this.current = object;
17475
17476	    var ret = this[object.type](object);
17477
17478	    this.current = this.parents.shift();
17479
17480	    if (!this.mutating || ret) {
17481	      return ret;
17482	    } else if (ret !== false) {
17483	      return object;
17484	    }
17485	  },
17486
17487	  Program: function Program(program) {
17488	    this.acceptArray(program.body);
17489	  },
17490
17491	  MustacheStatement: visitSubExpression,
17492	  Decorator: visitSubExpression,
17493
17494	  BlockStatement: visitBlock,
17495	  DecoratorBlock: visitBlock,
17496
17497	  PartialStatement: visitPartial,
17498	  PartialBlockStatement: function PartialBlockStatement(partial) {
17499	    visitPartial.call(this, partial);
17500
17501	    this.acceptKey(partial, 'program');
17502	  },
17503
17504	  ContentStatement: function ContentStatement() /* content */{},
17505	  CommentStatement: function CommentStatement() /* comment */{},
17506
17507	  SubExpression: visitSubExpression,
17508
17509	  PathExpression: function PathExpression() /* path */{},
17510
17511	  StringLiteral: function StringLiteral() /* string */{},
17512	  NumberLiteral: function NumberLiteral() /* number */{},
17513	  BooleanLiteral: function BooleanLiteral() /* bool */{},
17514	  UndefinedLiteral: function UndefinedLiteral() /* literal */{},
17515	  NullLiteral: function NullLiteral() /* literal */{},
17516
17517	  Hash: function Hash(hash) {
17518	    this.acceptArray(hash.pairs);
17519	  },
17520	  HashPair: function HashPair(pair) {
17521	    this.acceptRequired(pair, 'value');
17522	  }
17523	};
17524
17525	function visitSubExpression(mustache) {
17526	  this.acceptRequired(mustache, 'path');
17527	  this.acceptArray(mustache.params);
17528	  this.acceptKey(mustache, 'hash');
17529	}
17530	function visitBlock(block) {
17531	  visitSubExpression.call(this, block);
17532
17533	  this.acceptKey(block, 'program');
17534	  this.acceptKey(block, 'inverse');
17535	}
17536	function visitPartial(partial) {
17537	  this.acceptRequired(partial, 'name');
17538	  this.acceptArray(partial.params);
17539	  this.acceptKey(partial, 'hash');
17540	}
17541
17542	exports['default'] = Visitor;
17543	module.exports = exports['default'];
17544
17545/***/ }),
17546/* 40 */
17547/***/ (function(module, exports, __webpack_require__) {
17548
17549	'use strict';
17550
17551	var _interopRequireDefault = __webpack_require__(1)['default'];
17552
17553	exports.__esModule = true;
17554	exports.SourceLocation = SourceLocation;
17555	exports.id = id;
17556	exports.stripFlags = stripFlags;
17557	exports.stripComment = stripComment;
17558	exports.preparePath = preparePath;
17559	exports.prepareMustache = prepareMustache;
17560	exports.prepareRawBlock = prepareRawBlock;
17561	exports.prepareBlock = prepareBlock;
17562	exports.prepareProgram = prepareProgram;
17563	exports.preparePartialBlock = preparePartialBlock;
17564
17565	var _exception = __webpack_require__(6);
17566
17567	var _exception2 = _interopRequireDefault(_exception);
17568
17569	function validateClose(open, close) {
17570	  close = close.path ? close.path.original : close;
17571
17572	  if (open.path.original !== close) {
17573	    var errorNode = { loc: open.path.loc };
17574
17575	    throw new _exception2['default'](open.path.original + " doesn't match " + close, errorNode);
17576	  }
17577	}
17578
17579	function SourceLocation(source, locInfo) {
17580	  this.source = source;
17581	  this.start = {
17582	    line: locInfo.first_line,
17583	    column: locInfo.first_column
17584	  };
17585	  this.end = {
17586	    line: locInfo.last_line,
17587	    column: locInfo.last_column
17588	  };
17589	}
17590
17591	function id(token) {
17592	  if (/^\[.*\]$/.test(token)) {
17593	    return token.substr(1, token.length - 2);
17594	  } else {
17595	    return token;
17596	  }
17597	}
17598
17599	function stripFlags(open, close) {
17600	  return {
17601	    open: open.charAt(2) === '~',
17602	    close: close.charAt(close.length - 3) === '~'
17603	  };
17604	}
17605
17606	function stripComment(comment) {
17607	  return comment.replace(/^\{\{~?\!-?-?/, '').replace(/-?-?~?\}\}$/, '');
17608	}
17609
17610	function preparePath(data, parts, loc) {
17611	  loc = this.locInfo(loc);
17612
17613	  var original = data ? '@' : '',
17614	      dig = [],
17615	      depth = 0,
17616	      depthString = '';
17617
17618	  for (var i = 0, l = parts.length; i < l; i++) {
17619	    var part = parts[i].part,
17620
17621	    // If we have [] syntax then we do not treat path references as operators,
17622	    // i.e. foo.[this] resolves to approximately context.foo['this']
17623	    isLiteral = parts[i].original !== part;
17624	    original += (parts[i].separator || '') + part;
17625
17626	    if (!isLiteral && (part === '..' || part === '.' || part === 'this')) {
17627	      if (dig.length > 0) {
17628	        throw new _exception2['default']('Invalid path: ' + original, { loc: loc });
17629	      } else if (part === '..') {
17630	        depth++;
17631	        depthString += '../'
vendor: 3,286 bytes, lines 17631-17779
17631;
17632	      }
17633	    } else {
17634	      dig.push(part);
17635	    }
17636	  }
17637
17638	  return {
17639	    type: 'PathExpression',
17640	    data: data,
17641	    depth: depth,
17642	    parts: dig,
17643	    original: original,
17644	    loc: loc
17645	  };
17646	}
17647
17648	function prepareMustache(path, params, hash, open, strip, locInfo) {
17649	  // Must use charAt to support IE pre-10
17650	  var escapeFlag = open.charAt(3) || open.charAt(2),
17651	      escaped = escapeFlag !== '{' && escapeFlag !== '&';
17652
17653	  var decorator = /\*/.test(open);
17654	  return {
17655	    type: decorator ? 'Decorator' : 'MustacheStatement',
17656	    path: path,
17657	    params: params,
17658	    hash: hash,
17659	    escaped: escaped,
17660	    strip: strip,
17661	    loc: this.locInfo(locInfo)
17662	  };
17663	}
17664
17665	function prepareRawBlock(openRawBlock, contents, close, locInfo) {
17666	  validateClose(openRawBlock, close);
17667
17668	  locInfo = this.locInfo(locInfo);
17669	  var program = {
17670	    type: 'Program',
17671	    body: contents,
17672	    strip: {},
17673	    loc: locInfo
17674	  };
17675
17676	  return {
17677	    type: 'BlockStatement',
17678	    path: openRawBlock.path,
17679	    params: openRawBlock.params,
17680	    hash: openRawBlock.hash,
17681	    program: program,
17682	    openStrip: {},
17683	    inverseStrip: {},
17684	    closeStrip: {},
17685	    loc: locInfo
17686	  };
17687	}
17688
17689	function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) {
17690	  if (close && close.path) {
17691	    validateClose(openBlock, close);
17692	  }
17693
17694	  var decorator = /\*/.test(openBlock.open);
17695
17696	  program.blockParams = openBlock.blockParams;
17697
17698	  var inverse = undefined,
17699	      inverseStrip = undefined;
17700
17701	  if (inverseAndProgram) {
17702	    if (decorator) {
17703	      throw new _exception2['default']('Unexpected inverse block on decorator', inverseAndProgram);
17704	    }
17705
17706	    if (inverseAndProgram.chain) {
17707	      inverseAndProgram.program.body[0].closeStrip = close.strip;
17708	    }
17709
17710	    inverseStrip = inverseAndProgram.strip;
17711	    inverse = inverseAndProgram.program;
17712	  }
17713
17714	  if (inverted) {
17715	    inverted = inverse;
17716	    inverse = program;
17717	    program = inverted;
17718	  }
17719
17720	  return {
17721	    type: decorator ? 'DecoratorBlock' : 'BlockStatement',
17722	    path: openBlock.path,
17723	    params: openBlock.params,
17724	    hash: openBlock.hash,
17725	    program: program,
17726	    inverse: inverse,
17727	    openStrip: openBlock.strip,
17728	    inverseStrip: inverseStrip,
17729	    closeStrip: close && close.strip,
17730	    loc: this.locInfo(locInfo)
17731	  };
17732	}
17733
17734	function prepareProgram(statements, loc) {
17735	  if (!loc && statements.length) {
17736	    var firstLoc = statements[0].loc,
17737	        lastLoc = statements[statements.length - 1].loc;
17738
17739	    /* istanbul ignore else */
17740	    if (firstLoc && lastLoc) {
17741	      loc = {
17742	        source: firstLoc.source,
17743	        start: {
17744	          line: firstLoc.start.line,
17745	          column: firstLoc.start.column
17746	        },
17747	        end: {
17748	          line: lastLoc.end.line,
17749	          column: lastLoc.end.column
17750	        }
17751	      };
17752	    }
17753	  }
17754
17755	  return {
17756	    type: 'Program',
17757	    body: statements,
17758	    strip: {},
17759	    loc: loc
17760	  };
17761	}
17762
17763	function preparePartialBlock(open, program, close, locInfo) {
17764	  validateClose(open, close);
17765
17766	  return {
17767	    type: 'PartialBlockStatement',
17768	    name: open.path,
17769	    params: open.params,
17770	    hash: open.hash,
17771	    program: program,
17772	    openStrip: open.strip,
17773	    closeStrip: close && close.strip,
17774	    loc: this.locInfo(locInfo)
17775	  };
17776	}
17777
17778/***/ }),
17779/* 4
vendor: 2,542 bytes, lines 17779-17872
177791 */
17780/***/ (function(module, exports, __webpack_require__) {
17781
17782	/* eslint-disable new-cap */
17783
17784	'use strict';
17785
17786	var _interopRequireDefault = __webpack_require__(1)['default'];
17787
17788	exports.__esModule = true;
17789	exports.Compiler = Compiler;
17790	exports.precompile = precompile;
17791	exports.compile = compile;
17792
17793	var _exception = __webpack_require__(6);
17794
17795	var _exception2 = _interopRequireDefault(_exception);
17796
17797	var _utils = __webpack_require__(5);
17798
17799	var _ast = __webpack_require__(35);
17800
17801	var _ast2 = _interopRequireDefault(_ast);
17802
17803	var slice = [].slice;
17804
17805	function Compiler() {}
17806
17807	// the foundHelper register will disambiguate helper lookup from finding a
17808	// function in a context. This is necessary for mustache compatibility, which
17809	// requires that context functions in blocks are evaluated by blockHelperMissing,
17810	// and then proceed as if the resulting value was provided to blockHelperMissing.
17811
17812	Compiler.prototype = {
17813	  compiler: Compiler,
17814
17815	  equals: function equals(other) {
17816	    var len = this.opcodes.length;
17817	    if (other.opcodes.length !== len) {
17818	      return false;
17819	    }
17820
17821	    for (var i = 0; i < len; i++) {
17822	      var opcode = this.opcodes[i],
17823	          otherOpcode = other.opcodes[i];
17824	      if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) {
17825	        return false;
17826	      }
17827	    }
17828
17829	    // We know that length is the same between the two arrays because they are directly tied
17830	    // to the opcode behavior above.
17831	    len = this.children.length;
17832	    for (var i = 0; i < len; i++) {
17833	      if (!this.children[i].equals(other.children[i])) {
17834	        return false;
17835	      }
17836	    }
17837
17838	    return true;
17839	  },
17840
17841	  guid: 0,
17842
17843	  compile: function compile(program, options) {
17844	    this.sourceNode = [];
17845	    this.opcodes = [];
17846	    this.children = [];
17847	    this.options = options;
17848	    this.stringParams = options.stringParams;
17849	    this.trackIds = options.trackIds;
17850
17851	    options.blockParams = options.blockParams || [];
17852
17853	    // These changes will propagate to the other compiler components
17854	    var knownHelpers = options.knownHelpers;
17855	    options.knownHelpers = {
17856	      'helperMissing': true,
17857	      'blockHelperMissing': true,
17858	      'each': true,
17859	      'if': true,
17860	      'unless': true,
17861	      'with': true,
17862	      'log': true,
17863	      'lookup': true
17864	    };
17865	    if (knownHelpers) {
17866	      for (var _name in knownHelpers) {
17867	        /* istanbul ignore else */
17868	        if (_name in knownHelpers) {
17869	          this.options.knownHelpers[_name] = knownHelpers[_name];
17870	        }
17871	      }
17872	    }
vendor: 8,795 bytes, lines 17872-18166
17872
17873
17874	    return this.accept(program);
17875	  },
17876
17877	  compileProgram: function compileProgram(program) {
17878	    var childCompiler = new this.compiler(),
17879	        // eslint-disable-line new-cap
17880	    result = childCompiler.compile(program, this.options),
17881	        guid = this.guid++;
17882
17883	    this.usePartial = this.usePartial || result.usePartial;
17884
17885	    this.children[guid] = result;
17886	    this.useDepths = this.useDepths || result.useDepths;
17887
17888	    return guid;
17889	  },
17890
17891	  accept: function accept(node) {
17892	    /* istanbul ignore next: Sanity code */
17893	    if (!this[node.type]) {
17894	      throw new _exception2['default']('Unknown type: ' + node.type, node);
17895	    }
17896
17897	    this.sourceNode.unshift(node);
17898	    var ret = this[node.type](node);
17899	    this.sourceNode.shift();
17900	    return ret;
17901	  },
17902
17903	  Program: function Program(program) {
17904	    this.options.blockParams.unshift(program.blockParams);
17905
17906	    var body = program.body,
17907	        bodyLength = body.length;
17908	    for (var i = 0; i < bodyLength; i++) {
17909	      this.accept(body[i]);
17910	    }
17911
17912	    this.options.blockParams.shift();
17913
17914	    this.isSimple = bodyLength === 1;
17915	    this.blockParams = program.blockParams ? program.blockParams.length : 0;
17916
17917	    return this;
17918	  },
17919
17920	  BlockStatement: function BlockStatement(block) {
17921	    transformLiteralToPath(block);
17922
17923	    var program = block.program,
17924	        inverse = block.inverse;
17925
17926	    program = program && this.compileProgram(program);
17927	    inverse = inverse && this.compileProgram(inverse);
17928
17929	    var type = this.classifySexpr(block);
17930
17931	    if (type === 'helper') {
17932	      this.helperSexpr(block, program, inverse);
17933	    } else if (type === 'simple') {
17934	      this.simpleSexpr(block);
17935
17936	      // now that the simple mustache is resolved, we need to
17937	      // evaluate it by executing `blockHelperMissing`
17938	      this.opcode('pushProgram', program);
17939	      this.opcode('pushProgram', inverse);
17940	      this.opcode('emptyHash');
17941	      this.opcode('blockValue', block.path.original);
17942	    } else {
17943	      this.ambiguousSexpr(block, program, inverse);
17944
17945	      // now that the simple mustache is resolved, we need to
17946	      // evaluate it by executing `blockHelperMissing`
17947	      this.opcode('pushProgram', program);
17948	      this.opcode('pushProgram', inverse);
17949	      this.opcode('emptyHash');
17950	      this.opcode('ambiguousBlockValue');
17951	    }
17952
17953	    this.opcode('append');
17954	  },
17955
17956	  DecoratorBlock: function DecoratorBlock(decorator) {
17957	    var program = decorator.program && this.compileProgram(decorator.program);
17958	    var params = this.setupFullMustacheParams(decorator, program, undefined),
17959	        path = decorator.path;
17960
17961	    this.useDecorators = true;
17962	    this.opcode('registerDecorator', params.length, path.original);
17963	  },
17964
17965	  PartialStatement: function PartialStatement(partial) {
17966	    this.usePartial = true;
17967
17968	    var program = partial.program;
17969	    if (program) {
17970	      program = this.compileProgram(partial.program);
17971	    }
17972
17973	    var params = partial.params;
17974	    if (params.length > 1) {
17975	      throw new _exception2['default']('Unsupported number of partial arguments: ' + params.length, partial);
17976	    } else if (!params.length) {
17977	      if (this.options.explicitPartialContext) {
17978	        this.opcode('pushLiteral', 'undefined');
17979	      } else {
17980	        params.push({ type: 'PathExpression', parts: [], depth: 0 });
17981	      }
17982	    }
17983
17984	    var partialName = partial.name.original,
17985	        isDynamic = partial.name.type === 'SubExpression';
17986	    if (isDynamic) {
17987	      this.accept(partial.name);
17988	    }
17989
17990	    this.setupFullMustacheParams(partial, program, undefined, true);
17991
17992	    var indent = partial.indent || '';
17993	    if (this.options.preventIndent && indent) {
17994	      this.opcode('appendContent', indent);
17995	      indent = '';
17996	    }
17997
17998	    this.opcode('invokePartial', isDynamic, partialName, indent);
17999	    this.opcode('append');
18000	  },
18001	  PartialBlockStatement: function PartialBlockStatement(partialBlock) {
18002	    this.PartialStatement(partialBlock);
18003	  },
18004
18005	  MustacheStatement: function MustacheStatement(mustache) {
18006	    this.SubExpression(mustache);
18007
18008	    if (mustache.escaped && !this.options.noEscape) {
18009	      this.opcode('appendEscaped');
18010	    } else {
18011	      this.opcode('append');
18012	    }
18013	  },
18014	  Decorator: function Decorator(decorator) {
18015	    this.DecoratorBlock(decorator);
18016	  },
18017
18018	  ContentStatement: function ContentStatement(content) {
18019	    if (content.value) {
18020	      this.opcode('appendContent', content.value);
18021	    }
18022	  },
18023
18024	  CommentStatement: function CommentStatement() {},
18025
18026	  SubExpression: function SubExpression(sexpr) {
18027	    transformLiteralToPath(sexpr);
18028	    var type = this.classifySexpr(sexpr);
18029
18030	    if (type === 'simple') {
18031	      this.simpleSexpr(sexpr);
18032	    } else if (type === 'helper') {
18033	      this.helperSexpr(sexpr);
18034	    } else {
18035	      this.ambiguousSexpr(sexpr);
18036	    }
18037	  },
18038	  ambiguousSexpr: function ambiguousSexpr(sexpr, program, inverse) {
18039	    var path = sexpr.path,
18040	        name = path.parts[0],
18041	        isBlock = program != null || inverse != null;
18042
18043	    this.opcode('getContext', path.depth);
18044
18045	    this.opcode('pushProgram', program);
18046	    this.opcode('pushProgram', inverse);
18047
18048	    path.strict = true;
18049	    this.accept(path);
18050
18051	    this.opcode('invokeAmbiguous', name, isBlock);
18052	  },
18053
18054	  simpleSexpr: function simpleSexpr(sexpr) {
18055	    var path = sexpr.path;
18056	    path.strict = true;
18057	    this.accept(path);
18058	    this.opcode('resolvePossibleLambda');
18059	  },
18060
18061	  helperSexpr: function helperSexpr(sexpr, program, inverse) {
18062	    var params = this.setupFullMustacheParams(sexpr, program, inverse),
18063	        path = sexpr.path,
18064	        name = path.parts[0];
18065
18066	    if (this.options.knownHelpers[name]) {
18067	      this.opcode('invokeKnownHelper', params.length, name);
18068	    } else if (this.options.knownHelpersOnly) {
18069	      throw new _exception2['default']('You specified knownHelpersOnly, but used the unknown helper ' + name, sexpr);
18070	    } else {
18071	      path.strict = true;
18072	      path.falsy = true;
18073
18074	      this.accept(path);
18075	      this.opcode('invokeHelper', params.length, path.original, _ast2['default'].helpers.simpleId(path));
18076	    }
18077	  },
18078
18079	  PathExpression: function PathExpression(path) {
18080	    this.addDepth(path.depth);
18081	    this.opcode('getContext', path.depth);
18082
18083	    var name = path.parts[0],
18084	        scoped = _ast2['default'].helpers.scopedId(path),
18085	        blockParamId = !path.depth && !scoped && this.blockParamIndex(name);
18086
18087	    if (blockParamId) {
18088	      this.opcode('lookupBlockParam', blockParamId, path.parts);
18089	    } else if (!name) {
18090	      // Context reference, i.e. `{{foo .}}` or `{{foo ..}}`
18091	      this.opcode('pushContext');
18092	    } else if (path.data) {
18093	      this.options.data = true;
18094	      this.opcode('lookupData', path.depth, path.parts, path.strict);
18095	    } else {
18096	      this.opcode('lookupOnContext', path.parts, path.falsy, path.strict, scoped);
18097	    }
18098	  },
18099
18100	  StringLiteral: function StringLiteral(string) {
18101	    this.opcode('pushString', string.value);
18102	  },
18103
18104	  NumberLiteral: function NumberLiteral(number) {
18105	    this.opcode('pushLiteral', number.value);
18106	  },
18107
18108	  BooleanLiteral: function BooleanLiteral(bool) {
18109	    this.opcode('pushLiteral', bool.value);
18110	  },
18111
18112	  UndefinedLiteral: function UndefinedLiteral() {
18113	    this.opcode('pushLiteral', 'undefined');
18114	  },
18115
18116	  NullLiteral: function NullLiteral() {
18117	    this.opcode('pushLiteral', 'null');
18118	  },
18119
18120	  Hash: function Hash(hash) {
18121	    var pairs = hash.pairs,
18122	        i = 0,
18123	        l = pairs.length;
18124
18125	    this.opcode('pushHash');
18126
18127	    for (; i < l; i++) {
18128	      this.pushParam(pairs[i].value);
18129	    }
18130	    while (i--) {
18131	      this.opcode('assignToHash', pairs[i].key);
18132	    }
18133	    this.opcode('popHash');
18134	  },
18135
18136	  // HELPERS
18137	  opcode: function opcode(name) {
18138	    this.opcodes.push({ opcode: name, args: slice.call(arguments, 1), loc: this.sourceNode[0].loc });
18139	  },
18140
18141	  addDepth: function addDepth(depth) {
18142	    if (!depth) {
18143	      return;
18144	    }
18145
18146	    this.useDepths = true;
18147	  },
18148
18149	  classifySexpr: function classifySexpr(sexpr) {
18150	    var isSimple = _ast2['default'].helpers.simpleId(sexpr.path);
18151
18152	    var isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]);
18153
18154	    // a mustache is an eligible helper if:
18155	    // * its id is simple (a single part, not `this` or `..`)
18156	    var isHelper = !isBlockParam && _ast2['default'].helpers.helperExpression(sexpr);
18157
18158	    // if a mustache is an eligible helper but not a definite
18159	    // helper, it is ambiguous, and will be resolved in a later
18160	    // pass or at runtime.
18161	    var isEligible = !isBlockParam && (isHelper || isSimple);
18162
18163	    // if ambiguous, we can possibly resolve the ambiguity now
18164	    // An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc.
18165	    if (isEligible && !isHelper) {
18166	      var _name
vendor: 4,602 bytes, lines 18166-18323
181662 = sexpr.path.parts[0],
18167	          options = this.options;
18168
18169	      if (options.knownHelpers[_name2]) {
18170	        isHelper = true;
18171	      } else if (options.knownHelpersOnly) {
18172	        isEligible = false;
18173	      }
18174	    }
18175
18176	    if (isHelper) {
18177	      return 'helper';
18178	    } else if (isEligible) {
18179	      return 'ambiguous';
18180	    } else {
18181	      return 'simple';
18182	    }
18183	  },
18184
18185	  pushParams: function pushParams(params) {
18186	    for (var i = 0, l = params.length; i < l; i++) {
18187	      this.pushParam(params[i]);
18188	    }
18189	  },
18190
18191	  pushParam: function pushParam(val) {
18192	    var value = val.value != null ? val.value : val.original || '';
18193
18194	    if (this.stringParams) {
18195	      if (value.replace) {
18196	        value = value.replace(/^(\.?\.\/)*/g, '').replace(/\//g, '.');
18197	      }
18198
18199	      if (val.depth) {
18200	        this.addDepth(val.depth);
18201	      }
18202	      this.opcode('getContext', val.depth || 0);
18203	      this.opcode('pushStringParam', value, val.type);
18204
18205	      if (val.type === 'SubExpression') {
18206	        // SubExpressions get evaluated and passed in
18207	        // in string params mode.
18208	        this.accept(val);
18209	      }
18210	    } else {
18211	      if (this.trackIds) {
18212	        var blockParamIndex = undefined;
18213	        if (val.parts && !_ast2['default'].helpers.scopedId(val) && !val.depth) {
18214	          blockParamIndex = this.blockParamIndex(val.parts[0]);
18215	        }
18216	        if (blockParamIndex) {
18217	          var blockParamChild = val.parts.slice(1).join('.');
18218	          this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild);
18219	        } else {
18220	          value = val.original || value;
18221	          if (value.replace) {
18222	            value = value.replace(/^this(?:\.|$)/, '').replace(/^\.\//, '').replace(/^\.$/, '');
18223	          }
18224
18225	          this.opcode('pushId', val.type, value);
18226	        }
18227	      }
18228	      this.accept(val);
18229	    }
18230	  },
18231
18232	  setupFullMustacheParams: function setupFullMustacheParams(sexpr, program, inverse, omitEmpty) {
18233	    var params = sexpr.params;
18234	    this.pushParams(params);
18235
18236	    this.opcode('pushProgram', program);
18237	    this.opcode('pushProgram', inverse);
18238
18239	    if (sexpr.hash) {
18240	      this.accept(sexpr.hash);
18241	    } else {
18242	      this.opcode('emptyHash', omitEmpty);
18243	    }
18244
18245	    return params;
18246	  },
18247
18248	  blockParamIndex: function blockParamIndex(name) {
18249	    for (var depth = 0, len = this.options.blockParams.length; depth < len; depth++) {
18250	      var blockParams = this.options.blockParams[depth],
18251	          param = blockParams && _utils.indexOf(blockParams, name);
18252	      if (blockParams && param >= 0) {
18253	        return [depth, param];
18254	      }
18255	    }
18256	  }
18257	};
18258
18259	function precompile(input, options, env) {
18260	  if (input == null || typeof input !== 'string' && input.type !== 'Program') {
18261	    throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.precompile. You passed ' + input);
18262	  }
18263
18264	  options = options || {};
18265	  if (!('data' in options)) {
18266	    options.data = true;
18267	  }
18268	  if (options.compat) {
18269	    options.useDepths = true;
18270	  }
18271
18272	  var ast = env.parse(input, options),
18273	      environment = new env.Compiler().compile(ast, options);
18274	  return new env.JavaScriptCompiler().compile(environment, options);
18275	}
18276
18277	function compile(input, options, env) {
18278	  if (options === undefined) options = {};
18279
18280	  if (input == null || typeof input !== 'string' && input.type !== 'Program') {
18281	    throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.compile. You passed ' + input);
18282	  }
18283
18284	  options = _utils.extend({}, options);
18285	  if (!('data' in options)) {
18286	    options.data = true;
18287	  }
18288	  if (options.compat) {
18289	    options.useDepths = true;
18290	  }
18291
18292	  var compiled = undefined;
18293
18294	  function compileInput() {
18295	    var ast = env.parse(input, options),
18296	        environment = new env.Compiler().compile(ast, options),
18297	        templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true);
18298	    return env.template(templateSpec);
18299	  }
18300
18301	  // Template is only compiled on first use and cached after that point.
18302	  function ret(context, execOptions) {
18303	    if (!compiled) {
18304	      compiled = compileInput();
18305	    }
18306	    return compiled.call(this, context, execOptions);
18307	  }
18308	  ret._setup = function (setupOptions) {
18309	    if (!compiled) {
18310	      compiled = compileInput();
18311	    }
18312	    return compiled._setup(setupOptions);
18313	  };
18314	  ret._child = function (i, data, blockParams, depths) {
18315	    if (!compiled) {
18316	      compiled = compileInput();
18317	    }
18318	    return compiled._child(i, data, blockParams, depths);
18319	  };
18320	  return ret;
18321	}
18322
18323	function argEquals(a, b) {
vendor: 8,012 bytes, lines 18324-18590
18324	  if (a === b) {
18325	    return true;
18326	  }
18327
18328	  if (_utils.isArray(a) && _utils.isArray(b) && a.length === b.length) {
18329	    for (var i = 0; i < a.length; i++) {
18330	      if (!argEquals(a[i], b[i])) {
18331	        return false;
18332	      }
18333	    }
18334	    return true;
18335	  }
18336	}
18337
18338	function transformLiteralToPath(sexpr) {
18339	  if (!sexpr.path.parts) {
18340	    var literal = sexpr.path;
18341	    // Casting to string here to make false and 0 literal values play nicely with the rest
18342	    // of the system.
18343	    sexpr.path = {
18344	      type: 'PathExpression',
18345	      data: false,
18346	      depth: 0,
18347	      parts: [literal.original + ''],
18348	      original: literal.original + '',
18349	      loc: literal.loc
18350	    };
18351	  }
18352	}
18353
18354/***/ }),
18355/* 42 */
18356/***/ (function(module, exports, __webpack_require__) {
18357
18358	'use strict';
18359
18360	var _interopRequireDefault = __webpack_require__(1)['default'];
18361
18362	exports.__esModule = true;
18363
18364	var _base = __webpack_require__(4);
18365
18366	var _exception = __webpack_require__(6);
18367
18368	var _exception2 = _interopRequireDefault(_exception);
18369
18370	var _utils = __webpack_require__(5);
18371
18372	var _codeGen = __webpack_require__(43);
18373
18374	var _codeGen2 = _interopRequireDefault(_codeGen);
18375
18376	function Literal(value) {
18377	  this.value = value;
18378	}
18379
18380	function JavaScriptCompiler() {}
18381
18382	JavaScriptCompiler.prototype = {
18383	  // PUBLIC API: You can override these methods in a subclass to provide
18384	  // alternative compiled forms for name lookup and buffering semantics
18385	  nameLookup: function nameLookup(parent, name /* , type*/) {
18386	    if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
18387	      return [parent, '.', name];
18388	    } else {
18389	      return [parent, '[', JSON.stringify(name), ']'];
18390	    }
18391	  },
18392	  depthedLookup: function depthedLookup(name) {
18393	    return [this.aliasable('container.lookup'), '(depths, "', name, '")'];
18394	  },
18395
18396	  compilerInfo: function compilerInfo() {
18397	    var revision = _base.COMPILER_REVISION,
18398	        versions = _base.REVISION_CHANGES[revision];
18399	    return [revision, versions];
18400	  },
18401
18402	  appendToBuffer: function appendToBuffer(source, location, explicit) {
18403	    // Force a source as this simplifies the merge logic.
18404	    if (!_utils.isArray(source)) {
18405	      source = [source];
18406	    }
18407	    source = this.source.wrap(source, location);
18408
18409	    if (this.environment.isSimple) {
18410	      return ['return ', source, ';'];
18411	    } else if (explicit) {
18412	      // This is a case where the buffer operation occurs as a child of another
18413	      // construct, generally braces. We have to explicitly output these buffer
18414	      // operations to ensure that the emitted code goes in the correct location.
18415	      return ['buffer += ', source, ';'];
18416	    } else {
18417	      source.appendToBuffer = true;
18418	      return source;
18419	    }
18420	  },
18421
18422	  initializeBuffer: function initializeBuffer() {
18423	    return this.quotedString('');
18424	  },
18425	  // END PUBLIC API
18426
18427	  compile: function compile(environment, options, context, asObject) {
18428	    this.environment = environment;
18429	    this.options = options;
18430	    this.stringParams = this.options.stringParams;
18431	    this.trackIds = this.options.trackIds;
18432	    this.precompile = !asObject;
18433
18434	    this.name = this.environment.name;
18435	    this.isChild = !!context;
18436	    this.context = context || {
18437	      decorators: [],
18438	      programs: [],
18439	      environments: []
18440	    };
18441
18442	    this.preamble();
18443
18444	    this.stackSlot = 0;
18445	    this.stackVars = [];
18446	    this.aliases = {};
18447	    this.registers = { list: [] };
18448	    this.hashes = [];
18449	    this.compileStack = [];
18450	    this.inlineStack = [];
18451	    this.blockParams = [];
18452
18453	    this.compileChildren(environment, options);
18454
18455	    this.useDepths = this.useDepths || environment.useDepths || environment.useDecorators || this.options.compat;
18456	    this.useBlockParams = this.useBlockParams || environment.useBlockParams;
18457
18458	    var opcodes = environment.opcodes,
18459	        opcode = undefined,
18460	        firstLoc = undefined,
18461	        i = undefined,
18462	        l = undefined;
18463
18464	    for (i = 0, l = opcodes.length; i < l; i++) {
18465	      opcode = opcodes[i];
18466
18467	      this.source.currentLocation = opcode.loc;
18468	      firstLoc = firstLoc || opcode.loc;
18469	      this[opcode.opcode].apply(this, opcode.args);
18470	    }
18471
18472	    // Flush any trailing content that might be pending.
18473	    this.source.currentLocation = firstLoc;
18474	    this.pushSource('');
18475
18476	    /* istanbul ignore next */
18477	    if (this.stackSlot || this.inlineStack.length || this.compileStack.length) {
18478	      throw new _exception2['default']('Compile completed with content left on stack');
18479	    }
18480
18481	    if (!this.decorators.isEmpty()) {
18482	      this.useDecorators = true;
18483
18484	      this.decorators.prepend('var decorators = container.decorators;\n');
18485	      this.decorators.push('return fn;');
18486
18487	      if (asObject) {
18488	        this.decorators = Function.apply(this, ['fn', 'props', 'container', 'depth0', 'data', 'blockParams', 'depths', this.decorators.merge()]);
18489	      } else {
18490	        this.decorators.prepend('function(fn, props, container, depth0, data, blockParams, depths) {\n');
18491	        this.decorators.push('}\n');
18492	        this.decorators = this.decorators.merge();
18493	      }
18494	    } else {
18495	      this.decorators = undefined;
18496	    }
18497
18498	    var fn = this.createFunctionContext(asObject);
18499	    if (!this.isChild) {
18500	      var ret = {
18501	        compiler: this.compilerInfo(),
18502	        main: fn
18503	      };
18504
18505	      if (this.decorators) {
18506	        ret.main_d = this.decorators; // eslint-disable-line camelcase
18507	        ret.useDecorators = true;
18508	      }
18509
18510	      var _context = this.context;
18511	      var programs = _context.programs;
18512	      var decorators = _context.decorators;
18513
18514	      for (i = 0, l = programs.length; i < l; i++) {
18515	        if (programs[i]) {
18516	          ret[i] = programs[i];
18517	          if (decorators[i]) {
18518	            ret[i + '_d'] = decorators[i];
18519	            ret.useDecorators = true;
18520	          }
18521	        }
18522	      }
18523
18524	      if (this.environment.usePartial) {
18525	        ret.usePartial = true;
18526	      }
18527	      if (this.options.data) {
18528	        ret.useData = true;
18529	      }
18530	      if (this.useDepths) {
18531	        ret.useDepths = true;
18532	      }
18533	      if (this.useBlockParams) {
18534	        ret.useBlockParams = true;
18535	      }
18536	      if (this.options.compat) {
18537	        ret.compat = true;
18538	      }
18539
18540	      if (!asObject) {
18541	        ret.compiler = JSON.stringify(ret.compiler);
18542
18543	        this.source.currentLocation = { start: { line: 1, column: 0 } };
18544	        ret = this.objectLiteral(ret);
18545
18546	        if (options.srcName) {
18547	          ret = ret.toStringWithSourceMap({ file: options.destName });
18548	          ret.map = ret.map && ret.map.toString();
18549	        } else {
18550	          ret = ret.toString();
18551	        }
18552	      } else {
18553	        ret.compilerOptions = this.options;
18554	      }
18555
18556	      return ret;
18557	    } else {
18558	      return fn;
18559	    }
18560	  },
18561
18562	  preamble: function preamble() {
18563	    // track the last context pushed into place to allow skipping the
18564	    // getContext opcode when it would be a noop
18565	    this.lastContext = 0;
18566	    this.source = new _codeGen2['default'](this.options.srcName);
18567	    this.decorators = new _codeGen2['default'](this.options.srcName);
18568	  },
18569
18570	  createFunctionContext: function createFunctionContext(asObject) {
18571	    var varDeclarations = '';
18572
18573	    var locals = this.stackVars.concat(this.registers.list);
18574	    if (locals.length > 0) {
18575	      varDeclarations += ', ' + locals.join(', ');
18576	    }
18577
18578	    // Generate minimizer alias mappings
18579	    //
18580	    // When using true SourceNodes, this will update all references to the given alias
18581	    // as the source nodes are reused in situ. For the non-source node compilation mode,
18582	    // aliases will not be used, but this case is already being run on the client and
18583	    // we aren't concern about minimizing the template size.
18584	    var aliasCount = 0;
18585	    for (var alias in this.aliases) {
18586	      // eslint-disable-line guard-for-in
18587	      var node = this.aliases[alias];
18588
18589	      if (this.aliases.hasOwnProperty(alias) && node.children && node.referenceCount > 1) {
18590	        varDeclarations += ', alias' + ++aliasCount + '=' + alias;
vendor: 4,556 bytes, lines 18591-18740
18591	        node.children[0] = 'alias' + aliasCount;
18592	      }
18593	    }
18594
18595	    var params = ['container', 'depth0', 'helpers', 'partials', 'data'];
18596
18597	    if (this.useBlockParams || this.useDepths) {
18598	      params.push('blockParams');
18599	    }
18600	    if (this.useDepths) {
18601	      params.push('depths');
18602	    }
18603
18604	    // Perform a second pass over the output to merge content when possible
18605	    var source = this.mergeSource(varDeclarations);
18606
18607	    if (asObject) {
18608	      params.push(source);
18609
18610	      return Function.apply(this, params);
18611	    } else {
18612	      return this.source.wrap(['function(', params.join(','), ') {\n  ', source, '}']);
18613	    }
18614	  },
18615	  mergeSource: function mergeSource(varDeclarations) {
18616	    var isSimple = this.environment.isSimple,
18617	        appendOnly = !this.forceBuffer,
18618	        appendFirst = undefined,
18619	        sourceSeen = undefined,
18620	        bufferStart = undefined,
18621	        bufferEnd = undefined;
18622	    this.source.each(function (line) {
18623	      if (line.appendToBuffer) {
18624	        if (bufferStart) {
18625	          line.prepend('  + ');
18626	        } else {
18627	          bufferStart = line;
18628	        }
18629	        bufferEnd = line;
18630	      } else {
18631	        if (bufferStart) {
18632	          if (!sourceSeen) {
18633	            appendFirst = true;
18634	          } else {
18635	            bufferStart.prepend('buffer += ');
18636	          }
18637	          bufferEnd.add(';');
18638	          bufferStart = bufferEnd = undefined;
18639	        }
18640
18641	        sourceSeen = true;
18642	        if (!isSimple) {
18643	          appendOnly = false;
18644	        }
18645	      }
18646	    });
18647
18648	    if (appendOnly) {
18649	      if (bufferStart) {
18650	        bufferStart.prepend('return ');
18651	        bufferEnd.add(';');
18652	      } else if (!sourceSeen) {
18653	        this.source.push('return "";');
18654	      }
18655	    } else {
18656	      varDeclarations += ', buffer = ' + (appendFirst ? '' : this.initializeBuffer());
18657
18658	      if (bufferStart) {
18659	        bufferStart.prepend('return buffer + ');
18660	        bufferEnd.add(';');
18661	      } else {
18662	        this.source.push('return buffer;');
18663	      }
18664	    }
18665
18666	    if (varDeclarations) {
18667	      this.source.prepend('var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n'));
18668	    }
18669
18670	    return this.source.merge();
18671	  },
18672
18673	  // [blockValue]
18674	  //
18675	  // On stack, before: hash, inverse, program, value
18676	  // On stack, after: return value of blockHelperMissing
18677	  //
18678	  // The purpose of this opcode is to take a block of the form
18679	  // `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and
18680	  // replace it on the stack with the result of properly
18681	  // invoking blockHelperMissing.
18682	  blockValue: function blockValue(name) {
18683	    var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
18684	        params = [this.contextName(0)];
18685	    this.setupHelperArgs(name, 0, params);
18686
18687	    var blockName = this.popStack();
18688	    params.splice(1, 0, blockName);
18689
18690	    this.push(this.source.functionCall(blockHelperMissing, 'call', params));
18691	  },
18692
18693	  // [ambiguousBlockValue]
18694	  //
18695	  // On stack, before: hash, inverse, program, value
18696	  // Compiler value, before: lastHelper=value of last found helper, if any
18697	  // On stack, after, if no lastHelper: same as [blockValue]
18698	  // On stack, after, if lastHelper: value
18699	  ambiguousBlockValue: function ambiguousBlockValue() {
18700	    // We're being a bit cheeky and reusing the options value from the prior exec
18701	    var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
18702	        params = [this.contextName(0)];
18703	    this.setupHelperArgs('', 0, params, true);
18704
18705	    this.flushInline();
18706
18707	    var current = this.topStack();
18708	    params.splice(1, 0, current);
18709
18710	    this.pushSource(['if (!', this.lastHelper, ') { ', current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params), '}']);
18711	  },
18712
18713	  // [appendContent]
18714	  //
18715	  // On stack, before: ...
18716	  // On stack, after: ...
18717	  //
18718	  // Appends the string value of `content` to the current buffer
18719	  appendContent: function appendContent(content) {
18720	    if (this.pendingContent) {
18721	      content = this.pendingContent + content;
18722	    } else {
18723	      this.pendingLocation = this.source.currentLocation;
18724	    }
18725
18726	    this.pendingContent = content;
18727	  },
18728
18729	  // [append]
18730	  //
18731	  // On stack, before: value, ...
18732	  // On stack, after: ...
18733	  //
18734	  // Coerces `value` to a String and appends it to the current buffer.
18735	  //
18736	  // If `value` is truthy, or 0, it is coerced into a string and appended
18737	  // Otherwise, the empty string is appended
18738	  append: function append() {
18739	    if (this.isInline()) {
18740	      this.replaceStack(function (current) {
vendor: 9,606 bytes, lines 18741-19041
18741	        return [' != null ? ', current, ' : ""'];
18742	      });
18743
18744	      this.pushSource(this.appendToBuffer(this.popStack()));
18745	    } else {
18746	      var local = this.popStack();
18747	      this.pushSource(['if (', local, ' != null) { ', this.appendToBuffer(local, undefined, true), ' }']);
18748	      if (this.environment.isSimple) {
18749	        this.pushSource(['else { ', this.appendToBuffer("''", undefined, true), ' }']);
18750	      }
18751	    }
18752	  },
18753
18754	  // [appendEscaped]
18755	  //
18756	  // On stack, before: value, ...
18757	  // On stack, after: ...
18758	  //
18759	  // Escape `value` and append it to the buffer
18760	  appendEscaped: function appendEscaped() {
18761	    this.pushSource(this.appendToBuffer([this.aliasable('container.escapeExpression'), '(', this.popStack(), ')']));
18762	  },
18763
18764	  // [getContext]
18765	  //
18766	  // On stack, before: ...
18767	  // On stack, after: ...
18768	  // Compiler value, after: lastContext=depth
18769	  //
18770	  // Set the value of the `lastContext` compiler value to the depth
18771	  getContext: function getContext(depth) {
18772	    this.lastContext = depth;
18773	  },
18774
18775	  // [pushContext]
18776	  //
18777	  // On stack, before: ...
18778	  // On stack, after: currentContext, ...
18779	  //
18780	  // Pushes the value of the current context onto the stack.
18781	  pushContext: function pushContext() {
18782	    this.pushStackLiteral(this.contextName(this.lastContext));
18783	  },
18784
18785	  // [lookupOnContext]
18786	  //
18787	  // On stack, before: ...
18788	  // On stack, after: currentContext[name], ...
18789	  //
18790	  // Looks up the value of `name` on the current context and pushes
18791	  // it onto the stack.
18792	  lookupOnContext: function lookupOnContext(parts, falsy, strict, scoped) {
18793	    var i = 0;
18794
18795	    if (!scoped && this.options.compat && !this.lastContext) {
18796	      // The depthed query is expected to handle the undefined logic for the root level that
18797	      // is implemented below, so we evaluate that directly in compat mode
18798	      this.push(this.depthedLookup(parts[i++]));
18799	    } else {
18800	      this.pushContext();
18801	    }
18802
18803	    this.resolvePath('context', parts, i, falsy, strict);
18804	  },
18805
18806	  // [lookupBlockParam]
18807	  //
18808	  // On stack, before: ...
18809	  // On stack, after: blockParam[name], ...
18810	  //
18811	  // Looks up the value of `parts` on the given block param and pushes
18812	  // it onto the stack.
18813	  lookupBlockParam: function lookupBlockParam(blockParamId, parts) {
18814	    this.useBlockParams = true;
18815
18816	    this.push(['blockParams[', blockParamId[0], '][', blockParamId[1], ']']);
18817	    this.resolvePath('context', parts, 1);
18818	  },
18819
18820	  // [lookupData]
18821	  //
18822	  // On stack, before: ...
18823	  // On stack, after: data, ...
18824	  //
18825	  // Push the data lookup operator
18826	  lookupData: function lookupData(depth, parts, strict) {
18827	    if (!depth) {
18828	      this.pushStackLiteral('data');
18829	    } else {
18830	      this.pushStackLiteral('container.data(data, ' + depth + ')');
18831	    }
18832
18833	    this.resolvePath('data', parts, 0, true, strict);
18834	  },
18835
18836	  resolvePath: function resolvePath(type, parts, i, falsy, strict) {
18837	    // istanbul ignore next
18838
18839	    var _this = this;
18840
18841	    if (this.options.strict || this.options.assumeObjects) {
18842	      this.push(strictLookup(this.options.strict && strict, this, parts, type));
18843	      return;
18844	    }
18845
18846	    var len = parts.length;
18847	    for (; i < len; i++) {
18848	      /* eslint-disable no-loop-func */
18849	      this.replaceStack(function (current) {
18850	        var lookup = _this.nameLookup(current, parts[i], type);
18851	        // We want to ensure that zero and false are handled properly if the context (falsy flag)
18852	        // needs to have the special handling for these values.
18853	        if (!falsy) {
18854	          return [' != null ? ', lookup, ' : ', current];
18855	        } else {
18856	          // Otherwise we can use generic falsy handling
18857	          return [' && ', lookup];
18858	        }
18859	      });
18860	      /* eslint-enable no-loop-func */
18861	    }
18862	  },
18863
18864	  // [resolvePossibleLambda]
18865	  //
18866	  // On stack, before: value, ...
18867	  // On stack, after: resolved value, ...
18868	  //
18869	  // If the `value` is a lambda, replace it on the stack by
18870	  // the return value of the lambda
18871	  resolvePossibleLambda: function resolvePossibleLambda() {
18872	    this.push([this.aliasable('container.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']);
18873	  },
18874
18875	  // [pushStringParam]
18876	  //
18877	  // On stack, before: ...
18878	  // On stack, after: string, currentContext, ...
18879	  //
18880	  // This opcode is designed for use in string mode, which
18881	  // provides the string value of a parameter along with its
18882	  // depth rather than resolving it immediately.
18883	  pushStringParam: function pushStringParam(string, type) {
18884	    this.pushContext();
18885	    this.pushString(type);
18886
18887	    // If it's a subexpression, the string result
18888	    // will be pushed after this opcode.
18889	    if (type !== 'SubExpression') {
18890	      if (typeof string === 'string') {
18891	        this.pushString(string);
18892	      } else {
18893	        this.pushStackLiteral(string);
18894	      }
18895	    }
18896	  },
18897
18898	  emptyHash: function emptyHash(omitEmpty) {
18899	    if (this.trackIds) {
18900	      this.push('{}'); // hashIds
18901	    }
18902	    if (this.stringParams) {
18903	      this.push('{}'); // hashContexts
18904	      this.push('{}'); // hashTypes
18905	    }
18906	    this.pushStackLiteral(omitEmpty ? 'undefined' : '{}');
18907	  },
18908	  pushHash: function pushHash() {
18909	    if (this.hash) {
18910	      this.hashes.push(this.hash);
18911	    }
18912	    this.hash = { values: [], types: [], contexts: [], ids: [] };
18913	  },
18914	  popHash: function popHash() {
18915	    var hash = this.hash;
18916	    this.hash = this.hashes.pop();
18917
18918	    if (this.trackIds) {
18919	      this.push(this.objectLiteral(hash.ids));
18920	    }
18921	    if (this.stringParams) {
18922	      this.push(this.objectLiteral(hash.contexts));
18923	      this.push(this.objectLiteral(hash.types));
18924	    }
18925
18926	    this.push(this.objectLiteral(hash.values));
18927	  },
18928
18929	  // [pushString]
18930	  //
18931	  // On stack, before: ...
18932	  // On stack, after: quotedString(string), ...
18933	  //
18934	  // Push a quoted version of `string` onto the stack
18935	  pushString: function pushString(string) {
18936	    this.pushStackLiteral(this.quotedString(string));
18937	  },
18938
18939	  // [pushLiteral]
18940	  //
18941	  // On stack, before: ...
18942	  // On stack, after: value, ...
18943	  //
18944	  // Pushes a value onto the stack. This operation prevents
18945	  // the compiler from creating a temporary variable to hold
18946	  // it.
18947	  pushLiteral: function pushLiteral(value) {
18948	    this.pushStackLiteral(value);
18949	  },
18950
18951	  // [pushProgram]
18952	  //
18953	  // On stack, before: ...
18954	  // On stack, after: program(guid), ...
18955	  //
18956	  // Push a program expression onto the stack. This takes
18957	  // a compile-time guid and converts it into a runtime-accessible
18958	  // expression.
18959	  pushProgram: function pushProgram(guid) {
18960	    if (guid != null) {
18961	      this.pushStackLiteral(this.programExpression(guid));
18962	    } else {
18963	      this.pushStackLiteral(null);
18964	    }
18965	  },
18966
18967	  // [registerDecorator]
18968	  //
18969	  // On stack, before: hash, program, params..., ...
18970	  // On stack, after: ...
18971	  //
18972	  // Pops off the decorator's parameters, invokes the decorator,
18973	  // and inserts the decorator into the decorators list.
18974	  registerDecorator: function registerDecorator(paramSize, name) {
18975	    var foundDecorator = this.nameLookup('decorators', name, 'decorator'),
18976	        options = this.setupHelperArgs(name, paramSize);
18977
18978	    this.decorators.push(['fn = ', this.decorators.functionCall(foundDecorator, '', ['fn', 'props', 'container', options]), ' || fn;']);
18979	  },
18980
18981	  // [invokeHelper]
18982	  //
18983	  // On stack, before: hash, inverse, program, params..., ...
18984	  // On stack, after: result of helper invocation
18985	  //
18986	  // Pops off the helper's parameters, invokes the helper,
18987	  // and pushes the helper's return value onto the stack.
18988	  //
18989	  // If the helper is not found, `helperMissing` is called.
18990	  invokeHelper: function invokeHelper(paramSize, name, isSimple) {
18991	    var nonHelper = this.popStack(),
18992	        helper = this.setupHelper(paramSize, name),
18993	        simple = isSimple ? [helper.name, ' || '] : '';
18994
18995	    var lookup = ['('].concat(simple, nonHelper);
18996	    if (!this.options.strict) {
18997	      lookup.push(' || ', this.aliasable('helpers.helperMissing'));
18998	    }
18999	    lookup.push(')');
19000
19001	    this.push(this.source.functionCall(lookup, 'call', helper.callParams));
19002	  },
19003
19004	  // [invokeKnownHelper]
19005	  //
19006	  // On stack, before: hash, inverse, program, params..., ...
19007	  // On stack, after: result of helper invocation
19008	  //
19009	  // This operation is used when the helper is known to exist,
19010	  // so a `helperMissing` fallback is not required.
19011	  invokeKnownHelper: function invokeKnownHelper(paramSize, name) {
19012	    var helper = this.setupHelper(paramSize, name);
19013	    this.push(this.source.functionCall(helper.name, 'call', helper.callParams));
19014	  },
19015
19016	  // [invokeAmbiguous]
19017	  //
19018	  // On stack, before: hash, inverse, program, params..., ...
19019	  // On stack, after: result of disambiguation
19020	  //
19021	  // This operation is used when an expression like `{{foo}}`
19022	  // is provided, but we don't know at compile-time whether it
19023	  // is a helper or a path.
19024	  //
19025	  // This operation emits more code than the other options,
19026	  // and can be avoided by passing the `knownHelpers` and
19027	  // `knownHelpersOnly` flags at compile-time.
19028	  invokeAmbiguous: function invokeAmbiguous(name, helperCall) {
19029	    this.useRegister('helper');
19030
19031	    var nonHelper = this.popStack();
19032
19033	    this.emptyHash();
19034	    var helper = this.setupHelper(0, name, helperCall);
19035
19036	    var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
19037
19038	    var lookup = ['(', '(helper = ', helperName, ' || ', nonHelper, ')'];
19039	    if (!this.options.strict) {
19040	      lookup[0] = '(helper = ';
19041	      lookup.push(' != null ? helper : ', this.aliasable('helper
vendor: 11,305 bytes, lines 19041-19435
19041s.helperMissing'));
19042	    }
19043
19044	    this.push(['(', lookup, helper.paramsInit ? ['),(', helper.paramsInit] : [], '),', '(typeof helper === ', this.aliasable('"function"'), ' ? ', this.source.functionCall('helper', 'call', helper.callParams), ' : helper))']);
19045	  },
19046
19047	  // [invokePartial]
19048	  //
19049	  // On stack, before: context, ...
19050	  // On stack after: result of partial invocation
19051	  //
19052	  // This operation pops off a context, invokes a partial with that context,
19053	  // and pushes the result of the invocation back.
19054	  invokePartial: function invokePartial(isDynamic, name, indent) {
19055	    var params = [],
19056	        options = this.setupParams(name, 1, params);
19057
19058	    if (isDynamic) {
19059	      name = this.popStack();
19060	      delete options.name;
19061	    }
19062
19063	    if (indent) {
19064	      options.indent = JSON.stringify(indent);
19065	    }
19066	    options.helpers = 'helpers';
19067	    options.partials = 'partials';
19068	    options.decorators = 'container.decorators';
19069
19070	    if (!isDynamic) {
19071	      params.unshift(this.nameLookup('partials', name, 'partial'));
19072	    } else {
19073	      params.unshift(name);
19074	    }
19075
19076	    if (this.options.compat) {
19077	      options.depths = 'depths';
19078	    }
19079	    options = this.objectLiteral(options);
19080	    params.push(options);
19081
19082	    this.push(this.source.functionCall('container.invokePartial', '', params));
19083	  },
19084
19085	  // [assignToHash]
19086	  //
19087	  // On stack, before: value, ..., hash, ...
19088	  // On stack, after: ..., hash, ...
19089	  //
19090	  // Pops a value off the stack and assigns it to the current hash
19091	  assignToHash: function assignToHash(key) {
19092	    var value = this.popStack(),
19093	        context = undefined,
19094	        type = undefined,
19095	        id = undefined;
19096
19097	    if (this.trackIds) {
19098	      id = this.popStack();
19099	    }
19100	    if (this.stringParams) {
19101	      type = this.popStack();
19102	      context = this.popStack();
19103	    }
19104
19105	    var hash = this.hash;
19106	    if (context) {
19107	      hash.contexts[key] = context;
19108	    }
19109	    if (type) {
19110	      hash.types[key] = type;
19111	    }
19112	    if (id) {
19113	      hash.ids[key] = id;
19114	    }
19115	    hash.values[key] = value;
19116	  },
19117
19118	  pushId: function pushId(type, name, child) {
19119	    if (type === 'BlockParam') {
19120	      this.pushStackLiteral('blockParams[' + name[0] + '].path[' + name[1] + ']' + (child ? ' + ' + JSON.stringify('.' + child) : ''));
19121	    } else if (type === 'PathExpression') {
19122	      this.pushString(name);
19123	    } else if (type === 'SubExpression') {
19124	      this.pushStackLiteral('true');
19125	    } else {
19126	      this.pushStackLiteral('null');
19127	    }
19128	  },
19129
19130	  // HELPERS
19131
19132	  compiler: JavaScriptCompiler,
19133
19134	  compileChildren: function compileChildren(environment, options) {
19135	    var children = environment.children,
19136	        child = undefined,
19137	        compiler = undefined;
19138
19139	    for (var i = 0, l = children.length; i < l; i++) {
19140	      child = children[i];
19141	      compiler = new this.compiler(); // eslint-disable-line new-cap
19142
19143	      var existing = this.matchExistingProgram(child);
19144
19145	      if (existing == null) {
19146	        this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
19147	        var index = this.context.programs.length;
19148	        child.index = index;
19149	        child.name = 'program' + index;
19150	        this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile);
19151	        this.context.decorators[index] = compiler.decorators;
19152	        this.context.environments[index] = child;
19153
19154	        this.useDepths = this.useDepths || compiler.useDepths;
19155	        this.useBlockParams = this.useBlockParams || compiler.useBlockParams;
19156	        child.useDepths = this.useDepths;
19157	        child.useBlockParams = this.useBlockParams;
19158	      } else {
19159	        child.index = existing.index;
19160	        child.name = 'program' + existing.index;
19161
19162	        this.useDepths = this.useDepths || existing.useDepths;
19163	        this.useBlockParams = this.useBlockParams || existing.useBlockParams;
19164	      }
19165	    }
19166	  },
19167	  matchExistingProgram: function matchExistingProgram(child) {
19168	    for (var i = 0, len = this.context.environments.length; i < len; i++) {
19169	      var environment = this.context.environments[i];
19170	      if (environment && environment.equals(child)) {
19171	        return environment;
19172	      }
19173	    }
19174	  },
19175
19176	  programExpression: function programExpression(guid) {
19177	    var child = this.environment.children[guid],
19178	        programParams = [child.index, 'data', child.blockParams];
19179
19180	    if (this.useBlockParams || this.useDepths) {
19181	      programParams.push('blockParams');
19182	    }
19183	    if (this.useDepths) {
19184	      programParams.push('depths');
19185	    }
19186
19187	    return 'container.program(' + programParams.join(', ') + ')';
19188	  },
19189
19190	  useRegister: function useRegister(name) {
19191	    if (!this.registers[name]) {
19192	      this.registers[name] = true;
19193	      this.registers.list.push(name);
19194	    }
19195	  },
19196
19197	  push: function push(expr) {
19198	    if (!(expr instanceof Literal)) {
19199	      expr = this.source.wrap(expr);
19200	    }
19201
19202	    this.inlineStack.push(expr);
19203	    return expr;
19204	  },
19205
19206	  pushStackLiteral: function pushStackLiteral(item) {
19207	    this.push(new Literal(item));
19208	  },
19209
19210	  pushSource: function pushSource(source) {
19211	    if (this.pendingContent) {
19212	      this.source.push(this.appendToBuffer(this.source.quotedString(this.pendingContent), this.pendingLocation));
19213	      this.pendingContent = undefined;
19214	    }
19215
19216	    if (source) {
19217	      this.source.push(source);
19218	    }
19219	  },
19220
19221	  replaceStack: function replaceStack(callback) {
19222	    var prefix = ['('],
19223	        stack = undefined,
19224	        createdStack = undefined,
19225	        usedLiteral = undefined;
19226
19227	    /* istanbul ignore next */
19228	    if (!this.isInline()) {
19229	      throw new _exception2['default']('replaceStack on non-inline');
19230	    }
19231
19232	    // We want to merge the inline statement into the replacement statement via ','
19233	    var top = this.popStack(true);
19234
19235	    if (top instanceof Literal) {
19236	      // Literals do not need to be inlined
19237	      stack = [top.value];
19238	      prefix = ['(', stack];
19239	      usedLiteral = true;
19240	    } else {
19241	      // Get or create the current stack name for use by the inline
19242	      createdStack = true;
19243	      var _name = this.incrStack();
19244
19245	      prefix = ['((', this.push(_name), ' = ', top, ')'];
19246	      stack = this.topStack();
19247	    }
19248
19249	    var item = callback.call(this, stack);
19250
19251	    if (!usedLiteral) {
19252	      this.popStack();
19253	    }
19254	    if (createdStack) {
19255	      this.stackSlot--;
19256	    }
19257	    this.push(prefix.concat(item, ')'));
19258	  },
19259
19260	  incrStack: function incrStack() {
19261	    this.stackSlot++;
19262	    if (this.stackSlot > this.stackVars.length) {
19263	      this.stackVars.push('stack' + this.stackSlot);
19264	    }
19265	    return this.topStackName();
19266	  },
19267	  topStackName: function topStackName() {
19268	    return 'stack' + this.stackSlot;
19269	  },
19270	  flushInline: function flushInline() {
19271	    var inlineStack = this.inlineStack;
19272	    this.inlineStack = [];
19273	    for (var i = 0, len = inlineStack.length; i < len; i++) {
19274	      var entry = inlineStack[i];
19275	      /* istanbul ignore if */
19276	      if (entry instanceof Literal) {
19277	        this.compileStack.push(entry);
19278	      } else {
19279	        var stack = this.incrStack();
19280	        this.pushSource([stack, ' = ', entry, ';']);
19281	        this.compileStack.push(stack);
19282	      }
19283	    }
19284	  },
19285	  isInline: function isInline() {
19286	    return this.inlineStack.length;
19287	  },
19288
19289	  popStack: function popStack(wrapped) {
19290	    var inline = this.isInline(),
19291	        item = (inline ? this.inlineStack : this.compileStack).pop();
19292
19293	    if (!wrapped && item instanceof Literal) {
19294	      return item.value;
19295	    } else {
19296	      if (!inline) {
19297	        /* istanbul ignore next */
19298	        if (!this.stackSlot) {
19299	          throw new _exception2['default']('Invalid stack pop');
19300	        }
19301	        this.stackSlot--;
19302	      }
19303	      return item;
19304	    }
19305	  },
19306
19307	  topStack: function topStack() {
19308	    var stack = this.isInline() ? this.inlineStack : this.compileStack,
19309	        item = stack[stack.length - 1];
19310
19311	    /* istanbul ignore if */
19312	    if (item instanceof Literal) {
19313	      return item.value;
19314	    } else {
19315	      return item;
19316	    }
19317	  },
19318
19319	  contextName: function contextName(context) {
19320	    if (this.useDepths && context) {
19321	      return 'depths[' + context + ']';
19322	    } else {
19323	      return 'depth' + context;
19324	    }
19325	  },
19326
19327	  quotedString: function quotedString(str) {
19328	    return this.source.quotedString(str);
19329	  },
19330
19331	  objectLiteral: function objectLiteral(obj) {
19332	    return this.source.objectLiteral(obj);
19333	  },
19334
19335	  aliasable: function aliasable(name) {
19336	    var ret = this.aliases[name];
19337	    if (ret) {
19338	      ret.referenceCount++;
19339	      return ret;
19340	    }
19341
19342	    ret = this.aliases[name] = this.source.wrap(name);
19343	    ret.aliasable = true;
19344	    ret.referenceCount = 1;
19345
19346	    return ret;
19347	  },
19348
19349	  setupHelper: function setupHelper(paramSize, name, blockHelper) {
19350	    var params = [],
19351	        paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper);
19352	    var foundHelper = this.nameLookup('helpers', name, 'helper'),
19353	        callContext = this.aliasable(this.contextName(0) + ' != null ? ' + this.contextName(0) + ' : (container.nullContext || {})');
19354
19355	    return {
19356	      params: params,
19357	      paramsInit: paramsInit,
19358	      name: foundHelper,
19359	      callParams: [callContext].concat(params)
19360	    };
19361	  },
19362
19363	  setupParams: function setupParams(helper, paramSize, params) {
19364	    var options = {},
19365	        contexts = [],
19366	        types = [],
19367	        ids = [],
19368	        objectArgs = !params,
19369	        param = undefined;
19370
19371	    if (objectArgs) {
19372	      params = [];
19373	    }
19374
19375	    options.name = this.quotedString(helper);
19376	    options.hash = this.popStack();
19377
19378	    if (this.trackIds) {
19379	      options.hashIds = this.popStack();
19380	    }
19381	    if (this.stringParams) {
19382	      options.hashTypes = this.popStack();
19383	      options.hashContexts = this.popStack();
19384	    }
19385
19386	    var inverse = this.popStack(),
19387	        program = this.popStack();
19388
19389	    // Avoid setting fn and inverse if neither are set. This allows
19390	    // helpers to do a check for `if (options.fn)`
19391	    if (program || inverse) {
19392	      options.fn = program || 'container.noop';
19393	      options.inverse = inverse || 'container.noop';
19394	    }
19395
19396	    // The parameters go on to the stack in order (making sure that they are evaluated in order)
19397	    // so we need to pop them off the stack in reverse order
19398	    var i = paramSize;
19399	    while (i--) {
19400	      param = this.popStack();
19401	      params[i] = param;
19402
19403	      if (this.trackIds) {
19404	        ids[i] = this.popStack();
19405	      }
19406	      if (this.stringParams) {
19407	        types[i] = this.popStack();
19408	        contexts[i] = this.popStack();
19409	      }
19410	    }
19411
19412	    if (objectArgs) {
19413	      options.args = this.source.generateArray(params);
19414	    }
19415
19416	    if (this.trackIds) {
19417	      options.ids = this.source.generateArray(ids);
19418	    }
19419	    if (this.stringParams) {
19420	      options.types = this.source.generateArray(types);
19421	      options.contexts = this.source.generateArray(contexts);
19422	    }
19423
19424	    if (this.options.data) {
19425	      options.data = 'data';
19426	    }
19427	    if (this.useBlockParams) {
19428	      options.blockParams = 'blockParams';
19429	    }
19430	    return options;
19431	  },
19432
19433	  setupHelperArgs: function setupHelperArgs(helper, paramSize, params, useRegister) {
19434	    var options = this.setupParams(helper, paramSize, params);
19435	    options
vendor: 1,005 bytes, lines 19435-19458
19435 = this.objectLiteral(options);
19436	    if (useRegister) {
19437	      this.useRegister('options');
19438	      params.push('options');
19439	      return ['options=', options];
19440	    } else if (params) {
19441	      params.push(options);
19442	      return '';
19443	    } else {
19444	      return options;
19445	    }
19446	  }
19447	};
19448
19449	(function () {
19450	  var reservedWords = ('break else new var' + ' case finally return void' + ' catch for switch while' + ' continue function this with' + ' default if throw' + ' delete in try' + ' do instanceof typeof' + ' abstract enum int short' + ' boolean export interface static' + ' byte extends long super' + ' char final native synchronized' + ' class float package throws' + ' const goto private transient' + ' debugger implements protected volatile' + ' double import public let yield await' + ' null true false').split(' ');
19451
19452	  var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
19453
19454	  for (var i = 0, l = reservedWords.length; i < l; i++) {
19455	    compilerWords[reservedWords[i]] = true;
19456	  }
19457	})();
19458
vendor: 4,122 bytes, lines 19459-19610
19459	JavaScriptCompiler.isValidJavaScriptVariableName = function (name) {
19460	  return !JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name);
19461	};
19462
19463	function strictLookup(requireTerminal, compiler, parts, type) {
19464	  var stack = compiler.popStack(),
19465	      i = 0,
19466	      len = parts.length;
19467	  if (requireTerminal) {
19468	    len--;
19469	  }
19470
19471	  for (; i < len; i++) {
19472	    stack = compiler.nameLookup(stack, parts[i], type);
19473	  }
19474
19475	  if (requireTerminal) {
19476	    return [compiler.aliasable('container.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ')'];
19477	  } else {
19478	    return stack;
19479	  }
19480	}
19481
19482	exports['default'] = JavaScriptCompiler;
19483	module.exports = exports['default'];
19484
19485/***/ }),
19486/* 43 */
19487/***/ (function(module, exports, __webpack_require__) {
19488
19489	/* global define */
19490	'use strict';
19491
19492	exports.__esModule = true;
19493
19494	var _utils = __webpack_require__(5);
19495
19496	var SourceNode = undefined;
19497
19498	try {
19499	  /* istanbul ignore next */
19500	  if (false) {
19501	    // We don't support this in AMD environments. For these environments, we asusme that
19502	    // they are running on the browser and thus have no need for the source-map library.
19503	    var SourceMap = require('source-map');
19504	    SourceNode = SourceMap.SourceNode;
19505	  }
19506	} catch (err) {}
19507	/* NOP */
19508
19509	/* istanbul ignore if: tested but not covered in istanbul due to dist build  */
19510	if (!SourceNode) {
19511	  SourceNode = function (line, column, srcFile, chunks) {
19512	    this.src = '';
19513	    if (chunks) {
19514	      this.add(chunks);
19515	    }
19516	  };
19517	  /* istanbul ignore next */
19518	  SourceNode.prototype = {
19519	    add: function add(chunks) {
19520	      if (_utils.isArray(chunks)) {
19521	        chunks = chunks.join('');
19522	      }
19523	      this.src += chunks;
19524	    },
19525	    prepend: function prepend(chunks) {
19526	      if (_utils.isArray(chunks)) {
19527	        chunks = chunks.join('');
19528	      }
19529	      this.src = chunks + this.src;
19530	    },
19531	    toStringWithSourceMap: function toStringWithSourceMap() {
19532	      return { code: this.toString() };
19533	    },
19534	    toString: function toString() {
19535	      return this.src;
19536	    }
19537	  };
19538	}
19539
19540	function castChunk(chunk, codeGen, loc) {
19541	  if (_utils.isArray(chunk)) {
19542	    var ret = [];
19543
19544	    for (var i = 0, len = chunk.length; i < len; i++) {
19545	      ret.push(codeGen.wrap(chunk[i], loc));
19546	    }
19547	    return ret;
19548	  } else if (typeof chunk === 'boolean' || typeof chunk === 'number') {
19549	    // Handle primitives that the SourceNode will throw up on
19550	    return chunk + '';
19551	  }
19552	  return chunk;
19553	}
19554
19555	function CodeGen(srcFile) {
19556	  this.srcFile = srcFile;
19557	  this.source = [];
19558	}
19559
19560	CodeGen.prototype = {
19561	  isEmpty: function isEmpty() {
19562	    return !this.source.length;
19563	  },
19564	  prepend: function prepend(source, loc) {
19565	    this.source.unshift(this.wrap(source, loc));
19566	  },
19567	  push: function push(source, loc) {
19568	    this.source.push(this.wrap(source, loc));
19569	  },
19570
19571	  merge: function merge() {
19572	    var source = this.empty();
19573	    this.each(function (line) {
19574	      source.add(['  ', line, '\n']);
19575	    });
19576	    return source;
19577	  },
19578
19579	  each: function each(iter) {
19580	    for (var i = 0, len = this.source.length; i < len; i++) {
19581	      iter(this.source[i]);
19582	    }
19583	  },
19584
19585	  empty: function empty() {
19586	    var loc = this.currentLocation || { start: {} };
19587	    return new SourceNode(loc.start.line, loc.start.column, this.srcFile);
19588	  },
19589	  wrap: function wrap(chunk) {
19590	    var loc = arguments.length <= 1 || arguments[1] === undefined ? this.currentLocation || { start: {} } : arguments[1];
19591
19592	    if (chunk instanceof SourceNode) {
19593	      return chunk;
19594	    }
19595
19596	    chunk = castChunk(chunk, this, loc);
19597
19598	    return new SourceNode(loc.start.line, loc.start.column, this.srcFile, chunk);
19599	  },
19600
19601	  functionCall: function functionCall(fn, type, params) {
19602	    params = this.generateList(params);
19603	    return this.wrap([fn, type ? '.' + type + '(' : '(', params, ')']);
19604	  },
19605
19606	  quotedString: function quotedString(str) {
19607	    return '"' + (str + '').replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4
19608	    .replace(/\u2029/g, '\\u2029') + '"';
19609	  },
19610
19611	  objectLiteral: function objectLiteral(obj) {
19612	    var pairs = [];
19613
19614	    for (var key in obj) {
19615	      if (obj.hasOwnProperty(key)) {
19616	        var value = castChunk(obj[key], this);
19617	        if (value !== 'undefined') {
19618	          pairs.push([this.quotedString(key), ':', value]);
19619	        }
19620	      }
19621	    }
19622
19623	    var ret = this.generateList(pairs);
19624	    ret.prepend('{');
19625	    ret.add('}');
19626	    return ret;
19627	  },
19628
19629	  generateList: function generateList(entries) {
19630	    var ret = this.empty();
19631
19632	    for (var i = 0, len = entries.length; i < len; i++) {
19633	      if (i) {
19634	        ret.add(',');
19635	      }
19636
19637	      ret.add(castChunk(entries[i], this));
19638	    }
19639
19640	    return ret;
19641	  },
19642
19643	  generateArray: function generateArray(entries) {
19644	    var ret = this.generateList(entries);
19645	    ret.prepend('[');
19646	    ret.add(']');
19647
19648	    return ret;
19649	  }
19650	};
19651
19652	exports['default'] = CodeGen;
19653	module.exports = exports['default'];
19654
19655/***/ })
19656/******/ ])
19657});
19658;
19659/*!
19660* jquery.inputmask.bundle.js
19661* https://github.com/RobinHerbots/Inputmask
19662* Copyright (c) 2010 - 2017 Robin Herbots
19663* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
19664* Version: 3.3.11
19665*/
19666
19667!function(modules) {
19668    function __webpack_require__(moduleId) {
19669        if (installedModules[moduleId]) return installedModules[moduleId].exports;
19670        var module = installedModules[moduleId] = {
19671            i: moduleId,
19672            l: !1,
19673            exports: {}
19674        };
19675        return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__), 
19676        module.l = !0, module.exports;
19677    }
19678    var installedModules = {};
19679    __webpack_require__.m = modules, __webpack_require__.c = installedModules, __webpack_require__.d = function(exports, name, getter) {
19680        __webpack_require__.o(exports, name) || Object.defineProperty(exports, name, {
19681            configurable: !1,
19682            enumerable: !0,
19683            get: getter
19684        });
19685    }, __webpack_require__.n = function(module) {
19686        var getter = module && module.__esModule ? function() {
19687            return module.default;
19688        } : function() {
19689            return module;
19690        };
19691        return __webpack_require__.d(getter, "a", getter), getter;
19692    }, __webpack_require__.o = function(object, property) {
19693        return Object.prototype.hasOwnProperty.call(object, property);
19694    }, __webpack_require__.p = "", __webpack_require__(__webpack_require__.s = 3);
19695}([ function(module, exports, __webpack_require__) {
19696    "use strict";
19697    var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
19698    "function" == typeof Symbol && Symbol.iterator;
19699    !function(factory) {
19700        __WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = "function" == typeof (__WEBPACK_AMD_DEFINE_FACTORY__ = factory) ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
19701    }(function($) {
19702        return $;
19703    });
19704}, function(module, exports, __webpack_require__) {
19705    "use strict";
19706    var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__, _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(obj) {
19707        return typeof obj;
19708    } : function(obj) {
19709        return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
19710    };
19711    !function(factory) {
19712        __WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(0), __webpack_require__(10), __webpack_require__(11) ], 
19713        void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = "function" == typeof (__WEBPACK_AMD_DEFINE_FACTORY__ = factory) ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
19714    }(function($, window, document, undefined) {
19715        function Inputmask(alias, options, internal) {
19716            if (!(this instanceof Inputmask)) return new Inputmask(alias, options, internal);
19717            this.el = undefined, this.events = {}, this.maskset = undefined, this.refreshValue = !1, 
19718            !0 !== internal && ($.isPlainObject(alias) ? options = alias : (options = options || {}).alias = alias, 
19719            this.opts = $.extend(!0, {}, this.defaults, options), this.noMasksCache = options && options.definitions !== undefined, 
19720            this.userOptions = options || {}, this.isRTL = this.opts.numericInput, resolveAlias(this.opts.alias, options, this.opts));
19721        }
19722        function resolveAlias(aliasStr, options, opts) {
19723            var aliasDefinition = Inputmask.prototype.aliases[aliasStr];
19724            return aliasDefinition ? (aliasDefinition.alias && resolveAlias(aliasDefinition.alias, undefined, opts), 
19725            $.extend(!0, opts, aliasDefinition), $.extend(!0, opts, options), !0) : (null === opts.mask && (
19725opts.mask = aliasStr), 
19726            !1);
19727        }
19728        function generateMaskSet(opts, nocache) {
19729            function generateMask(mask, metadata, opts) {
19730                var regexMask = !1;
19731                if (null !== mask && "" !== mask || ((regexMask = null !== opts.regex) ? mask = (mask = opts.regex).replace(/^(\^)(.*)(\$)$/, "$2") : (regexMask = !0, 
19732                mask = ".*")), 1 === mask.length && !1 === opts.greedy && 0 !== opts.repeat && (opts.placeholder = ""), 
19733                opts.repeat > 0 || "*" === opts.repeat || "+" === opts.repeat) {
19734                    var repeatStart = "*" === opts.repeat ? 0 : "+" === opts.repeat ? 1 : opts.repeat;
19735                    mask = opts.groupmarker.start + mask + opts.groupmarker.end + opts.quantifiermarker.start + repeatStart + "," + opts.repeat + opts.quantifiermarker.end;
19736                }
19737                var masksetDefinition, maskdefKey = regexMask ? "regex_" + opts.regex : opts.numericInput ? mask.split("").reverse().join("") : mask;
19738                return Inputmask.prototype.masksCache[maskdefKey] === undefined || !0 === nocache ? (masksetDefinition = {
19739                    mask: mask,
19740                    maskToken: Inputmask.prototype.analyseMask(mask, regexMask, opts),
19741                    validPositions: {},
19742                    _buffer: undefined,
19743                    buffer: undefined,
19744                    tests: {},
19745                    metadata: metadata,
19746                    maskLength: undefined
19747                }, !0 !== nocache && (Inputmask.prototype.masksCache[maskdefKey] = masksetDefinition, 
19748                masksetDefinition = $.extend(!0, {}, Inputmask.prototype.masksCache[maskdefKey]))) : masksetDefinition = $.extend(!0, {}, Inputmask.prototype.masksCache[maskdefKey]), 
19749                masksetDefinition;
19750            }
19751            if ($.isFunction(opts.mask) && (opts.mask = opts.mask(opts)), $.isArray(opts.mask)) {
19752                if (opts.mask.length > 1) {
19753                    opts.keepStatic = null === opts.keepStatic || opts.keepStatic;
19754                    var altMask = opts.groupmarker.start;
19755                    return $.each(opts.numericInput ? opts.mask.reverse() : opts.mask, function(ndx, msk) {
19756                        altMask.length > 1 && (altMask += opts.groupmarker.end + opts.alternatormarker + opts.groupmarker.start), 
19757                        msk.mask === undefined || $.isFunction(msk.mask) ? altMask += msk : altMask += msk.mask;
19758                    }), altMask += opts.groupmarker.end, generateMask(altMask, opts.mask, opts);
19759                }
19760                opts.mask = opts.mask.pop();
19761            }
19762            return opts.mask && opts.mask.mask !== undefined && !$.isFunction(opts.mask.mask) ? generateMask(opts.mask.mask, opts.mask, opts) : generateMask(opts.mask, opts.mask, opts);
19763        }
19764        function maskScope(actionObj, maskset, opts) {
19765            function getMaskTemplate(baseOnInput, minimalPos, includeMode) {
19766                minimalPos = minimalPos || 0;
19767                var ndxIntlzr, test, testPos, maskTemplate = [], pos = 0, lvp = getLastValidPosition();
19768                do {
19769                    !0 === baseOnInput && getMaskSet().validPositions[pos] ? (test = (testPos = getMaskSet().validPositions[pos]).match, 
19770                    ndxIntlzr = testPos.locator.slice(), maskTemplate.push(!0 === includeMode ? testPos.input : !1 === includeMode ? test.nativeDef : getPlaceholder(pos, test))) : (test = (testPos = getTestTemplate(pos, ndxIntlzr, pos - 1)).match, 
19771                    ndxIntlzr = testPos.locator.slice(), (!1 === opts.jitMasking || pos < lvp || "number" == typeof opts.jitMasking && isFinite(opts.jitMasking) && opts.jitMasking > pos) && maskTemplate.push(!1 === includeMode ? test.nativeDef : getPlaceholder(pos, test))), 
19772                    pos++;
19773                } while ((maxLength === undefined || pos < maxLength) && (null !== test.fn || "" !== test.def) || minimalPos > pos);
19774                return "" === maskTemplate[maskTemplate.length - 1] && maskTemplate.pop(), getMaskSet().maskLength = pos + 1, 
19775                maskTemplate;
19776            }
19777            function getMaskSet() {
19778                return maskset;
19779            }
19780            function resetMaskSet(soft) {
19781                var maskset = getMaskSet();
19782                maskset.buffer = undefined, !0 !== soft && (maskset.validPositions = {}, maskset.p = 0);
19783            }
19784            function getLastValidPosition(closestTo, strict, validPositions) {
19785                var before = -1, after = -1, valids = validPositions || getMaskSet().validPositions;
19786                closestTo === undefined && (closestTo = -1);
19787                for (var posNdx in valids) {
19788                    var psNdx = parseInt(posNdx);
19789                    valids[psNdx] && (strict || !0 !== valids[psNdx].generatedInput) && (psNdx <= closestTo && (before = psNdx), 
19790                    psNdx >= closestTo && (after = psNdx));
19791                }
19792                return -1 !== before && closestTo - before > 1 || after < closestTo ? before : after;
19793            }
19794            function stripValidPositions(start, end, nocheck, strict) {
19795                var i, startPos = start, positionsClone = $.extend(!0, {}, getMaskSet().validPositions), needsValidation = !1;
19796                for (getMaskSet().p = start, i = end - 1; i >= startPos; i--) getMaskSet().validPositions[i] !== undefined && (!0 !== nocheck && (!getMaskSet().validPositions[i].match.optionality && function(pos) {
19797                    var posMatch = getMaskSet().validPositions[pos];
19798                    if (posMatch !== undefined && null === posMatch.match.fn) {
19799                        var prevMatch = getMaskSet().validPositions[pos - 1], nextMatch = getMaskSet().validPositions[pos + 1];
19800                        return prevMatch !== undefined && nextMatch !== undefined;
19801                    }
19802                    return !1;
19803                }(i) || !1 === opts.canClearPosition(getMaskSet(), i, getLastValidPosition(), str
19803ict, opts)) || delete getMaskSet().validPositions[i]);
19804                for (resetMaskSet(!0), i = startPos + 1; i <= getLastValidPosition(); ) {
19805                    for (;getMaskSet().validPositions[startPos] !== undefined; ) startPos++;
19806                    if (i < startPos && (i = startPos + 1), getMaskSet().validPositions[i] === undefined && isMask(i)) i++; else {
19807                        var t = getTestTemplate(i);
19808                        !1 === needsValidation && positionsClone[startPos] && positionsClone[startPos].match.def === t.match.def ? (getMaskSet().validPositions[startPos] = $.extend(!0, {}, positionsClone[startPos]), 
19809                        getMaskSet().validPositions[startPos].input = t.input, delete getMaskSet().validPositions[i], 
19810                        i++) : positionCanMatchDefinition(startPos, t.match.def) ? !1 !== isValid(startPos, t.input || getPlaceholder(i), !0) && (delete getMaskSet().validPositions[i], 
19811                        i++, needsValidation = !0) : isMask(i) || (i++, startPos--), startPos++;
19812                    }
19813                }
19814                resetMaskSet(!0);
19815            }
19816            function determineTestTemplate(tests, guessNextBest) {
19817                for (var testPos, testPositions = tests, lvp = getLastValidPosition(), lvTest = getMaskSet().validPositions[lvp] || getTests(0)[0], lvTestAltArr = lvTest.alternation !== undefined ? lvTest.locator[lvTest.alternation].toString().split(",") : [], ndx = 0; ndx < testPositions.length && (!((testPos = testPositions[ndx]).match && (opts.greedy && !0 !== testPos.match.optionalQuantifier || (!1 === testPos.match.optionality || !1 === testPos.match.newBlockMarker) && !0 !== testPos.match.optionalQuantifier) && (lvTest.alternation === undefined || lvTest.alternation !== testPos.alternation || testPos.locator[lvTest.alternation] !== undefined && checkAlternationMatch(testPos.locator[lvTest.alternation].toString().split(","), lvTestAltArr))) || !0 === guessNextBest && (null !== testPos.match.fn || /[0-9a-bA-Z]/.test(testPos.match.def))); ndx++) ;
19818                return testPos;
19819            }
19820            function getTestTemplate(pos, ndxIntlzr, tstPs) {
19821                return getMaskSet().validPositions[pos] || determineTestTemplate(getTests(pos, ndxIntlzr ? ndxIntlzr.slice() : ndxIntlzr, tstPs));
19822            }
19823            function getTest(pos) {
19824                return getMaskSet().validPositions[pos] ? getMaskSet().validPositions[pos] : getTests(pos)[0];
19825            }
19826            function positionCanMatchDefinition(pos, def) {
19827                for (var valid = !1, tests = getTests(pos), tndx = 0; tndx < tests.length; tndx++) if (tests[tndx].match && tests[tndx].match.def === def) {
19828                    valid = !0;
19829                    break;
19830                }
19831                return valid;
19832            }
19833            function getTests(pos, ndxIntlzr, tstPs) {
19834                function resolveTestFromToken(maskToken, ndxInitializer, loopNdx, quantifierRecurse) {
19835                    function handleMatch(match, loopNdx, quantifierRecurse) {
19836                        function isFirstMatch(latestMatch, tokenGroup) {
19837                            var firstMatch = 0 === $.inArray(latestMatch, tokenGroup.matches);
19838                            return firstMatch || $.each(tokenGroup.matches, function(ndx, match) {
19839                                if (!0 === match.isQuantifier && (firstMatch = isFirstMatch(latestMatch, tokenGroup.matches[ndx - 1]))) return !1;
19840                            }), firstMatch;
19841                        }
19842                        function resolveNdxInitializer(pos, alternateNdx, targetAlternation) {
19843                            var bestMatch, indexPos;
19844                            if (getMaskSet().validPositions[pos - 1] && targetAlternation && getMaskSet().tests[pos]) for (var vpAlternation = getMaskSet().validPositions[pos - 1].locator, tpAlternation = getMaskSet().tests[pos][0].locator, i = 0; i < targetAlternation; i++) if (vpAlternation[i] !== tpAlternation[i]) return vpAlternation.slice(targetAlternation + 1);
19845                            return (getMaskSet().tests[pos] || getMaskSet().validPositions[pos]) && $.each(getMaskSet().tests[pos] || [ getMaskSet().validPositions[pos] ], function(ndx, lmnt) {
19846                                var alternation = targetAlternation !== undefined ? targetAlternation : lmnt.alternation, ndxPos = lmnt.locator[alternation] !== undefined ? lmnt.locator[alternation].toString().indexOf(alternateNdx) : -1;
19847                                (indexPos === undefined || ndxPos < indexPos) && -1 !== ndxPos && (bestMatch = lmnt, 
19848                                indexPos = ndxPos);
19849                            }), bestMatch ? bestMatch.locator.slice((targetAlternation !== undefined ? targetAlternation : bestMatch.alternation) + 1) : targetAlternation !== undefined ? resolveNdxInitializer(pos, alternateNdx) : undefined;
19850                        }
19851                        if (testPos > 1e4) throw "Inputmask: There is probably an error in your mask definition or in the code. Create an issue on github with an example of the mask you are using. " + getMaskSet().mask;
19852                        if (testPos === pos && match.matches === undefined) return matches.push({
19853                            match: match,
19854                            locator: loopNdx.reverse(),
19855                            cd: cacheDependency
19856                        }), !0;
19857                        if (match.matches !== undefined) {
19858                            if (match.isGroup && quantifierRecurse !== match) {
19859                                if (match = handleMatch(maskToken.matches[$.inArray(match, maskToken.matches) + 1], loopNdx)) return !0;
19860                            } else if (match.isOptional) {
19861                                var optionalToken = match;
19862                                if (match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse)) {
19863                                    if (latestMatch = matches[matches.length - 1].match, !isFirstMatch(latestMatch, optionalToken)) return !0;
19864                                    insertStop = !0, testPos = pos;
19865                                }
19866                            } else if (match.isAlternator) {
19867                                var maltMatches, alternateToken = match, malternateMatches = [], currentMatches = matches.slice(), loopNdxCnt = loopNdx.length, altIndex = ndxInitializer.length > 0 ? ndxInitializer.shift() : -1;
19868                                if (-1 === altIndex || "string" == typeof altIndex) {
19869                                    var amndx, currentPos = testPos, ndxInitializerClone = ndxInitializer.slice(), altIndexArr = [];
19870                                    if ("string" == typeof altIndex) altIndexArr = altIndex.split(","); else for (amndx = 0;
19870 amndx < alternateToken.matches.length; amndx++) altIndexArr.push(amndx);
19871                                    for (var ndx = 0; ndx < altIndexArr.length; ndx++) {
19872                                        if (amndx = parseInt(altIndexArr[ndx]), matches = [], ndxInitializer = resolveNdxInitializer(testPos, amndx, loopNdxCnt) || ndxInitializerClone.slice(), 
19873                                        !0 !== (match = handleMatch(alternateToken.matches[amndx] || maskToken.matches[amndx], [ amndx ].concat(loopNdx), quantifierRecurse) || match) && match !== undefined && altIndexArr[altIndexArr.length - 1] < alternateToken.matches.length) {
19874                                            var ntndx = $.inArray(match, maskToken.matches) + 1;
19875                                            maskToken.matches.length > ntndx && (match = handleMatch(maskToken.matches[ntndx], [ ntndx ].concat(loopNdx.slice(1, loopNdx.length)), quantifierRecurse)) && (altIndexArr.push(ntndx.toString()), 
19876                                            $.each(matches, function(ndx, lmnt) {
19877                                                lmnt.alternation = loopNdx.length - 1;
19878                                            }));
19879                                        }
19880                                        maltMatches = matches.slice(), testPos = currentPos, matches = [];
19881                                        for (var ndx1 = 0; ndx1 < maltMatches.length; ndx1++) {
19882                                            var altMatch = maltMatches[ndx1], dropMatch = !1;
19883                                            altMatch.alternation = altMatch.alternation || loopNdxCnt;
19884                                            for (var ndx2 = 0; ndx2 < malternateMatches.length; ndx2++) {
19885                                                var altMatch2 = malternateMatches[ndx2];
19886                                                if ("string" != typeof altIndex || -1 !== $.inArray(altMatch.locator[altMatch.alternation].toString(), altIndexArr)) {
19887                                                    if (function(source, target) {
19888                                                        return source.match.nativeDef === target.match.nativeDef || source.match.def === target.match.nativeDef || source.match.nativeDef === target.match.def;
19889                                                    }(altMatch, altMatch2)) {
19890                                                        dropMatch = !0, altMatch.alternation === altMatch2.alternation && -1 === altMatch2.locator[altMatch2.alternation].toString().indexOf(altMatch.locator[altMatch.alternation]) && (altMatch2.locator[altMatch2.alternation] = altMatch2.locator[altMatch2.alternation] + "," + altMatch.locator[altMatch.alternation], 
19891                                                        altMatch2.alternation = altMatch.alternation), altMatch.match.nativeDef === altMatch2.match.def && (altMatch.locator[altMatch.alternation] = altMatch2.locator[altMatch2.alternation], 
19892                                                        malternateMatches.splice(malternateMatches.indexOf(altMatch2), 1, altMatch));
19893                                                        break;
19894                                                    }
19895                                                    if (altMatch.match.def === altMatch2.match.def) {
19896                                                        dropMatch = !1;
19897                                                        break;
19898                                                    }
19899                                                    if (function(source, target) {
19900                                                        return null === source.match.fn && null !== target.match.fn && target.match.fn.test(source.match.def, getMaskSet(), pos, !1, opts, !1);
19901                                                    }(altMatch, altMatch2) || function(source, target) {
19902                                                        return null !== source.match.fn && null !== target.match.fn && target.match.fn.test(source.match.def.replace(/[\[\]]/g, ""), getMaskSet(), pos, !1, opts, !1);
19903                                                    }(altMatch, altMatch2)) {
19904                                                        altMatch.alternation === altMatch2.alternation && -1 === altMatch.locator[altMatch.alternation].toString().indexOf(altMatch2.locator[altMatch2.alternation].toString().split("")[0]) && (altMatch.na = altMatch.na || altMatch.locator[altMatch.alternation].toString(), 
19905                                                        -1 === altMatch.na.indexOf(altMatch.locator[altMatch.alternation].toString().split("")[0]) && (altMatch.na = altMatch.na + "," + altMatch.locator[altMatch2.alternation].toString().split("")[0]), 
19906                                                        dropMatch = !0, altMatch.locator[altMatch.alternation] = altMatch2.locator[altMatch2.alternation].toString().split("")[0] + "," + altMatch.locator[altMatch.alternation], 
19907                                                        malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch));
19908                                                        break;
19909                                                    }
19910                                                }
19911                                            }
19912                                            dropMatch || malternateMatches.push(altMatch);
19913                                        }
19914                                    }
19915                                    "string" == typeof altIndex && (malternateMatches = $.map(malternateMatches, function(lmnt, ndx) {
19916                                        if (isFinite(ndx)) {
19917                                            var alternation = lmnt.alternation, altLocArr = lmnt.locator[alternation].toString().split(",");
19918                                            lmnt.locator[alternation] = undefined, lmnt.alternation = undefined;
19919                                            for (var alndx = 0; alndx < altLocArr.length; alndx++) -1 !== $.inArray(altLocArr[alndx], altIndexArr) && (lmnt.locator[alternation] !== undefined ? (lmnt.locator[alternation] += ",", 
19920                                            lmnt.locator[alternation] += altLocArr[alndx]) : lmnt.locator[alternation] = parseInt(altLocArr[alndx]), 
19921                                            lmnt.alternation = alternation);
19922                                            if (lmnt.locator[alternation] !== undefined) return lmnt;
19923                                        }
19924                                    })), matches = currentMatches.concat(malternateMatches), testPos = pos, insertStop = matches.length > 0, 
19925                                    match = malternateMatches.length > 0, ndxInitializer = ndxInitializerClone.slice();
19926                                } else match = handleMatch(alternateToken.matches[altIndex] || maskToken.matches[altIndex], [ altIndex ].concat(loopNdx), quantifierRecurse);
19927                                if (match) return !0;
19928                            } else if (match.isQuantifier && quantifierRecurse !== maskToken.matches[$.inArray(match, maskToken.matches) - 1]) for (var qt = match, qndx = ndxInitializer.length > 0 ? ndxInitializer.shift() : 0; qndx < (isNaN(qt.quantifier.max) ? qndx + 1 : qt.quantifier.max) && testPos <= pos; qndx++) {
19929                                var tokenGroup = maskToken.matches[$.inArray(qt, maskToken.matches) - 1];
19930                                if (match = handleMatch(tokenGroup, [ qndx ].concat(loopNdx), tokenGroup)) {
19931                                    if (latestMatch = matches[matches.length - 1].match, latestMatch.optionalQuantifier = qndx > qt.quantifier.min - 1, 
19932                                    isFirstMatch(latestMatch, tokenGroup)) {
19933                                        if (qndx > qt.quantifier.min - 1) {
19934                                            insertStop = !0, testPos = pos;
19935                                            break;
19936                                        }
19937                                        return !0;
19938                                    }
19939                                    return !0;
19940                                }
19941                            } else if (match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse)) return !0;
19942                        } else testPos++;
19943                    }
19944                    for (var tndx = ndxInitializer.length > 0 ? ndxInitializer.shift() : 0; tndx < maskToken.matches.length; tndx++) if (!0 !== maskToken.matches[tndx].isQuantifier) {
19945                        var match = handleMatch(maskToken.matches[tndx], [ tndx ].concat(loopNdx), quantifierRecurse);
19946                        if (match && testPos === pos) return match;
19947                        if (testPos > pos) break;
19948                    }
19949                }
19950                function filterTests(tests) {
19951                    if (opts.keepStatic && pos > 0 && tests.length > 1 + ("" === tests[tests.length - 1].match.def ? 1 : 0) && !0 !== tests[0].match.optionality && !0 !== tests[0].match.optionalQuantifier && null === tests[0].match.fn && !/[0-9a-bA-Z]/.test(tests[0].match.def)) {
19952                        if (getMaskSet().validPositions[pos - 1] === undefined) return [ determineTestTemplate(tests) ];
19953                        if (getMaskSet().validPositions[pos - 1].alternation === tests[0].alternation) return [ determineTestTemplate(tests) ];
19954                        if (getMaskSet().validPositions[pos - 1]) return [ determineTestTemplate(tests) ];
19955                    }
19956                    return tests;
19957                }
19958                var latestMatch, maskTokens = getMaskSet().maskToken, testPos = ndxIntlzr ? tstPs : 0, ndxInitializer = ndxIntlzr ? ndxIntlzr.slice() : [ 0 ], matches = [], insertStop = !1, cacheDependency = ndxIntlzr ? ndxIntlzr.join("") : "";
19959                if (pos > -1) {
19960                    if (ndxIntlzr === undefined) {
19961                        for (var test, previousPos = pos - 1; (test = getMaskSet().validPositions[previousPos] || getMaskSet().tests[previousPos]) === undefined && previousPos > -1; ) previousPos--;
19962                        test !== undefined && previousPos > -1 && (ndxInitializer = function(tests) {
19963                            var locator = [];
19964                            return $.isArray(tests) || (tests = [ tests ]), tests.length > 0 && (tests[0].alternation === undefined ? 0 === (locator = determineTestTemplate(tests.slice()).locator.slice()).length && (locator = tests[0].locator.slice()) : $.each(tests, function(ndx, tst) {
19965                                if ("" !== tst.def) if (0 === locator.length) locator = t
19965st.locator.slice(); else for (var i = 0; i < locator.length; i++) tst.locator[i] && -1 === locator[i].toString().indexOf(tst.locator[i]) && (locator[i] += "," + tst.locator[i]);
19966                            })), locator;
19967                        }(test), cacheDependency = ndxInitializer.join(""), testPos = previousPos);
19968                    }
19969                    if (getMaskSet().tests[pos] && getMaskSet().tests[pos][0].cd === cacheDependency) return filterTests(getMaskSet().tests[pos]);
19970                    for (var mtndx = ndxInitializer.shift(); mtndx < maskTokens.length && !(resolveTestFromToken(maskTokens[mtndx], ndxInitializer, [ mtndx ]) && testPos === pos || testPos > pos); mtndx++) ;
19971                }
19972                return (0 === matches.length || insertStop) && matches.push({
19973                    match: {
19974                        fn: null,
19975                        cardinality: 0,
19976                        optionality: !0,
19977                        casing: null,
19978                        def: "",
19979                        placeholder: ""
19980                    },
19981                    locator: [],
19982                    cd: cacheDependency
19983                }), ndxIntlzr !== undefined && getMaskSet().tests[pos] ? filterTests($.extend(!0, [], matches)) : (getMaskSet().tests[pos] = $.extend(!0, [], matches), 
19984                filterTests(getMaskSet().tests[pos]));
19985            }
19986            function getBufferTemplate() {
19987                return getMaskSet()._buffer === undefined && (getMaskSet()._buffer = getMaskTemplate(!1, 1), 
19988                getMaskSet().buffer === undefined && (getMaskSet().buffer = getMaskSet()._buffer.slice())), 
19989                getMaskSet()._buffer;
19990            }
19991            function getBuffer(noCache) {
19992                return getMaskSet().buffer !== undefined && !0 !== noCache || (getMaskSet().buffer = getMaskTemplate(!0, getLastValidPosition(), !0)), 
19993                getMaskSet().buffer;
19994            }
19995            function refreshFromBuffer(start, end, buffer) {
19996                var i, p;
19997                if (!0 === start) resetMaskSet(), start = 0, end = buffer.length; else for (i = start; i < end; i++) delete getMaskSet().validPositions[i];
19998                for (p = start, i = start; i < end; i++) if (resetMaskSet(!0), buffer[i] !== opts.skipOptionalPartCharacter) {
19999                    var valResult = isValid(p, buffer[i], !0, !0);
20000                    !1 !== valResult && (resetMaskSet(!0), p = valResult.caret !== undefined ? valResult.caret : valResult.pos + 1);
20001                }
20002            }
20003            function casing(elem, test, pos) {
20004                switch (opts.casing || test.casing) {
20005                  case "upper":
20006                    elem = elem.toUpperCase();
20007                    break;
20008
20009                  case "lower":
20010                    elem = elem.toLowerCase();
20011                    break;
20012
20013                  case "title":
20014                    var posBefore = getMaskSet().validPositions[pos - 1];
20015                    elem = 0 === pos || posBefore && posBefore.input === String.fromCharCode(Inputmask.keyCode.SPACE) ? elem.toUpperCase() : elem.toLowerCase();
20016                    break;
20017
20018                  default:
20019                    if ($.isFunction(opts.casing)) {
20020                        var args = Array.prototype.slice.call(arguments);
20021                        args.push(getMaskSet().validPositions), elem = opts.casing.apply(this, args);
20022                    }
20023                }
20024                return elem;
20025            }
20026            function checkAlternationMatch(altArr1, altArr2, na) {
20027                for (var naNdx, altArrC = opts.greedy ? altArr2 : altArr2.slice(0, 1), isMatch = !1, naArr = na !== undefined ? na.split(",") : [], i = 0; i < naArr.length; i++) -1 !== (naNdx = altArr1.indexOf(naArr[i])) && altArr1.splice(naNdx, 1);
20028                for (var alndx = 0; alndx < altArr1.length; alndx++) if (-1 !== $.inArray(altArr1[alndx], altArrC)) {
20029                    isMatch = !0;
20030                    break;
20031                }
20032                return isMatch;
20033            }
20034            function isValid(pos, c, strict, fromSetValid, fromAlternate, validateOnly) {
20035                function isSelection(posObj) {
20036                    var selection = isRTL ? posObj.begin - posObj.end > 1 || posObj.begin - posObj.end == 1 : posObj.end - posObj.begin > 1 || posObj.end - posObj.begin == 1;
20037                    return selection && 0 === posObj.begin && posObj.end === getMaskSet().maskLength ? "full" : selection;
20038                }
20039                function _isValid(position, c, strict) {
20040                    var rslt = !1;
20041                    return $.each(getTests(position), function(ndx, tst) {
20042                        for (var test = tst.match, loopend = c ? 1 : 0, chrs = "", i = test.cardinality; i > loopend; i--) chrs += getBufferElement(position - (i - 1));
20043                        if (c && (chrs += c), getBuffer(!0), !1 !== (rslt = null != test.fn ? test.fn.test(chrs, getMaskSet(), position, strict, opts, isSelection(pos)) : (c === test.def || c === opts.skipOptionalPartCharacter) && "" !== test.def && {
20044                            c: getPlaceholder(position, test, !0) || test.def,
20045                            pos: position
20046                        })) {
20047                            var elem = rslt.c !== undefined ? rslt.c : c;
20048                            elem = elem === opts.skipOptionalPartCharacter && null === test.fn ? getPlaceholder(position, test, !0) || test.def : elem;
20049                            var validatedPos = position, possibleModifiedBuffer = getBuffer();
20050                            if (rslt.remove !== undefined && ($.isArray(rslt.remove) || (rslt.remove = [ rslt.remove ]), 
20051                            $.each(rslt.remove.sort(function(a, b) {
20052                                return b - a;
20053                            }), function(ndx, lmnt) {
20054                                stripValidPositions(lmnt, lmnt + 1, !0);
20055                            })), rslt.insert !== undefined && ($.isArray(rslt.insert) || (rslt.insert = [ rslt.insert ]), 
20056                            $.each(rslt.insert.sort(function(a, b) {
20057                                return a - b;
20058                            }), function(ndx, lmnt) {
20059                                isValid(lmnt.pos, lmnt.c, !0, fromSetValid);
20060                            })), rslt.refreshFromBuffer) {
20061                                var refresh = rslt.refreshFromBuffer;
20062                                if (refreshFromBuffer(!0 === refresh ? refresh : refresh.start, refresh.end, possibleModifiedBuffer), 
20063                                rslt.pos === undefined && rslt.c === undefined) return rslt.pos = getLastValidPosition(), 
20064                                !1;
20065                                if ((validatedPos = rslt.pos !== undefined ? rslt.pos : position) !== position) return rslt = $.extend(rslt, isValid(validatedPos, elem, !0, fromSetValid)), 
20066                                !1;
20067                            } else if (!0 !== rslt && rslt.pos !== undefined && rslt.pos !== position && (validatedPos = rslt.pos, 
20068                            refreshFromBuffer(position, validatedPos, getBuffer().slice()), validatedPos !== position)) return rslt = $.extend(rslt, isValid(validatedPos, elem, !0)), 
20069                            !1;
20070                            return (!0 === rslt || rslt.pos !== undefined || rslt.c !== undefined) && (ndx > 0 && resetMaskSet(!0), 
20071                            setValidPosition(validatedPos, $.extend({}, tst, {
20072                                input: casing(elem, test, validatedPos)
20073                            }), fromSetValid, isSelection(pos)) || (rslt = !1), !1);
20074                        }
20075                    }), rslt;
20076                }
20077                function setValidPosition(pos, validTest, fromSetValid, isSelection) {
20078                    if (isSelection || opts.insertMode && getMaskSet().validPositions[pos] !== undefined && fromSetValid === undefined) {
20079                        var i, positionsClone = $.extend(!0, {}, getMaskSet().validPositions), lvp = getLastValidPosition(undefined, !0);
20080                        for (i = pos; i <= lvp; i++) delete getMaskSet().validPositions[i];
20081                        getMaskSet().validPositions[pos] = $.extend(!0, {}, validTest);
20082                        var j, valid = !0, vps = getMaskSet().validPositions, needsValidation = !1, initialLength = getMaskSet().maskLength;
20083                        for (i = j = pos; i <= lvp; i++) {
20084                            var t = positionsClone[i];
20085                            if (t !== undefined) for (var posMatch = j; posMatch < getMaskSet().maskLength && (null === t.match.fn && vps[i] && (!0 === vps[i].match.optionalQuantifier || !0 === vps[i].match.optionality) || null != t.match.fn); ) {
20086                                if (posMatch++, !1 === needsValidation && positionsClone[posMatch] && positionsClone[posMatch].match.def === t.match.def) getMaskSet().validPositions[posMatch] = $.extend(!0, {}, positionsClone[posMatch]), 
20087                                getMaskSet().validPositions[posMatch].input = t.input, fillMissingNonMask(posMatch), 
20088                                j = posMatch, valid = !0; else if (positionCanMatchDefinition(posMatch, t.match.def)) {
20089                                    var result = isValid(posMatch, t.input, !0, !0);
20090                                    valid = !1 !== result, j = result.caret || result.insert ? getLastValidPosition() : posMatch, 
20091                                    needsValidation = !0;
20092                                } else if (!(valid = !0 === t.generatedInput) && posMatch >= getMaskSet().maskLength - 1) break;
20093                                if (getMaskSet().maskLength < initialLength && (getMaskSet().maskLength = initialLength), 
20094                                valid) break;
20095                            }
20096                            if (!valid) break;
20097                        }
20098                        if (!valid) return getMaskSet().validPositions = $.extend(!0, {}, positionsClone), 
20099                        resetMaskSet(!0), !1;
20100                    } else getMaskSet().validPositions[pos] = $.extend(!0, {}, validTest);
20101                    return resetMaskSet(!0), !0;
20102                }
20103                function fillMissingNonMask(maskPos) {
20104                    for (var pndx = maskPos - 1; pndx > -1 && !getMaskSet().validPositions[pndx]; pndx--) ;
20105                    var testTemplate, testsFromPos;
20106                    for (pndx++;
20106 pndx < maskPos; pndx++) getMaskSet().validPositions[pndx] === undefined && (!1 === opts.jitMasking || opts.jitMasking > pndx) && ("" === (testsFromPos = getTests(pndx, getTestTemplate(pndx - 1).locator, pndx - 1).slice())[testsFromPos.length - 1].match.def && testsFromPos.pop(), 
20107                    (testTemplate = determineTestTemplate(testsFromPos)) && (testTemplate.match.def === opts.radixPointDefinitionSymbol || !isMask(pndx, !0) || $.inArray(opts.radixPoint, getBuffer()) < pndx && testTemplate.match.fn && testTemplate.match.fn.test(getPlaceholder(pndx), getMaskSet(), pndx, !1, opts)) && !1 !== (result = _isValid(pndx, getPlaceholder(pndx, testTemplate.match, !0) || (null == testTemplate.match.fn ? testTemplate.match.def : "" !== getPlaceholder(pndx) ? getPlaceholder(pndx) : getBuffer()[pndx]), !0)) && (getMaskSet().validPositions[result.pos || pndx].generatedInput = !0));
20108                }
20109                strict = !0 === strict;
20110                var maskPos = pos;
20111                pos.begin !== undefined && (maskPos = isRTL && !isSelection(pos) ? pos.end : pos.begin);
20112                var result = !0, positionsClone = $.extend(!0, {}, getMaskSet().validPositions);
20113                if ($.isFunction(opts.preValidation) && !strict && !0 !== fromSetValid && !0 !== validateOnly && (result = opts.preValidation(getBuffer(), maskPos, c, isSelection(pos), opts)), 
20114                !0 === result) {
20115                    if (fillMissingNonMask(maskPos), isSelection(pos) && (handleRemove(undefined, Inputmask.keyCode.DELETE, pos, !0, !0), 
20116                    maskPos = getMaskSet().p), maskPos < getMaskSet().maskLength && (maxLength === undefined || maskPos < maxLength) && (result = _isValid(maskPos, c, strict), 
20117                    (!strict || !0 === fromSetValid) && !1 === result && !0 !== validateOnly)) {
20118                        var currentPosValid = getMaskSet().validPositions[maskPos];
20119                        if (!currentPosValid || null !== currentPosValid.match.fn || currentPosValid.match.def !== c && c !== opts.skipOptionalPartCharacter) {
20120                            if ((opts.insertMode || getMaskSet().validPositions[seekNext(maskPos)] === undefined) && !isMask(maskPos, !0)) for (var nPos = maskPos + 1, snPos = seekNext(maskPos); nPos <= snPos; nPos++) if (!1 !== (result = _isValid(nPos, c, strict))) {
20121                                !function(originalPos, newPos) {
20122                                    var vp = getMaskSet().validPositions[newPos];
20123                                    if (vp) for (var targetLocator = vp.locator, tll = targetLocator.length, ps = originalPos; ps < newPos; ps++) if (getMaskSet().validPositions[ps] === undefined && !isMask(ps, !0)) {
20124                                        var tests = getTests(ps).slice(), bestMatch = determineTestTemplate(tests, !0), equality = -1;
20125                                        "" === tests[tests.length - 1].match.def && tests.pop(), $.each(tests, function(ndx, tst) {
20126                                            for (var i = 0; i < tll; i++) {
20127                                                if (tst.locator[i] === undefined || !checkAlternationMatch(tst.locator[i].toString().split(","), targetLocator[i].toString().split(","), tst.na)) {
20128                                                    var targetAI = targetLocator[i], bestMatchAI = bestMatch.locator[i], tstAI = tst.locator[i];
20129                                                    targetAI - bestMatchAI > Math.abs(targetAI - tstAI) && (bestMatch = tst);
20130                                                    break;
20131                                                }
20132                                                equality < i && (equality = i, bestMatch = tst);
20133                                            }
20134                                        }), (bestMatch = $.extend({}, bestMatch, {
20135                                            input: getPlaceholder(ps, bestMatch.match, !0) || bestMatch.match.def
20136                                        })).generatedInput = !0, setValidPosition(ps, bestMatch, !0), getMaskSet().validPositions[newPos] = undefined, 
20137                                        _isValid(newPos, vp.input, !0);
20138                                    }
20139                                }(maskPos, result.pos !== undefined ? result.pos : nPos), maskPos = nPos;
20140                                break;
20141                            }
20142                        } else result = {
20143                            caret: seekNext(maskPos)
20144                        };
20145                    }
20146                    !1 === result && opts.keepStatic && !strict && !0 !== fromAlternate && (result = function(pos, c, strict) {
20147                        var lastAlt, alternation, altPos, prevAltPos, i, validPos, altNdxs, decisionPos, validPsClone = $.extend(!0, {}, getMaskSet().validPositions), isValidRslt = !1, lAltPos = getLastValidPosition();
20148                        for (prevAltPos = getMaskSet().validPositions[lAltPos]; lAltPos >= 0; lAltPos--) if ((altPos = getMaskSet().validPositions[lAltPos]) && altPos.alternation !== undefined) {
20149                            if (lastAlt = lAltPos, alternation = getMaskSet().validPositions[lastAlt].alternation, 
20150                            prevAltPos.locator[altPos.alternation] !== altPos.locator[altPos.alternation]) break;
20151                            prevAltPos = altPos;
20152                        }
20153                        if (alternation !== undefined) {
20154                            decisionPos = parseInt(lastAlt);
20155                            var decisionTaker = prevAltPos.locator[prevAltPos.alternation || alternation] !== undefined ? prevAltPos.locator[prevAltPos.alternation || alternation] : altNdxs[0];
20156                            decisionTaker.length > 0 && (decisionTaker = decisionTaker.split(",")[0]);
20157                            var possibilityPos = getMaskSet().validPositions[decisionPos], prevPos = getMaskSet().validPositions[decisionPos - 1];
20158                            $.each(getTests(decisionPos, prevPos ? prevPos.locator : undefined, decisionPos - 1), function(ndx, test) {
20159                                altNdxs = test.locator[alternation] ? test.locator[alternation].toString().split(",") : [];
20160                                for (var mndx = 0; mndx < altNdxs.length; mndx++) {
20161                                    var validInputs = [], staticInputsBeforePos = 0, staticInputsBeforePosAlternate = 0, verifyValidInput = !1;
20162                                    if (decisionTaker < altNdxs[mndx] && (test.na === undefined || -1 === $.inArray(altNdxs[mndx], test.na.split(",")) || -1 === $.inArray(decisionTaker.toString(), altNdxs))) {
20163                                        getMaskSet().validPositions[decisionPos] = $.extend(!0, {}, test);
20164                                        var possibilities = getMaskSet().validPositions[decisionPos].locator;
20165                                        for (getMaskSet().validPositions[decisionPos].locator[alternation] = parseInt(altNdxs[mndx]), 
20166                                        null == test.match.fn ? (possibilityPos.input !== test.match.def && (verifyValidInput = !0, 
20167                                        !0 !== possibilityPos.generatedInput && validInputs.push(possibilityPos.input)), 
20168                                        staticInputsBeforePosAlternate++, getMaskSet().validPositions[decisionPos].generatedInput = !/[0-9a-bA-Z]/.test(test.match.def), 
20169                                        getMaskSet().validPositions[decisionPos].input = test.match.def) : getMaskSet().validPositions[decisionPos].input = possibilityPos.input, 
20170                                        i = decisionPos + 1; i < getLastValidPosition(undefined, !0) + 1; i++) (validPos = getMaskSet().validPositions[i]) && !0 !== validPos.generatedInput && /[0-9a-bA-Z]/.test(validPos.input) ? validInputs.push(validPos.input) : i < pos && staticInputsBeforePos++, 
20171                                        delete getMaskSet().validPositions[i];
20172                                        for (verifyValidInput && validInputs[0] === test.match.def && validInputs.shift(), 
20173                                        resetMaskSet(!0), isValidRslt = !0; validInputs.length > 0; ) {
20174                                            var input = validInputs.shift();
20175                                            if (input !== opts.skipOptionalPartCharacter && !(isValidRslt = isValid(getLastValidPosition(undefined, !0) + 1, input, !1, fromSetValid, !0))) break;
20176                                        }
20177                                        if (isValidRslt) {
20178                                            getMaskSet().validPositions[decisionPos].locator = possibilities;
20179                                            var targetLvp = getLastValidPosition(pos) + 1;
20180                                            for (i = decisionPos + 1; i < getLastValidPosition() + 1; i++) ((validPos = getMaskSet().validPositions[i]) === undefined || null == validPos.match.fn) && i < pos + (staticInputsBeforePosAlternate - staticInputsBeforePos) && staticInputsBeforePosAlternate++;
20181                                            isValidRslt = isValid((pos += staticInputsBeforePosAlternate - staticInputsBeforePos) > targetLvp ? targetLvp : pos, c, strict, fromSetValid, !0);
20182                                        }
20183                                        if (isValidRslt) return !1;
20184                                        resetMaskSet(), getMaskSet().validPositions = $.extend(!0, {}, validPsClone);
20185                                    }
20186                                }
20187                            });
20188                        }
20189                        return isValidRslt;
20190                    }(maskPos, c, strict)), !0 === result && (result = {
20191                        pos: maskPos
20192                    });
20193                }
20194                if ($.isFunction(opts.postValidation) && !1 !== result && !strict && !0 !== fromSetValid && !0 !== validateOnly) {
20195                    var postResult = opts.postValidation(getBuffer(!0), result, opts);
20196                    if (postResult.refreshFromBuffer && postResult.buffer) {
20197                        var refresh = postResult.refreshFromBuffer;
20198                        refreshFromBuffer(!0 === refresh ? refresh : refresh.start, refresh.end, postResult.buffer);
20199                    }
20200                    result = !0 === postResult ? result : postResult;
20201                }
20202                return result && result.pos === undefined && (result.pos = maskPos), !1 !== result && !0 !== validateOnly || (resetMaskSet(!0), 
20203                getMaskSet().validPositions = $.extend(!0, {}, positionsClone)), result;
20204            }
20205            function isMask(pos, strict) {
20206                var test = getTestTemplate(pos).match;
20207                if ("" === test.def && (test = getTest(pos).match), null != test.fn) return test.fn;
20208                if (!0 !== strict && pos > -1) {
20209                    var tests = getTests(pos);
20210                    return tests.length > 1 + ("" === tests[tests.length - 1].match.def ? 1 : 0);
20211                }
20212                return !1;
20213            }
20214            function seekNext(pos, newBlock) {
20215                var maskL = getMaskSet().maskLength;
20216                if (pos >= maskL) return maskL;
20217                var position = pos;
20218                for (getTests(maskL + 1).length > 1 && (getMaskTemplate(!0, maskL + 1, !0), maskL = getMaskSet().maskLength); ++position < maskL && (!0 === newBlock && (!0 !== getTest(position).match.newBlockMarker || !isMask(position)) || !0 !== newBlock && !isMask(position)); ) ;
20219                return position;
20220            }
20221            function seekPrevious(pos, newBlock) {
20222                var tests, position = pos;
20223                if (position <= 0) return 0;
20224                for (;
20224--position > 0 && (!0 === newBlock && !0 !== getTest(position).match.newBlockMarker || !0 !== newBlock && !isMask(position) && ((tests = getTests(position)).length < 2 || 2 === tests.length && "" === tests[1].match.def)); ) ;
20225                return position;
20226            }
20227            function getBufferElement(position) {
20228                return getMaskSet().validPositions[position] === undefined ? getPlaceholder(position) : getMaskSet().validPositions[position].input;
20229            }
20230            function writeBuffer(input, buffer, caretPos, event, triggerInputEvent) {
20231                if (event && $.isFunction(opts.onBeforeWrite)) {
20232                    var result = opts.onBeforeWrite.call(inputmask, event, buffer, caretPos, opts);
20233                    if (result) {
20234                        if (result.refreshFromBuffer) {
20235                            var refresh = result.refreshFromBuffer;
20236                            refreshFromBuffer(!0 === refresh ? refresh : refresh.start, refresh.end, result.buffer || buffer), 
20237                            buffer = getBuffer(!0);
20238                        }
20239                        caretPos !== undefined && (caretPos = result.caret !== undefined ? result.caret : caretPos);
20240                    }
20241                }
20242                input !== undefined && (input.inputmask._valueSet(buffer.join("")), caretPos === undefined || event !== undefined && "blur" === event.type ? renderColorMask(input, caretPos, 0 === buffer.length) : android && event && "input" === event.type ? setTimeout(function() {
20243                    caret(input, caretPos);
20244                }, 0) : caret(input, caretPos), !0 === triggerInputEvent && (skipInputEvent = !0, 
20245                $(input).trigger("input")));
20246            }
20247            function getPlaceholder(pos, test, returnPL) {
20248                if ((test = test || getTest(pos).match).placeholder !== undefined || !0 === returnPL) return $.isFunction(test.placeholder) ? test.placeholder(opts) : test.placeholder;
20249                if (null === test.fn) {
20250                    if (pos > -1 && getMaskSet().validPositions[pos] === undefined) {
20251                        var prevTest, tests = getTests(pos), staticAlternations = [];
20252                        if (tests.length > 1 + ("" === tests[tests.length - 1].match.def ? 1 : 0)) for (var i = 0; i < tests.length; i++) if (!0 !== tests[i].match.optionality && !0 !== tests[i].match.optionalQuantifier && (null === tests[i].match.fn || prevTest === undefined || !1 !== tests[i].match.fn.test(prevTest.match.def, getMaskSet(), pos, !0, opts)) && (staticAlternations.push(tests[i]), 
20253                        null === tests[i].match.fn && (prevTest = tests[i]), staticAlternations.length > 1 && /[0-9a-bA-Z]/.test(staticAlternations[0].match.def))) return opts.placeholder.charAt(pos % opts.placeholder.length);
20254                    }
20255                    return test.def;
20256                }
20257                return opts.placeholder.charAt(pos % opts.placeholder.length);
20258            }
20259            function checkVal(input, writeOut, strict, nptvl, initiatingEvent) {
20260                function isTemplateMatch(ndx, charCodes) {
20261                    return -1 !== getBufferTemplate().slice(ndx, seekNext(ndx)).join("").indexOf(charCodes) && !isMask(ndx) && getTest(ndx).match.nativeDef === charCodes.charAt(charCodes.length - 1);
20262                }
20263                var inputValue = nptvl.slice(), charCodes = "", initialNdx = -1, result = undefined;
20264                if (resetMaskSet(), strict || !0 === opts.autoUnmask) initialNdx = seekNext(initialNdx); else {
20265                    var staticInput = getBufferTemplate().slice(0, seekNext(-1)).join(""), matches = inputValue.join("").match(new RegExp("^" + Inputmask.escapeRegex(staticInput), "g"));
20266                    matches && matches.length > 0 && (inputValue.splice(0, matches.length * staticInput.length), 
20267                    initialNdx = seekNext(initialNdx));
20268                }
20269                if (-1 === initialNdx ? (getMaskSet().p = seekNext(initialNdx), initialNdx = 0) : getMaskSet().p = initialNdx, 
20270                $.each(inputValue, function(ndx, charCode) {
20271                    if (charCode !== undefined) if (getMaskSet().validPositions[ndx] === undefined && inputValue[ndx] === getPlaceholder(ndx) && isMask(ndx, !0) && !1 === isValid(ndx, inputValue[ndx], !0, undefined, undefined, !0)) getMaskSet().p++; else {
20272                        var keypress = new $.Event("_checkval");
20273                        keypress.which = charCode.charCodeAt(0), charCodes += charCode;
20274                        var lvp = getLastValidPosition(undefined, !0), lvTest = getMaskSet().validPositions[lvp], nextTest = getTestTemplate(lvp + 1, lvTest ? lvTest.locator.slice() : undefined, lvp);
20275                        if (!isTemplateMatch(initialNdx, charCodes) || strict || opts.autoUnmask) {
20276                            var pos = strict ? ndx : null == nextTest.match.fn && nextTest.match.optionality && lvp + 1 < getMaskSet().p ? lvp + 1 : getMaskSet().p;
20277                            result = EventHandlers.keypressEvent.call(input, keypress, !0, !1, strict, pos), 
20278                            initialNdx = pos + 1, charCodes = "";
20279                        } else result = EventHandlers.keypressEvent.call(input, keypress, !0, !1, !0, lvp + 1);
20280                        if (!1 !== result && !strict && $.isFunction(opts.onBeforeWrite)) {
20281                            var origResult = result;
20282                            if (result = opts.onBeforeWrite.call(inputmask, keypress, getBuffer(), result.forwardPosition, opts), 
20283                            (result = $.extend(origResult, result)) && result.refreshFromBuffer) {
20284                                var refresh = result.refreshFromBuffer;
20285                                refreshFromBuffer(!0 === refresh ? refresh : refresh.start, refresh.end, result.buffer), 
20286                                resetMaskSet(!0), result.caret && (getMaskSet().p = result.caret, result.forwardPosition = result.caret);
20287                            }
20288                        }
20289                    }
20290                }), writeOut) {
20291                    var caretPos = undefined;
20292                    document.activeElement === input && result && (caretPos = opts.numericInput ? seekPrevious(result.forwardPosition) : result.forwardPosition), 
20293                    writeBuffer(input, getBuffer(), caretPos, initiatingEvent || new $.Event("checkval"), initiatingEvent && "input" === initiatingEvent.type);
20294                }
20295            }
20296            function unmaskedvalue(input) {
20297                if (input) {
20298                    if (input.inputmask === undefined) return input.value;
20299                    input.inputmask && input.inputmask.refreshValue && EventHandlers.setValueEvent.call(input);
20300                }
20301                var umValue = [], vps = getMaskSet().validPositions;
20302                for (var pndx in vps) vps[pndx].match && null != vps[pndx].match.fn && umValue.push(vps[pndx].input);
20303                var unmaskedValue = 0 === umValue.length ? "" : (isRTL ? umValue.reverse() : umValue).join("");
20304                if ($.isFunction(opts.onUnMask)) {
20305                    var bufferValue = (isRTL ? getBuffer().slice().reverse() : getBuffer()).join("");
20306                    unmaskedValue = opts.onUnMask.call(inputmask, bufferValue, unmaskedValue, opts);
20307                }
20308                return unmaskedValue;
20309            }
20310            function caret(input, begin, end, notranslate) {
20311                function translatePosition(pos) {
20312                    return !0 === notranslate || !isRTL || "number" != typeof pos || opts.greedy && "" === opts.placeholder || (pos = getBuffer().join("").length - pos), 
20313                    pos;
20314                }
20315                var range;
20316                if (begin === undefined) return input.setSelectionRange ? (begin = input.selectionStart, 
20317                end = input.selectionEnd) : window.getSelection ? (range = window.getSelection().getRangeAt(0)).commonAncestorContainer.parentNode !== input && range.commonAncestorContainer !== input || (begin = range.startOffset, 
20318                end = range.endOffset) : document.selection && document.selection.createRange && (end = (begin = 0 - (range = document.selection.createRange()).duplicate().moveStart("character", -input.inputmask._valueGet().length)) + range.text.length), 
20319                {
20320                    begin: translatePosition(begin),
20321                    end: translatePosition(end)
20322                };
20323                if (begin.begin !== undefined && (end = begin.end, begin = begin.begin), "number" == typeof begin) {
20324                    begin = translatePosition(begin), end = "number" == typeof (end = translatePosition(end)) ? end : begin;
20325                    var scrollCalc = parseInt(((input.ownerDocument.defaultView || window).getComputedStyle ? (input.ownerDocument.defaultView || window).getComputedStyle(input, null) : input.currentStyle).fontSize) * end;
20326                    if (input.scrollLeft = scrollCalc > input.scrollWidth ? scrollCalc : 0, mobile || !1 !== opts.insertMode || begin !== end || end++, 
20327                    input.setSelectionRange) input.selectionStart = begin, input.selectionEnd = end; else if (window.getSelection) {
20328                        if (range = document.createRange(), input.firstChild === undefined || null === input.firstChild) {
20329                            var textNode = document.createTextNode("");
20330                            input.appendChild(textNode);
20331                        }
20332                        range.setStart(input.firstChild, begin < input.inputmask._valueGet().length ? begin : input.inputmask._valueGet().length), 
20333                        range.setEnd(input.firstChild, end < input.inputmask._valueGet().length ? end : input.inputmask._valueGet().length), 
20334                        range.collapse(!0);
20335                        var sel = window.getSelection();
20336                        sel.removeAllRanges(), sel.addRange(range);
20337                    } else input.createTextRange && ((range = input.createTextRange()).collapse(!0), 
20338                    range.moveEnd("character", end), range.moveStart("character", begin), range.select());
20339                    renderColorMask(input, {
20340                        begin: begin,
20341                        end: end
20342                    });
20343                }
20344            }
20345            function determineLastRequiredPosition(returnDefinition) {
20346                var pos, testPos, buffer = getBuffer(), bl = buffer.length, lvp = getLastValidPosition(), positions = {}, lvTest = getMaskSet().validPositions[lvp], ndxIntlzr = lvTest !== undefined ? lvTest.locator.slice() : undefined;
20347                for (pos = lvp + 1; pos < buffer.length; pos++) ndxIntlzr = (testPos = getTestTemplate(pos, ndxIntlzr, pos - 1)).locator.slice(), 
20348                positions[pos] = $.extend(!0, {}, testPos);
20349                var lvTestAlt = lvTest && lvTest.alternation !== undefined ? lvTest.locator[lvTest.alternation] : undefined;
20350                for (pos = bl - 1; pos > lvp && (((testPos = positions[pos]).match.optionality || testPos.match.optionalQuantifier && testPos.match.newBlockMarker || lvTestAlt && (lvTestAlt !== positions[pos].locator[lvTest.alternation] && null != testPos.match.fn || null === testPos.match.fn && testPos.locator[lvTest.alternation] && checkAlternationMatch(testPos.locator[lvTest.alternation].toString().split(","), lvTestAlt.toString().split(",")) && "" !== getTests(pos)[0].def)) && buffer[pos] === getPlaceholder(pos, testPos.match)); pos--) bl--;
20351                return returnDefinition ? {
20352                    l: bl,
20353                    def: positions[bl] ? positions[bl].match : undefined
20354                } : bl;
20355            }
20356            function clearOptionalTail(buffer) {
20357                for (var validPos, rl = determineLastRequiredPosition(), bl = buffer.length, lv = getMaskSet().validPositions[getLastValidPosition()]; rl < bl && !isMask(rl, !0) && (validPos = lv !== undefined ? getTestTemplate(rl, lv.locator.slice(""), lv) : getTest(rl)) && !0 !== validPos.match.optionality && (!0 !== validPos.match.optionalQuantifier && !0 !== validPos.match.newBlockMarker || rl + 1 === bl && "" === (lv !== undefined ? getTestTemplate(rl + 1, lv.locator.slice(""), lv) : getTest(rl + 1)).match.def); ) rl++;
20358                for (;(validPos = getMaskSet().validPositions[rl - 1]) && validPos && validPos.match.optionality && validPos.input === opts.skipOptionalPartCharacter; ) rl--;
20359                return buffer.splice(rl), buffer;
20360            }
20361            function isComplete(buffer) {
20362                if ($.isFunction(opts.isComplete)) return opts.isComplete(buffer, opts);
20363                if ("*" === opts.repeat) return undefined;
20364                var complete = !1, lrp = determineLastRequiredPosition(!0), aml = seekPrevious(lrp.l);
20365                if (lrp.def === undefined || lrp.def.newBlockMarker || lrp.def.optionality || lrp.def.optionalQuantifier) {
20366                    complete = !0;
20367                    for (var i = 0; i <= aml; i++) {
20368                        var test = getTestTemplate(i).match;
20369                        if (null !== test.fn && getMaskSet().validPositions[i] === undefined && !0 !== test.optionality && !0 !== test.optionalQuantifier || null === test.fn && buffer[i] !== getPlaceholder(i, test)) {
20370                            complete = !1;
20371                            break;
20372                        }
20373                    }
20374                }
20375                return complete;
20376            }
20377            function handleRemove(input, k, pos, strict, fromIsValid) {
20378                if ((opts.numericInput || isRTL) && (k === Inputmask.keyCode.BACKSPACE ? k = Inputmask.keyCode.DELETE : k === Inputmask.keyCode.DELETE && (k = Inputmask.keyCode.BACKSPACE), 
20379                isRTL)) {
20380                    var pend = pos.end;
20381                    pos.end = pos.begin, pos.begin = pend;
20382                }
20383                k === Inputmask.keyCode.BACKSPACE && (pos.end - pos.begin < 1 || !1 === opts.insertMode) ? (pos.begin = seekPrevious(pos.begin), 
20384                getMaskSet().validPositions[pos.begin] !== undefined && getMaskSet().validPositions[pos.begin].input === opts.groupSeparator && pos.begin--) : k === Inputmask.keyCode.DELETE && pos.begin === pos.end && (pos.end = isMask(pos.end, !0) && getMaskSet().validPositions[pos.end] && getMaskSet().validPositions[pos.end].input !== opts.radixPoint ? pos.end + 1 : seekNext(pos.end) + 1, 
20385                getMaskSet().validPositions[pos.begin] !== undefined && getMaskSet().validPositions[pos.begin].input === opts.groupSeparator && pos.end++), 
20386                stripValidPositions(pos.begin, pos.end, !1, strict), !0 !== strict && function() {
20387                    if (opts.keepStatic) {
20388                        for (var validInputs = [], lastAlt = getLastValidPosition(-1, !0), positionsClone = $.extend(!0, {}, getMaskSet().validPositions), prevAltPos = getMaskSet().validPositions[lastAlt]; lastAlt >= 0; lastAlt--) {
20389                            var altPos = getMaskSet().validPositions[lastAlt];
20390                            if (altPos) {
20391                                if (!0 !== altPos.generatedInput && /[0-9a-bA-Z]/.test(altPos.input) && validInputs.push(altPos.input), 
20392                                delete getMaskSet().validPositions[lastAlt], altPos.alternation !== undefined && altPos.locator[altPos.alternation] !== prevAltPos.locator[altPos.alternation]) break;
20393                                prevAltPos = altPos;
20394                            }
20395                        }
20396                        if (lastAlt > -1) for (getMaskSet().p = seekNext(getLastValidPosition(-1, !0)); validInputs.length > 0; ) {
20397                            var keypress = new $.Event("keypress");
20398                            keypress.which = validInputs.pop().charCodeAt(0), EventHandlers.keypressEvent.call(input, keypress, !0, !1, !1, getMaskSet().p);
20399                        } else getMaskSet().validPositions = $.extend(!0, {}, positionsClone);
20400                    }
20401                }();
20402                var lvp = getLastValidPosition(pos.begin, !0);
20403                if (lvp < pos.begin) getMaskSet().p = seekNext(lvp); else if (!0 !== strict && (getMaskSet().p = pos.begin, 
20404                !0 !== fromIsValid)) for (;getMaskSet().p < lvp && getMaskSet().validPositions[getMaskSet().p] === undefined; ) getMaskSet().p++;
20405            }
20406            function initializeColorMask(input) {
20407                function findCaretPos(clientx) {
20408                    var caretPos, e = document.createElement("span");
20409                    for (var style in computedStyle) isNaN(style) && -1 !== style.indexOf("font") && (e.style[style] = computedStyle[style]);
20410                    e.style.textTransform = computedStyle.textTransform, e.style.letterSpacing = computedStyle.letterSpacing, 
20411                    e.style.position = "absolute", e.style.height = "auto", e.style.width = "auto", 
20412                    e.style.visibility = "hidden", e.style.whiteSpace = "nowrap", document.body.appendChild(e);
20413                    var itl, inputText = input.inputmask._valueGet(), previousWidth = 0;
20414                    for (caretPos = 0, itl = inputText.length; caretPos <= itl; caretPos++) {
20415                        if (e.innerHTML += inputText.charAt(caretPos) || "_", e.offsetWidth >= clientx) {
20416                            var offset1 = clientx - previousWidth, offset2 = e.offsetWidth - clientx;
20417                            e.innerHTML = inputText.charAt(caretPos), caretPos = (offset1 -= e.offsetWidth / 3) < offset2 ? caretPos - 1 : caretPos;
20418                            break;
20419                        }
20420                        previousWidth = e.offsetWidth;
20421                    }
20422                    return document.body.removeChild(e), caretPos;
20423                }
20424                var computedStyle = (input.ownerDocument.defaultView || window).getComputedStyle(input, null), template = document.createElement("div");
20425                template.style.width = computedStyle.width, template.style.textAlign = computedStyle.textAlign, 
20426                (colorMask = document.createElement("div")).className = "im-colormask", input.parentNode.insertBefore(colorMask, input), 
20427                input.parentNode.removeChild(input), colorMask.appendChild(template), colorMask.appendChild(input), 
20428                input.style.left = template.offsetLeft + "px", $(input).on("click", function(e) {
20429                    return caret(input, findCaretPos(e.clientX)), EventHandlers.clickEvent.call(input, [ e ]);
20430                }), $(input).on("keydown", function(e) {
20431                    e.shiftKey || !1 === opts.insertMode || setTimeout(function() {
20432                        renderColorMask(input);
20433                    }, 0);
20434                });
20435            }
20436            function renderColorMask(input, caretPos, clear) {
20437                function handleStatic() {
20438                    isStatic || null !== test.fn && testPos.input !== undefined ? isStatic && (null !== test.fn && testPos.input !== undefined || "" === test.def) && (isStatic = !1, 
20439                    maskTemplate += "</span>") : (isStatic = !0, maskTemplate += "<span class='im-static'>");
20440                }
20441                function handleCaret(force) {
20442                    !0 !== force && pos !== caretPos.begin || document.activeElement !== input || (maskTemplate += "<span class='im-caret' style='border-right-width: 1px;border-right-style: solid;'></span>");
20443                }
20444                var test, testPos, ndxIntlzr, maskTemplate = "", isStatic = !1, pos = 0;
20445                if (colorMask !== undefined) {
20446                    var buffer = getBuffer();
20447                    if (caretPos === undefined ? caretPos = caret(input) : caretPos.begin === undefined && (caretPos = {
20448                        begin: caretPos,
20449                        end: caretPos
20450                    }), !0 !== clear) {
20451                        var lvp = getLastValidPosition();
20452                        do {
20453                            handleCaret(), getMaskSet().validPositions[pos] ? (testPos = getMaskSet().validPositions[pos], 
20454                            test = testPos.match, ndxIntlzr = testPos.locator.slice(), handleStatic(), maskTemplate += buffer[pos]) : (testPos = getTestTemplate(pos, ndxIntlzr, pos - 1), 
20455                            test = testPos.match, ndxIntlzr = testPos.locator.slice(), (!1 === opts.jitMasking || pos < lvp || "number" == typeof opts.jitMasking && isFinite(opts.jitMasking) && opts.jitMasking > pos) && (handleStatic(), 
20456                            maskTemplate += getPlaceholder(pos, test))), pos++;
20457                        } while ((maxLength === undefined || pos < maxLength) && (null !== test.fn || "" !== test.def) || lvp > pos || isStatic);
20458                        -1 === maskTemplate.indexOf("im-caret") && handleCaret(!0), isStatic && handleStatic();
20459                    }
20460                    var template = colorMask.getElementsByTagName("div")[0];
20461                    template.innerHTML = maskTemplate, input.inputmask.positionColorMask(input, template);
20462                }
20463            }
20464            maskset = maskset || this.maskset, opts = opts || this.opts;
20465            var undoValue, $el, maxLength, colorMask, inputmask = this, el = this.el, isRTL = this.isRTL, skipKeyPressEvent = !1, skipInputEvent = !1, ignorable = !1, mouseEnter = !1, EventRuler = {
20466                on: function(input, eventName, eventHandler) {
20467                    var ev = function(e) {
20468                        if (this.inputmask === undefined && "FORM" !== this.nodeName) {
20469                            var imOpts = $.data(this, "_inputmask_opts");
20470                            imOpts ? new Inputmask(imOpts).mask(this) : EventRuler.off(this);
20471                        } else {
20472                            if ("setvalue" === e.type || "FORM" === this.nodeName || !(this.disabled || this.readOnly && !("keydown" === e.type && e.ctrlKey && 67 === e.keyCode || !1 === opts.tabThrough && e.keyCode === Inputmask.keyCode.TAB))) {
20473                                switch (e.type) {
20474                                  case "input":
20475                                    if (!0 === skipInputEvent) return skipInputEvent = !1, e.preventDefault();
20476                                    break;
20477
20478                                  case "keydown":
20479                                    skipKeyPressEvent = !1, skipInputEvent = !1;
20480                                    break;
20481
20482                                  case "keypress":
20483                                    if (!0 === skipKeyPressEvent) return e.preventDefault();
20484                                    skipKeyPressEvent = !0;
20485                                    break;
20486
20487                                  case "click":
20488                                    if (iemobile || iphone) {
20489                                        var that = this, args = arguments;
20490                                        return setTimeout(function() {
20491                                            eventHandler.apply(that, args);
20492                                        }, 0), !1;
20493                                    }
20494                                }
20495                                var returnVal = eventHandler.apply(this, arguments);
20496                                return !1 === returnVal && (e.preventDefault(), e.stopPropagation()), returnVal;
20497                            }
20498                            e.preventDefault();
20499                        }
20500                    };
20501                    input.inputmask.events[eventName] = input.inputmask.events[eventName] || [], input.inputmask.events[eventName].push(ev), 
20502                    -1 !== $.inArray(eventName, [ "submit", "reset" ]) ? null !== input.form && $(input.form).on(eventName, ev) : $(input).on(eventName, ev);
20503                },
20504                off: function(input, event) {
20505                    if (input.inputmask && input.inputmask.events) {
20506                        var events;
20507                        event ? (events = [])[event] = input.inputmask.events[event] : events = input.inputmask.events, 
20508                        $.each(events, function(eventName, evArr) {
20509                            for (;evArr.length > 0; ) {
20510                                var ev = evArr.pop();
20511                                -1 !== $.inArray(eventName, [ "submit", "reset" ]) ? null !== input.form && $(input.form).off(eventName, ev) : $(input).off(eventName, ev);
20512                            }
20513                            delete input.inputmask.events[eventName];
20514                        });
20515                    }
20516                }
20517            }, EventHandlers = {
20518                keydownEvent: function(e) {
20519                    var input = this, $input = $(input), k = e.keyCode, pos = caret(input);
20520                    if (k === Inputmask.keyCode.BACKSPACE || k === Inputmask.keyCode.DELETE || iphone && k === Inputmask.keyCode.BACKSPACE_SAFARI || e.ctrlKey && k === Inputmask.keyCode.X && !function(eventName) {
20521                        var el = document.createElement("input"), evName = "on" + eventName, isSupported = evName in el;
20522                        return isSupported || (el.setAttribute(evName, "return;"), isSupported = "function" == typeof el[evName]), 
20523                        el = null, isSupported;
20524                    }("cut")) e.preventDefault(), handleRemove(input, k, pos), writeBuffer(input, getBuffer(!0), getMaskSet().p, e, input.inputmask._valueGet() !== getBuffer().join("")), 
20525                    input.inputmask._valueGet() === getBufferTemplate().join("") ? $input.trigger("cleared") : !0 === isComplete(getBuffer()) && $input.trigger("complete"); else if (k === Inputmask.keyCode.END || k === Inputmask.keyCode.PAGE_DOWN) {
20526                        e.preventDefault();
20527                        var caretPos = seekNext(getLastValidPosition());
20528                        opts.insertMode || caretPos !== getMaskSet().maskLength || e.shiftKey || caretPos--, 
20529                        caret(input, e.shiftKey ? pos.begin : caretPos, caretPos, !0);
20530                    } else k === Inputmask.keyCode.HOME && !e.shiftKey || k === Inputmask.keyCode.PAGE_UP ? (e.preventDefault(), 
20531                    caret(input, 0, e.shiftKey ? pos.begin : 0, !0)) : (opts.undoOnEscape && k === Inputmask.keyCode.ESCAPE || 90 === k && e.ctrlKey) && !0 !== e.altKey ? (checkVal(input, !0, !1, undoValue.split("")), 
20532                    $input.trigger("click")) : k !== Inputmask.keyCode.INSERT || e.shiftKey || e.ctrlKey ? !0 === opts.tabThrough && k === Inputmask.keyCode.TAB ? (!0 === e.shiftKey ? (null === getTest(pos.begin).match.fn && (pos.begin = seekNext(pos.begin)), 
20533                    pos.end = seekPrevious(pos.begin, !0), pos.begin = seekPrevious(pos.end, !0)) : (pos.begin = seekNext(pos.begin, !0), 
20534                    pos.end = seekNext(pos.begin, !0), pos.end < getMaskSet().maskLength && pos.end--), 
20535                    pos.begin < getMaskSet().maskLength && (e.preventDefault(), caret(input, pos.begin, pos.end))) : e.shiftKey || !1 === opts.insertMode && (k === Inputmask.keyCode.RIGHT ? setTimeout(function() {
20536                        var caretPos = caret(input);
20537                        caret(input, caretPos.begin);
20538                    }, 0) : k === Inputmask.keyCode.LEFT && setTimeout(function() {
20539                        var caretPos = caret(input);
20540                        caret(input, isRTL ? caretPos.begin + 1 : caretPos.begin - 1);
20541                    }, 0)) : (opts.insertMode = !opts.insertMode, caret(input, opts.insertMode || pos.begin !== getMaskSet().maskLength ? pos.begin : pos.begin - 1));
20542                    opts.onKeyDown.call(this, e, getBuffer(), caret(input).begin, opts), ignorable = -1 !== $.inArray(k, opts.ignorables);
20543                },
20544                keypressEvent: function(e, checkval, writeOut, strict, ndx) {
20545                    var input = this, $input = $(input), k = e.which || e.charCode || e.keyCode;
20546                    if (!(!0 === checkval || e.ctrlKey && e.altKey) && (e.ctrlKey || e.metaKey || ignorable)) return k === Inputmask.keyCode.ENTER && undoValue !== getBuffer().join("") && (undoValue = getBuffer().join(""), 
20547                    setTimeout(function() {
20548                        $input.trigger("change");
20549                    }, 0)), !0;
20550                    if (k) {
20551                        46 === k && !1 === e.shiftKey && "" !== opts.radixPoint && (k = opts.radixPoint.charCodeAt(0));
20552                        var forwardPosition, pos = checkval ? {
20553                            begin: ndx,
20554                            end: ndx
20555                        } : caret(input), c = String.fromCharCode(k);
20556                        getMaskSet().writeOutBuffer = !0;
20557                        var valResult = isValid(pos, c, strict);
20558                        if (!1 !== valResult && (resetMaskSet(!0), forwardPosition = valResult.caret !== undefined ? valResult.caret : checkval ? valResult.pos + 1 : seekNext(valResult.pos), 
20559                        getMaskSet().p = forwardPosition), !1 !== writeOut && (setTimeout(function() {
20560                            opts.onKeyValidation.call(input, k, valResult, opts);
20561                        }, 0), getMaskSet().writeOutBuffer && !1 !== valResult)) {
20562                            var buffer = getBuffer();
20563                            writeBuffer(input, buffer, opts.numericInput && valResult.caret === undefined ? seekPrevious(forwardPosition) : forwardPosition, e, !0 !== checkval), 
20564                            !0 !== checkval && setTimeout(function() {
20565                                !0 === isComplete(buffer) && $input.trigger("complete");
20566                            }, 0);
20567                        }
20568                        if (e.preventDefault(), checkval) return !1 !== valResult && (valResult.forwardPosition = forwardPosition), 
20569                        valResult;
20570                    }
20571                },
20572                pasteEvent: function(e) {
20573                    var tempValue, input = this, ev = e.originalEvent || e, $input = $(input), inputValue = input.inputmask._valueGet(!0), caretPos = caret(input);
20574                    isRTL && (tempValue = caretPos.end, caretPos.end = caretPos.begin, caretPos.begin = tempValue);
20575                    var valueBeforeCaret = inputValue.substr(0, caretPos.begin), valueAfterCaret = inputValue.substr(caretPos.end, inputValue.length);
20576                    if (valueBeforeCaret === (isRTL ? getBufferTemplate().reverse() : getBufferTemplate()).slice(0, caretPos.begin).join("") && (valueBeforeCaret = ""), 
20577                    valueAfterCaret === (isRTL ? getBufferTemplate().reverse() : getBufferTemplate()).slice(caretPos.end).join("") && (valueAfterCaret = ""), 
20578                    isRTL && (tempValue = valueBeforeCaret, valueBeforeCaret = valueAfterCaret, valueAfterCaret = tempValue), 
20579                    window.clipboardData && window.clipboardData.getData) inputValue = valueBeforeCaret + window.clipboardData.getData("Text") + valueAfterCaret; else {
20580                        if (!ev.clipboardData || !ev.clipboardData.getData) return !0;
20581                        inputValue = valueBeforeCaret + ev.clipboardData.getData("text/plain") + valueAfterCaret;
20582                    }
20583                    var pasteValue = inputValue;
20584                    if ($.isFunction(opts.onBeforePaste)) {
20585                        if (!1 === (pasteValue = opts.onBeforePaste.call(inputmask, inputValue, opts))) return e.preventDefault();
20586                        pasteValue || (pasteValue = inputValue);
20587                    }
20588                    return checkVal(input, !1, !1, isRTL ? pasteValue.split("").reverse() : pasteValue.toString().split("")), 
20589                    writeBuffer(input, getBuffer(), seekNext(getLastValidPosition()), e, undoValue !== getBuffer().join("")), 
20590                    !0 === isComplete(getBuffer()) && $input.trigger("complete"), e.preventDefault();
20591                },
20592                inputFallBackEvent: function(e) {
20593                    var input = this, inputValue = input.inputmask._valueGet();
20594                    if (getBuffer().join("") !== inputValue) {
20595                        var caretPos = caret(input);
20596                        if (!1 === function(input, inputValue, caretPos) {
20597                            if ("." === inputValue.charAt(caretPos.begin - 1) && "" !== opts.radixPoint && ((inputValue = inputValue.split(""))[caretPos.begin - 1] = opts.radixPoint.charAt(0), 
20598                            inputValue = inputValue.join("")), inputValue.charAt(caretPos.begin - 1) === opts.radixPoint && inputValue.length > getBuffer().length) {
20599                                var keypress = new $.Event("keypress");
20600                                return keypress.which = opts.radixPoint.charCodeAt(0), EventHandlers.keypressEvent.call(input, keypress, !0, !0, !1, caretPos.begin - 1), 
20601                                !1;
20602                            }
20603                        }(input, inputValue, caretPos)) return !1;
20604                        if (inputValue = inputValue.replace(new RegExp("(" + Inputmask.escapeRegex(getBufferTemplate().join("")) + ")*"), ""), 
20605                        !1 === function(input, inputValue, caretPos) {
20606                            if (iemobile) {
20607                                var inputChar = inputValue.replace(getBuffer().join(""), "");
20608                                if (1 === inputChar.length) {
20609                                    var keypress = new $.Event("keypress");
20610                                    return keypress.which = inputChar.charCodeAt(0), EventHandlers.keypressEvent.call(input, keypress, !0, !0, !1, getMaskSet().validPositions[caretPos.begin - 1] ? caretPos.begin : caretPos.begin - 1), 
20611                                    !1;
20612                                }
20613                            }
20614                        }(input, inputValue, caretPos)) return !1;
20615                        caretPos.begin > inputValue.length && (caret(input, inputValue.length), caretPos = caret(input));
20616                        var buffer = getBuffer().join(""), frontPart = inputValue.substr(0, caretPos.begin), backPart = inputValue.substr(caretPos.begin), frontBufferPart = buffer.substr(0, caretPos.begin), backBufferPart = buffer.substr(caretPos.begin), selection = caretPos, entries = "", isEntry = !1;
20617                        if (frontPart !== frontBufferPart) {
20618                            selection.begin = 0;
20619                            for (var fpl = (isEntry = frontPart.length >= frontBufferPart.length) ? frontPart.length : frontBufferPart.length, i = 0; frontPart.charAt(i) === frontBufferPart.charAt(i) && i < fpl; i++) selection.begin++;
20620                            isEntry && (entries += frontPart.slice(selection.begin, selection.end));
20621                        }
20622                        backPart !== backBufferPart && (backPart.length > backBufferPart.length ? isEntry && (selection.end = selection.begin) : backPart.length < backBufferPart.length ? selection.end += backBufferPart.length - backPart.length : backPart.charAt(0) !== backBufferPart.charAt(0) && selection.end++), 
20623                        writeBuffer(input, getBuffer(), selection), entr
20623ies.length > 0 ? $.each(entries.split(""), function(ndx, entry) {
20624                            var keypress = new $.Event("keypress");
20625                            keypress.which = entry.charCodeAt(0), ignorable = !1, EventHandlers.keypressEvent.call(input, keypress);
20626                        }) : (selection.begin === selection.end - 1 && caret(input, seekPrevious(selection.begin + 1), selection.end), 
20627                        e.keyCode = Inputmask.keyCode.DELETE, EventHandlers.keydownEvent.call(input, e)), 
20628                        e.preventDefault();
20629                    }
20630                },
20631                setValueEvent: function(e) {
20632                    this.inputmask.refreshValue = !1;
20633                    var input = this, value = input.inputmask._valueGet(!0);
20634                    $.isFunction(opts.onBeforeMask) && (value = opts.onBeforeMask.call(inputmask, value, opts) || value), 
20635                    value = value.split(""), checkVal(input, !0, !1, isRTL ? value.reverse() : value), 
20636                    undoValue = getBuffer().join(""), (opts.clearMaskOnLostFocus || opts.clearIncomplete) && input.inputmask._valueGet() === getBufferTemplate().join("") && input.inputmask._valueSet("");
20637                },
20638                focusEvent: function(e) {
20639                    var input = this, nptValue = input.inputmask._valueGet();
20640                    opts.showMaskOnFocus && (!opts.showMaskOnHover || opts.showMaskOnHover && "" === nptValue) && (input.inputmask._valueGet() !== getBuffer().join("") ? writeBuffer(input, getBuffer(), seekNext(getLastValidPosition())) : !1 === mouseEnter && caret(input, seekNext(getLastValidPosition()))), 
20641                    !0 === opts.positionCaretOnTab && !1 === mouseEnter && "" !== nptValue && (writeBuffer(input, getBuffer(), caret(input)), 
20642                    EventHandlers.clickEvent.apply(input, [ e, !0 ])), undoValue = getBuffer().join("");
20643                },
20644                mouseleaveEvent: function(e) {
20645                    var input = this;
20646                    if (mouseEnter = !1, opts.clearMaskOnLostFocus && document.activeElement !== input) {
20647                        var buffer = getBuffer().slice(), nptValue = input.inputmask._valueGet();
20648                        nptValue !== input.getAttribute("placeholder") && "" !== nptValue && (-1 === getLastValidPosition() && nptValue === getBufferTemplate().join("") ? buffer = [] : clearOptionalTail(buffer), 
20649                        writeBuffer(input, buffer));
20650                    }
20651                },
20652                clickEvent: function(e, tabbed) {
20653                    function doRadixFocus(clickPos) {
20654                        if ("" !== opts.radixPoint) {
20655                            var vps = getMaskSet().validPositions;
20656                            if (vps[clickPos] === undefined || vps[clickPos].input === getPlaceholder(clickPos)) {
20657                                if (clickPos < seekNext(-1)) return !0;
20658                                var radixPos = $.inArray(opts.radixPoint, getBuffer());
20659                                if (-1 !== radixPos) {
20660                                    for (var vp in vps) if (radixPos < vp && vps[vp].input !== getPlaceholder(vp)) return !1;
20661                                    return !0;
20662                                }
20663                            }
20664                        }
20665                        return !1;
20666                    }
20667                    var input = this;
20668                    setTimeout(function() {
20669                        if (document.activeElement === input) {
20670                            var selectedCaret = caret(input);
20671                            if (tabbed && (isRTL ? selectedCaret.end = selectedCaret.begin : selectedCaret.begin = selectedCaret.end), 
20672                            selectedCaret.begin === selectedCaret.end) switch (opts.positionCaretOnClick) {
20673                              case "none":
20674                                break;
20675
20676                              case "radixFocus":
20677                                if (doRadixFocus(selectedCaret.begin)) {
20678                                    var radixPos = getBuffer().join("").indexOf(opts.radixPoint);
20679                                    caret(input, opts.numericInput ? seekNext(radixPos) : radixPos);
20680                                    break;
20681                                }
20682
20683                              default:
20684                                var clickPosition = selectedCaret.begin, lvclickPosition = getLastValidPosition(clickPosition, !0), lastPosition = seekNext(lvclickPosition);
20685                                if (clickPosition < lastPosition) caret(input, isMask(clickPosition, !0) || isMask(clickPosition - 1, !0) ? clickPosition : seekNext(clickPosition)); else {
20686                                    var lvp = getMaskSet().validPositions[lvclickPosition], tt = getTestTemplate(lastPosition, lvp ? lvp.match.locator : undefined, lvp), placeholder = getPlaceholder(lastPosition, tt.match);
20687                                    if ("" !== placeholder && getBuffer()[lastPosition] !== placeholder && !0 !== tt.match.optionalQuantifier && !0 !== tt.match.newBlockMarker || !isMask(lastPosition, !0) && tt.match.def === placeholder) {
20688                                        var newPos = seekNext(lastPosition);
20689                                        (clickPosition >= newPos || clickPosition === lastPosition) && (lastPosition = newPos);
20690                                    }
20691                                    caret(input, lastPosition);
20692                                }
20693                            }
20694                        }
20695                    }, 0);
20696                },
20697                dblclickEvent: function(e) {
20698                    var input = this;
20699                    setTimeout(function() {
20700                        caret(input, 0, seekNext(getLastValidPosition()));
20701                    }, 0);
20702                },
20703                cutEvent: function(e) {
20704                    var input = this, $input = $(input), pos = caret(input), ev = e.originalEvent || e, clipboardData = window.clipboardData || ev.clipboardData, clipData = isRTL ? getBuffer().slice(pos.end, pos.begin) : getBuffer().slice(pos.begin, pos.end);
20705                    clipboardData.setData("text", isRTL ? clipData.reverse().join("") : clip
20705Data.join("")), 
20706                    document.execCommand && document.execCommand("copy"), handleRemove(input, Inputmask.keyCode.DELETE, pos), 
20707                    writeBuffer(input, getBuffer(), getMaskSet().p, e, undoValue !== getBuffer().join("")), 
20708                    input.inputmask._valueGet() === getBufferTemplate().join("") && $input.trigger("cleared");
20709                },
20710                blurEvent: function(e) {
20711                    var $input = $(this), input = this;
20712                    if (input.inputmask) {
20713                        var nptValue = input.inputmask._valueGet(), buffer = getBuffer().slice();
20714                        "" !== nptValue && (opts.clearMaskOnLostFocus && (-1 === getLastValidPosition() && nptValue === getBufferTemplate().join("") ? buffer = [] : clearOptionalTail(buffer)), 
20715                        !1 === isComplete(buffer) && (setTimeout(function() {
20716                            $input.trigger("incomplete");
20717                        }, 0), opts.clearIncomplete && (resetMaskSet(), buffer = opts.clearMaskOnLostFocus ? [] : getBufferTemplate().slice())), 
20718                        writeBuffer(input, buffer, undefined, e)), undoValue !== getBuffer().join("") && (undoValue = buffer.join(""), 
20719                        $input.trigger("change"));
20720                    }
20721                },
20722                mouseenterEvent: function(e) {
20723                    var input = this;
20724                    mouseEnter = !0, document.activeElement !== input && opts.showMaskOnHover && input.inputmask._valueGet() !== getBuffer().join("") && writeBuffer(input, getBuffer());
20725                },
20726                submitEvent: function(e) {
20727                    undoValue !== getBuffer().join("") && $el.trigger("change"), opts.clearMaskOnLostFocus && -1 === getLastValidPosition() && el.inputmask._valueGet && el.inputmask._valueGet() === getBufferTemplate().join("") && el.inputmask._valueSet(""), 
20728                    opts.removeMaskOnSubmit && (el.inputmask._valueSet(el.inputmask.unmaskedvalue(), !0), 
20729                    setTimeout(function() {
20730                        writeBuffer(el, getBuffer());
20731                    }, 0));
20732                },
20733                resetEvent: function(e) {
20734                    el.inputmask.refreshValue = !0, setTimeout(function() {
20735                        $el.trigger("setvalue");
20736                    }, 0);
20737                }
20738            };
20739            Inputmask.prototype.positionColorMask = function(input, template) {
20740                input.style.left = template.offsetLeft + "px";
20741            };
20742            var valueBuffer;
20743            if (actionObj !== undefined) switch (actionObj.action) {
20744              case "isComplete":
20745                return el = actionObj.el, isComplete(getBuffer());
20746
20747              case "unmaskedvalue":
20748                return el !== undefined && actionObj.value === undefined || (valueBuffer = actionObj.value, 
20749                valueBuffer = ($.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(inputmask, valueBuffer, opts) || valueBuffer : valueBuffer).split(""), 
20750                checkVal(undefined, !1, !1, isRTL ? valueBuffer.reverse() : valueBuffer), $.isFunction(opts.onBeforeWrite) && opts.onBeforeWrite.call(inputmask, undefined, getBuffer(), 0, opts)), 
20751                unmaskedvalue(el);
20752
20753              case "mask":
20754                !function(elem) {
20755                    EventRuler.off(elem);
20756                    var isSupported = function(input, opts) {
20757                        var elementType = input.getAttribute("type"), isSupported = "INPUT" === input.tagName && -1 !== $.inArray(elementType, opts.supportsInputType) || input.isContentEditable || "TEXTAREA" === input.tagName;
20758                        if (!isSupported) if ("INPUT" === input.tagName) {
20759                            var el = document.createElement("input");
20760                            el.setAttribute("type", elementType), isSupported = "text" === el.type, el = null;
20761                        } else isSupported = "partial";
20762                        return !1 !== isSupported ? function(npt) {
20763                            function getter() {
20764                                return this.inputmask ? this.inputmask.opts.autoUnmask ? this.inputmask.unmaskedvalue() : -1 !== getLastValidPosition() || !0 !== opts.nullable ? document.activeElement === this && opts.clearMaskOnLostFocus ? (isRTL ? clearOptionalTail(getBuffer().slice()).reverse() : clearOptionalTail(getBuffer().slice())).join("") : valueGet.call(this) : "" : valueGet.call(this);
20765                            }
20766                            function setter(value) {
20767                                valueSet.call(this, value), this.inputmask && $(this).trigger("setvalue");
20768                            }
20769                            var valueGet, valueSet;
20770                            if (!npt.inputmask.__valueGet) {
20771                                if (!0 !== opts.noValuePatching) {
20772                                    if (Object.getOwnPropertyDescriptor) {
20773                                        "function" != typeof Object.getPrototypeOf && (Object.getPrototypeOf = "object" === _typeof("test".__proto__) ? function(object) {
20774                                            return object.__proto__;
20775                                        } : function(object) {
20776                                            return object.constructor.prototype;
20777                                        });
20778                                        var valueProperty = Object.getPrototypeOf ? Object.getOwnPropertyDescriptor(Object.getPrototypeOf(npt), "value") : undefined;
20779                                        valueProperty && valueProperty.get && valueProperty.set ? (valueGet = valueProperty.get, 
20780                                        valueSet = valueProperty.set, Object.defineProperty(npt, "value", {
20781                                            get: getter,
20782                                            set: setter,
20783                                            configurable: !0
20784                                        })) : "INPUT" !== npt.tagName && (valueGet = function() {
20785                                            return this.textContent;
20786                                        }, valueSet = function(value) {
20787                                            this.textContent = value;
20788                                        }, Object.defineProperty(npt, "value", {
20789                                            get: getter,
20790                                            set: setter,
20791                                            configurable: !0
20792                                        }));
20793                                    } else document.__lookupGetter__ && npt.__lookupGetter__("value") && (valueGet = npt.__lookupGetter__("value"), 
20794                                    valueSet = npt.__lookupSetter__("value"), npt.__defineGetter__("value", getter), 
20795                                    npt.__defineSetter__("value", setter));
20796                                    npt.inputmask.__valueGet = valueGet, npt.inputmask.__valueSet = valueSet;
20797                                }
20798                                npt.inputmask._valueGet = function(overruleRTL) {
20799                                    return isRTL && !0 !== overruleRTL ? valueGet.call(this.el).split("").reverse().join("") : valueGet.call(this.el);
20800                                }, npt.inputmask._valueSet = function(value, overruleRTL) {
20801                                    valueSet.call(this.el, null === value || value === undefined ? "" : !0 !== overruleRTL && isRTL ? value.split("").reverse().join("") : value);
20802                                }, valueGet === undefined && (valueGet = function() {
20803                                    return this.value;
20804                                }, valueSet = function(value) {
20805                                    this.value = value;
20806                                }, function(type) {
20807                                    if ($.valHooks && ($.valHooks[type] === undefined || !0 !== $.valHooks[type].inputmaskpatch)) {
20808                                        var valhookGet = $.valHooks[type] && $.valHooks[type].get ? $.valHooks[type].get : function(elem) {
20809                                            return elem.value;
20810                                        }, valhookSet = $.valHooks[type] && $.valHooks[type].set ? $.valHooks[type].set : function(elem, value) {
20811                                            return elem.value = value, elem;
20812                                        };
20813                                        $.valHooks[type] = {
20814                                            get: function(elem) {
20815                                                if (elem.inputmask) {
20816                                                    if (elem.inputmask.opts.autoUnmask) return elem.inputmask.unmaskedvalue();
20817                                                    var result = valhookGet(elem);
20818                                                    return -1 !== getLastValidPosition(undefined, undefined, elem.inputmask.maskset.validPositions) || !0 !== opts.nullable ? result : "";
20819                                                }
20820                                                return valhookGet(elem);
20821                                            },
20822                                            set: function(elem, value) {
20823                                                var result, $elem = $(elem);
20824                                                return result = valhookSet(elem, value), elem.inputmask && $elem.trigger("setvalue"), 
20825                                                result;
20826                                            },
20827                                            inputmaskpatch: !0
20828                                        };
20829                                    }
20830                                }(npt.type), function(npt) {
20831                                    EventRuler.on(npt, "mouseenter", function(event) {
20832                                        var $input = $(this);
20833                                        this.inputmask._valueGet() !== getBuffer().join("") && $input.trigger("setvalue");
20834                                    });
20835                                }(npt));
20836                            }
20837                        }(input) : input.inputmask = undefined, isSupported;
20838                    }(elem, opts);
20839                    if (!1 !== isSupported && (el = elem, $el = $(el), -1 === (maxLength = el !== undefined ? el.maxLength : undefined) && (maxLength = undefined), 
20840                    !0 === opts.colorMask && initializeColorMask(el), android && (el.hasOwnProperty("inputmode") && (el.inputmode = opts.inputmode, 
20841                    el.setAttribute("inputmode", opts.inputmode)), "rtfm" === opts.androidHack && (!0 !== opts.colorMask && initializeColorMask(el), 
20842                    el.type = "password")), !0 === isSupported && (EventRuler.on(el, "submit", EventHandlers.submitEvent), 
20843                    EventRuler.on(el, "reset", EventHandlers.resetEvent), EventRuler.on(el, "mouseenter", EventHandlers.mouseenterEvent), 
20844                    EventRuler.on(el, "blur", EventHandlers.blurEvent), EventRuler.on(el, "focus", EventHandlers.focusEvent), 
20845                    EventRuler.on(el, "mouseleave", EventHandlers.mouseleaveEvent), !0 !== opts.colorMask && EventRuler.on(el, "click", EventHandlers.clickEvent), 
20846                    EventRuler.on(el, "dblclick", EventHandlers.dblclickEvent), EventRuler.on(el, "paste", EventHandlers.pasteEvent), 
20847                    EventRuler.on(el, "dragdrop", EventHandlers.pasteEvent), EventRuler.on(el, "drop", EventHandlers.pasteEvent), 
20848                    EventRuler.on(el, "cut", EventHandlers.cutEvent), EventRuler.on(el, "complete", opts.oncomplete), 
20849                    EventRuler.on(el, "incomplete", opts.onincomplete), EventRuler.on(el, "cleared", opts.oncleared), 
20850                    android || !0 === opts.inputEventOnly ? el.removeAttribute("maxLength") : (EventRuler.on(el, "keydown", EventHandlers.keydownEvent), 
20851                    EventRuler.on(el, "keypress", EventHandlers.keypressEvent)), EventRuler.on(el, "compositionstart", $.noop), 
20852                    EventRuler.on(el, "compositionupdate", $.noop), EventRuler.on(el, "compositionend", $.noop), 
20853                    EventRuler.on(el, "keyup", $.noop), EventRuler.on(el, "input", EventHandlers.inputFallBackEvent), 
20854                    EventRuler.on(el, "beforeinput", $.noop)), EventRuler.on(el, "setvalue", EventHandlers.setValueEvent), 
20855                    undoValue = getBufferTemplate().join(""), "" !== el.inputmask._valueGet(!0) || !1 === opts.clearMaskOnLostFocus || document.activeElement === el)) {
20856                        var initialValue = $.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(inputmask, el.inputmask._valueGet(!0), opts) || el.inputmask._valueGet(!0) : el.inputmask._valueGet(!0);
20857                        "" !== initialValue && checkVal(el, !0, !1, isRTL ? initialValue.split("").reverse() : initialValue.split(""));
20858                        var buffer = getBuffer().slice();
20859                        undoValue = buffer.join(""), !1 === isComplete(buffer) && opts.clearIncomplete && resetMaskSet(), 
20860                        opts.clearMaskOnLostFocus && document.activeElement !== el && (-1 === getLastValidPosition() ? buffer = [] : clearOptionalTail(buffer)), 
20861                        writeBuffer(el, buffer), document.activeElement === el && caret(el, seekNext(getLastValidPosition()));
20862                    }
20863                }(el);
20864                break;
20865
20866              case "format":
20867                return valueBuffer = ($.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(inputmask, actionObj.value, opts) || actionObj.value : actionObj.value).split(""), 
20868                checkVal(undefined, !0, !1, isRTL ? valueBuffer.reverse() : valueBuffer), actionObj.metadata ? {
20869                    value: isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join(""),
20870                    metadata: maskScope.call(this, {
20871                        action: "getmetadata"
20872                    }, maskset, opts)
20873                } : isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join("");
20874
20875              case "isValid":
20876                actionObj.value ? (valueBuffer = actionObj.value.split(""), checkVal(undefined, !0, !0, isRTL ? valueBuffer.reverse() : valueBuffer)) : actionObj.value = getBuffer().join("");
20877                for (var buffer = getBuffer(), rl = determineLastRequiredPosition(), lmib = buffer.length - 1; lmib > rl && !isMask(lmib); lmib--) ;
20878                return buffer.splice(rl, lmib + 1 - rl), isComplete(buffer) && actionObj.value === getBuffer().join("");
20879
20880              case "getemptymask":
20881                return getBufferTemplate().join("");
20882
20883              case "remove":
20884                if (el && el.inputmask) {
20885                    $el = $(el), el.inputmask._valueSet(opts.autoUnmask ? unmaskedvalue(el) : el.inputmask._valueGet(!0)), 
20886                    EventRuler.off(el);
20887                    Object.getOwnPropertyDescriptor && Object.getPrototypeOf ? Object.getOwnPropertyDescriptor(Object.getPrototypeOf(el), "value") && el.inputmask.__valueGet && Object.defineProperty(el, "value", {
20888                        get: el.inputmask.__valueGet,
20889                        set: el.inputmask.__valueSet,
20890                        configurable: !0
20891                    }) : document.__lookupGetter__ && el.__lookupGetter__("value") && el.inputmask.__valueGet && (el.__defineGetter__("value", el.inputmask.__valueGet), 
20892                    el.__defineSetter__("value", el.inputmask.__valueSet)), el.inputmask = undefined;
20893                }
20894                return el;
20895
20896              case "getmetadata":
20897                if ($.isArray(maskset.metadata)) {
20898                    var maskTarget = getMaskTemplate(!0, 0, !1).join("");
20899                    return $.each(maskset.metadata, function(ndx, mtdt) {
20900                        if (mtdt.mask === maskTarget) return maskTarget = mtdt, !1;
20901                    }), maskTarget;
20902                }
20903                return maskset.metadata;
20904            }
20905        }
20906        var ua = navigator.userAgent, mobile = /mobile/i.test(ua), iemobile = /iemobile/i.test(ua), iphone = /iphone/i.test(ua) && !iemobile, android = /android/i.test(ua) && !iemobile;
20907        return Inputmask.prototype = {
20908            dataAttribute: "data-inputmask",
20909            defaults: {
20910                placeholder: "_",
20911                optionalmarker: {
20912                    start: "[",
20913                    end: "]"
20914                },
20915                quantifiermarker: {
20916                    start: "{",
20917                    end: "}"
20918                },
20919                groupmarker: {
20920                    start: "(",
20921                    end: ")"
20922                },
20923                alternatormarker: "|",
20924                escapeChar: "\\",
20925                mask: null,
20926                regex: null,
20927                oncomplete: $.noop,
20928                onincomplete: $.noop,
20929                oncleared: $.noop,
20930                repeat: 0,
20931                greedy: !0,
20932                autoUnmask: !1,
20933                removeMaskOnSubmit: !1,
20934                clearMaskOnLostFocus: !0,
20935                insertMode: !0,
20936                clearIncomplete: !1,
20937                alias: null,
20938                onKeyDown: $.noop,
20939                onBeforeMask: null,
20940                onBeforePaste: function(pastedValue, opts) {
20941                    return $.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(this, pastedValue, opts) : pastedValue;
20942                },
20943                onBeforeWrite: null,
20944                onUnMask: null,
20945                showMaskOnFocus: !0,
20946                showMaskOnHover: !0,
20947                onKeyValidation: $.noop,
20948                skipOptionalPartCharacter: " ",
20949                numericInput: !1,
20950                rightAlign: !1,
20951                undoOnEscape: !0,
20952                radixPoint: "",
20953                radixPointDefinitionSymbol: undefined,
20954                groupSeparator: "",
20955                keepStatic: null,
20956                positionCaretOnTab: !0,
20957                tabThrough: !1,
20958                supportsInputType: [ "text", "tel", "password" ],
20959                ignorables: [ 8, 9, 13, 19, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 93, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 0, 229 ],
20960                isComplete: null,
20961                canClearPosition: $.noop,
20962                preValidation: null,
20963                postValidation: null,
20964                staticDefinitionSymbol: undefined,
20965                jitMasking: !1,
20966                nullable: !0,
20967                inputEventOnly: !1,
20968                noValuePatching: !1,
20969                positionCaretOnClick: "lvp",
20970                casing: null,
20971                inputmode: "verbatim",
20972                colorMask: !1,
20973                androidHack: !1,
20974                importDataAttributes: !0
20975            },
20976            definitions: {
20977                "9": {
20978                    validator: "[0-91-9]",
20979                    cardinality: 1,
20980                    definitionSymbol: "*"
20981                },
20982                a: {
20983                    validator: "[A-Za-zА-яЁёÀ-ÿµ]",
20984                    cardinality: 1,
20985                    definitionSymbol: "*"
20986                },
20987                "*": {
20988                    validator: "[0-91-9A-Za-zА-яЁёÀ-ÿµ]",
20989                    cardinality: 1
20990                }
20991            },
20992            aliases: {},
20993            masksCache: {},
20994            mask: function(elems) {
20995                function importAttributeOptions(npt, opts, userOptions, dataAttribute) {
20996                    if (!0 === opts.importDataAttributes) {
20997                        var option, dataoptions, optionData, p, importOption = function(option, optionData) {
20998                            null !== (optionData = optionData !== undefined ? optionData : npt.getAttribute(dataAttribute + "-" + option)) && ("string" == typeof optionData && (0 === option.indexOf("on") ? optionData = window[optionData] : "false" === optionData ? optionData = !1 : "true" === optionData && (
20998optionData = !0)), 
20999                            userOptions[option] = optionData);
21000                        }, attrOptions = npt.getAttribute(dataAttribute);
21001                        if (attrOptions && "" !== attrOptions && (attrOptions = attrOptions.replace(new RegExp("'", "g"), '"'), 
21002                        dataoptions = JSON.parse("{" + attrOptions + "}")), dataoptions) {
21003                            optionData = undefined;
21004                            for (p in dataoptions) if ("alias" === p.toLowerCase()) {
21005                                optionData = dataoptions[p];
21006                                break;
21007                            }
21008                        }
21009                        importOption("alias", optionData), userOptions.alias && resolveAlias(userOptions.alias, userOptions, opts);
21010                        for (option in opts) {
21011                            if (dataoptions) {
21012                                optionData = undefined;
21013                                for (p in dataoptions) if (p.toLowerCase() === option.toLowerCase()) {
21014                                    optionData = dataoptions[p];
21015                                    break;
21016                                }
21017                            }
21018                            importOption(option, optionData);
21019                        }
21020                    }
21021                    return $.extend(!0, opts, userOptions), ("rtl" === npt.dir || opts.rightAlign) && (npt.style.textAlign = "right"), 
21022                    ("rtl" === npt.dir || opts.numericInput) && (npt.dir = "ltr", npt.removeAttribute("dir"), 
21023                    opts.isRTL = !0), opts;
21024                }
21025                var that = this;
21026                return "string" == typeof elems && (elems = document.getElementById(elems) || document.querySelectorAll(elems)), 
21027                elems = elems.nodeName ? [ elems ] : elems, $.each(elems, function(ndx, el) {
21028                    var scopedOpts = $.extend(!0, {}, that.opts);
21029                    importAttributeOptions(el, scopedOpts, $.extend(!0, {}, that.userOptions), that.dataAttribute);
21030                    var maskset = generateMaskSet(scopedOpts, that.noMasksCache);
21031                    maskset !== undefined && (el.inputmask !== undefined && (el.inputmask.opts.autoUnmask = !0, 
21032                    el.inputmask.remove()), el.inputmask = new Inputmask(undefined, undefined, !0), 
21033                    el.inputmask.opts = scopedOpts, el.inputmask.noMasksCache = that.noMasksCache, el.inputmask.userOptions = $.extend(!0, {}, that.userOptions), 
21034                    el.inputmask.isRTL = scopedOpts.isRTL || scopedOpts.numericInput, el.inputmask.el = el, 
21035                    el.inputmask.maskset = maskset, $.data(el, "_inputmask_opts", scopedOpts), maskScope.call(el.inputmask, {
21036                        action: "mask"
21037                    }));
21038                }), elems && elems[0] ? elems[0].inputmask || this : this;
21039            },
21040            option: function(options, noremask) {
21041                return "string" == typeof options ? this.opts[options] : "object" === (void 0 === options ? "undefined" : _typeof(options)) ? ($.extend(this.userOptions, options), 
21042                this.el && !0 !== noremask && this.mask(this.el), this) : void 0;
21043            },
21044            unmaskedvalue: function(value) {
21045                return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
21046                maskScope.call(this, {
21047                    action: "unmaskedvalue",
21048                    value: value
21049                });
21050            },
21051            remove: function() {
21052                return maskScope.call(this, {
21053                    action: "remove"
21054                });
21055            },
21056            getemptymask: function() {
21057                return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
21058                maskScope.call(this, {
21059                    action: "getemptymask"
21060                });
21061            },
21062            hasMaskedValue: function() {
21063                return !this.opts.autoUnmask;
21064            },
21065            isComplete: function() {
21066                return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
21067                maskScope.call(this, {
21068                    action: "isComplete"
21069                });
21070            },
21071            getmetadata: function() {
21072                return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
21073                maskScope.call(this, {
21074                    action: "getmetadata"
21075                });
21076            },
21077            isValid: function(value) {
21078                return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
21079                maskScope.call(this, {
21080                    action: "isValid",
21081                    value: value
21082                });
21083            },
21084            format: function(value, metadata) {
21085                return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
21086                maskScope.call(this, {
21087                    action: "format",
21088                    value: value,
21089                    metadata: metadata
21090                });
21091            },
21092            analyseMask: function(mask, regexMask, opts) {
21093                function MaskToken(isGroup, isOptional, isQuantifier, isAlternator) {
21094                    this.matches = [], this.openGroup = isGroup || !1, this.alternatorGroup = !1, this.isGroup = isGroup || !1, 
21095                    this.isOptional = isOptional || !1, this.isQuantifier = is
21095Quantifier || !1, this.isAlternator = isAlternator || !1, 
21096                    this.quantifier = {
21097                        min: 1,
21098                        max: 1
21099                    };
21100                }
21101                function insertTestDefinition(mtoken, element, position) {
21102                    position = position !== undefined ? position : mtoken.matches.length;
21103                    var prevMatch = mtoken.matches[position - 1];
21104                    if (regexMask) 0 === element.indexOf("[") || escaped && /\\d|\\s|\\w]/i.test(element) || "." === element ? mtoken.matches.splice(position++, 0, {
21105                        fn: new RegExp(element, opts.casing ? "i" : ""),
21106                        cardinality: 1,
21107                        optionality: mtoken.isOptional,
21108                        newBlockMarker: prevMatch === undefined || prevMatch.def !== element,
21109                        casing: null,
21110                        def: element,
21111                        placeholder: undefined,
21112                        nativeDef: element
21113                    }) : (escaped && (element = element[element.length - 1]), $.each(element.split(""), function(ndx, lmnt) {
21114                        prevMatch = mtoken.matches[position - 1], mtoken.matches.splice(position++, 0, {
21115                            fn: null,
21116                            cardinality: 0,
21117                            optionality: mtoken.isOptional,
21118                            newBlockMarker: prevMatch === undefined || prevMatch.def !== lmnt && null !== prevMatch.fn,
21119                            casing: null,
21120                            def: opts.staticDefinitionSymbol || lmnt,
21121                            placeholder: opts.staticDefinitionSymbol !== undefined ? lmnt : undefined,
21122                            nativeDef: lmnt
21123                        });
21124                    })), escaped = !1; else {
21125                        var maskdef = (opts.definitions ? opts.definitions[element] : undefined) || Inputmask.prototype.definitions[element];
21126                        if (maskdef && !escaped) {
21127                            for (var prevalidators = maskdef.prevalidator, prevalidatorsL = prevalidators ? prevalidators.length : 0, i = 1; i < maskdef.cardinality; i++) {
21128                                var prevalidator = prevalidatorsL >= i ? prevalidators[i - 1] : [], validator = prevalidator.validator, cardinality = prevalidator.cardinality;
21129                                mtoken.matches.splice(position++, 0, {
21130                                    fn: validator ? "string" == typeof validator ? new RegExp(validator, opts.casing ? "i" : "") : new function() {
21131                                        this.test = validator;
21132                                    }() : new RegExp("."),
21133                                    cardinality: cardinality || 1,
21134                                    optionality: mtoken.isOptional,
21135                                    newBlockMarker: prevMatch === undefined || prevMatch.def !== (maskdef.definitionSymbol || element),
21136                                    casing: maskdef.casing,
21137                                    def: maskdef.definitionSymbol || element,
21138                                    placeholder: maskdef.placeholder,
21139                                    nativeDef: element
21140                                }), prevMatch = mtoken.matches[position - 1];
21141                            }
21142                            mtoken.matches.splice(position++, 0, {
21143                                fn: maskdef.validator ? "string" == typeof maskdef.validator ? new RegExp(maskdef.validator, opts.casing ? "i" : "") : new function() {
21144                                    this.test = maskdef.validator;
21145                                }() : new RegExp("."),
21146                                cardinality: maskdef.cardinality,
21147                                optionality: mtoken.isOptional,
21148                                newBlockMarker: prevMatch === undefined || prevMatch.def !== (maskdef.definitionSymbol || element),
21149                                casing: maskdef.casing,
21150                                def: maskdef.definitionSymbol || element,
21151                                placeholder: maskdef.placeholder,
21152                                nativeDef: element
21153                            });
21154                        } else mtoken.matches.splice(position++, 0, {
21155                            fn: null,
21156                            cardinality: 0,
21157                            optionality: mtoken.isOptional,
21158                            newBlockMarker: prevMatch === undefined || prevMatch.def !== element && null !== prevMatch.fn,
21159                            casing: null,
21160                            def: opts.staticDefinitionSymbol || element,
21161                            placeholder: opts.staticDefinitionSymbol !== undefined ? element : undefined,
21162                            nativeDef: element
21163                        }), escaped = !1;
21164                    }
21165                }
21166                function verifyGroupMarker(maskToken) {
21167                    maskToken && maskToken.matches && $.each(maskToken.matches, function(ndx, token) {
21168                        var nextToken = maskToken.matches[ndx + 1];
21169                        (nextToken === undefined || nextToken.matches === undefined || !1 === nextToken.isQuantifier) && token && token.isGroup && (token.isGroup = !1, 
21170                        regexMask || (insertTestDefinition(token, opts.groupmarker.start, 0), !0 !== token.openGroup && insertTestDefinition(token, opts.groupmarker.end))), 
21171                        verifyGroupMarker(token);
21172                    });
21173                }
21174                function defaultCase() {
21175                    if (openenings.length > 0) {
21176                        if (currentOpeningToken = openenings[openenings.length - 1], insertTestDefinition(currentOpeningToken, m), 
21177                        currentOpeningToken.isAlternator) {
21178                            alternator = openenings.pop();
21179                            for (var mndx = 0; mndx < alternator.matches.length; mndx++) alternator.matches[mndx].isGroup = !1;
21180                            openenings.length > 0 ? (currentOpeningToken = openenings[openenings.length - 1]).matches.push(alternator) : currentToken.matches.push(alternator);
21181                        }
21182                    } else insertTestDefinition(currentToken, m);
21183                }
21184                function reverseTokens(maskToken) {
21185                    maskToken.matches = maskToken.matches.reverse();
21186                    for (var match in maskToken.matches) if (maskToken.matches.hasOwnProperty(match)) {
21187                        var intMatch = parseInt(match);
21188                        if (maskToken.matches[match].isQuantifier && maskToken.matches[intMatch + 1] && maskToken.matches[intMatch + 1].isGroup) {
21189                            var qt = maskToken.matches[match];
21190                            maskToken.matches.splice(match, 1), maskToken.matches.splice(intMatch + 1, 0, qt);
21191                        }
21192                        maskToken.matches[match].matches !== undefined ? maskToken.matches[match] = reverseTokens(maskToken.matches[match]) : maskToken.matches[match] = function(st) {
21193                            return st === opts.optionalmarker.start ? st = opts.optionalmarker.end : st === opts.optionalmarker.end ? st = opts.optionalmarker.start : st === opts.groupmarker.start ? st = opts.groupmarker.end : st === opts.groupmarker.end && (st = opts.groupmarker.start), 
21194                            st;
21195                        }(maskToken.matches[match]);
21196                    }
21197                    return maskToken;
21198                }
21199                var match, m, openingToken, currentOpeningToken, alternator, lastMatch, groupToken, tokenizer = /(?:[?*+]|\{[0-9\+\*]+(?:,[0-9\+\*]*)?\})|[^.?*+^${[]()|\\]+|./g, regexTokenizer = /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g, escaped = !1, currentToken = new MaskToken(), openenings = [], maskTokens = [];
21200                for (regexMask && (opts.optionalmarker.start = undefined, opts.optionalmarker.end = undefined); match = regexMask ? regexTokenizer.exec(mask) : tokenizer.exec(mask); ) {
21201                    if (m = match[0], regexMask) switch (m.charAt(0)) {
21202                      case "?":
21203                        m = "{0,1}";
21204                        break;
21205
21206                      case "+":
21207                      case "*":
21208                        m = "{" + m + "}";
21209                    }
21210                    if (escaped) defaultCase(); else switch (m.charAt(0)) {
21211                      case opts.escapeChar:
21212                        escaped = !0, regexMask && defaultCase();
21213                        break;
21214
21215                      case opts.optionalmarker.end:
21216                      case opts.groupmarker.end:
21217                        if (openingToken = openenings.pop(), openingToken.openGroup = !1, openingToken !== undefined) if (openenings.length > 0) {
21218                            if ((currentOpeningToken = openenings[openenings.length - 1]).matches.push(openingToken), 
21219                            currentOpeningToken.isAlternator) {
21220                                alternator = openenings.pop();
21221                                for (var mndx = 0; mndx < alternator.matches.length; mndx++) alternator.matches[mndx].isGroup = !1, 
21222                                alternator.matches[mndx].alternatorGroup = !1;
21223                                openenings.length > 0 ? (currentOpeningToken = openenings[openenings.length - 1]).matches.push(alternator) : currentToken.matches.push(alternator);
21224                            }
21225                        } else currentToken.matches.push(openingToken); else defaultCase();
21226                        break;
21227
21228                      case opts.optionalmarker.start:
21229                        openenings.push(new MaskToken(!1, !0));
21230                        break;
21231
21232                      case opts.groupmarker.start:
21233                        openenings.push(new MaskToken(!0));
21234                        break;
21235
21236                      case opts.quantifiermarker.start:
21237                        var quantifier = new MaskToken(!1, !1, !0), mq = (m = m.replace(/[{}]/g, "")).split(","), mq0 = isNaN(mq[0]) ? mq[0] : parseInt(mq[0]), mq1 = 1 === mq.length ? mq0 : isNaN(mq[1]) ? mq[1] : parseInt(mq[1]);
21238                        if ("*" !== mq1 && "+" !== mq1 || (mq0 = "*" === mq1 ? 0 : 1), quantifier.quantifier = {
21239                            min: mq0,
21240                            max: mq1
21241                        }, openenings.length > 0) {
21242                            var matches = openenings[openenings.length - 1].matches;
21243                            (match = matches.pop()).isGroup || ((groupToken = new MaskToken(!0)).matches.push(match), 
21244                            match = groupToken), matches.push(match), matches.push(quantifier);
21245                        } else (match = currentToken.matches.pop()).isGroup || (regexMask && null === match.fn && "." === match.def && (match.fn = new RegExp(match.def, opts.casing ? "i" : "")), 
21246                        (groupToken = new MaskToken(!0)).matches.push(match), match = groupToken), currentToken.matches.push(match), 
21247                        currentToken.matches.push(quantifier);
21248                        break;
21249
21250                      case opts.alternatormarker:
21251                        if (openenings.length > 0) {
21252                            var subToken = (currentOpeningToken = openenings[openenings.length - 1]).matches[currentOpeningToken.matches.length - 1];
21253                            lastMatch = currentOpeningToken.openGroup && (subToken.matches === undefined || !1 === subToken.isGroup && !1 === subToken.isAlternator) ? openenings.pop() : currentOpeningToken.matches.pop();
21254                        } else lastMatch = currentToken.matches.pop();
21255                        if (lastMatch.isAlternator) openenings.push(lastMatch); else if (lastMatch.alternatorGroup ? (alternator = openenings.pop(), 
21256                        lastMatch.alternatorGroup = !1) : alternator = new MaskToken(!1, !1, !1, !0), alternator.matches.push(lastMatch), 
21257                        openenings.push(alternator), lastMatch.openGroup) {
21258                            lastMatch.openGroup = !1;
21259                            var alternatorGroup = new MaskToken(!0);
21260                            alternatorGroup.alternatorGroup = !0, openenings.push(alternatorGroup);
21261                        }
21262                        break;
21263
21264                      default:
21265                        defaultCase();
21266                    }
21267                }
21268                for (;openenings.length > 0; ) openingToken = openenings.pop(), currentToken.matches.push(openingToken);
21269                return currentToken.matches.length > 0 && (verifyGroupMarker(currentToken), maskTokens.push(currentToken)), 
21270                (opts.numericInput || opts.isRTL) && reverseTokens(maskTokens[0]), maskTokens;
21271            }
21272        }, Inputmask.extendDefaults = function(options) {
21273            $.extend(!0, Inputmask.prototype.defaults, options);
21274        }, Inputmask.extendDefinitions = function(definition) {
21275            $.extend(!0, Inputmask.prototype.definitions, definition);
21276        }, Inputmask.extendAliases = function(alias) {
21277            $.extend(!0, Inputmask.prototype.aliases, alias);
21278        }, Inputmask.format = function(value, options, metadata) {
21279            return Inputmask(options).format(value, metadata);
21280        }, Inputmask.unmask = function(value, options) {
21281            return Inputmask(options).unmaskedvalue(value);
21282        }, Inputmask.isValid = function(value, options) {
21283            return Inputmask(options).isValid(value);
21284        }, Inputmask.remove = function(elems) {
21285            $.each(elems, function(ndx, el) {
21286                el.inputmask && el.inputmask.remove();
21287            });
21288        }, Inputmask.escapeRegex = function(str) {
21289            var specials = [ "/", ".", "*", "+", "?", "|", "(", ")", "[", "]", "{", "}", "\\", "$", "^" ];
21290            return str.replace(new RegExp("(\\" + specials.join("|\\") + ")", "gim"), "\\$1");
21291        }, Inputmask.keyCode = {
21292            ALT: 18,
21293            BACKSPACE: 8,
21294            BACKSPACE_SAFARI: 127,
21295            CAPS_LOCK: 20,
21296            COMMA: 188,
21297            COMMAND: 91,
21298            COMMAND_LEFT: 91,
21299            COMMAND_RIGHT: 93,
21300            CONTROL: 17,
21301            DELETE: 46,
21302            DOWN: 40,
21303            END: 35,
21304            ENTER: 13,
21305            ESCAPE: 27,
21306            HOME: 36,
21307            INSERT: 45,
21308            LEFT: 37,
21309            MENU: 93,
21310            NUMPAD_ADD: 107,
21311            NUMPAD_DECIMAL: 110,
21312            NUMPAD_DIVIDE: 111,
21313            NUMPAD_ENTER: 108,
21314            NUMPAD_MULTIPLY: 106,
21315            NUMPAD_SUBTRACT: 109,
21316            PAGE_DOWN: 34,
21317            PAGE_UP: 33,
21318            PERIOD: 190,
21319            RIGHT: 39,
21320            SHIFT: 16,
21321            SPACE: 32,
21322            TAB: 9,
21323            UP: 38,
21324            WINDOWS: 91,
21325            X: 88
21326        }, Inputmask;
21327    });
21328}
21328, function(module, exports) {
21329    module.exports = jQuery;
21330}, function(module, exports, __webpack_require__) {
21331    "use strict";
21332    function _interopRequireDefault(obj) {
21333        return obj && obj.__esModule ? obj : {
21334            default: obj
21335        };
21336    }
21337    __webpack_require__(4), __webpack_require__(9), __webpack_require__(12), __webpack_require__(13), 
21338    __webpack_require__(14), __webpack_require__(15);
21339    var _inputmask2 = _interopRequireDefault(__webpack_require__(1)), _inputmask4 = _interopRequireDefault(__webpack_require__(0)), _jquery2 = _interopRequireDefault(__webpack_require__(2));
21340    _inputmask4.default === _jquery2.default && __webpack_require__(16), window.Inputmask = _inputmask2.default;
21341}, function(module, exports, __webpack_require__) {
21342    var content = __webpack_require__(5);
21343    "string" == typeof content && (content = [ [ module.i, content, "" ] ]);
21344    var options = {
21345        hmr: !0
21346    };
21347    options.transform = void 0;
21348    __webpack_require__(7)(content, options);
21349    content.locals && (module.exports = content.locals);
21350}, function(module, exports, __webpack_require__) {
21351    (module.exports = __webpack_require__(6)(void 0)).push([ module.i, "span.im-caret {\r\n    -webkit-animation: 1s blink step-end infinite;\r\n    animation: 1s blink step-end infinite;\r\n}\r\n\r\n@keyframes blink {\r\n    from, to {\r\n        border-right-color: black;\r\n    }\r\n    50% {\r\n        border-right-color: transparent;\r\n    }\r\n}\r\n\r\n@-webkit-keyframes blink {\r\n    from, to {\r\n        border-right-color: black;\r\n    }\r\n    50% {\r\n        border-right-color: transparent;\r\n    }\r\n}\r\n\r\nspan.im-static {\r\n    color: grey;\r\n}\r\n\r\ndiv.im-colormask {\r\n    display: inline-block;\r\n    border-style: inset;\r\n    border-width: 2px;\r\n    -webkit-appearance: textfield;\r\n    -moz-appearance: textfield;\r\n    appearance: textfield;\r\n}\r\n\r\ndiv.im-colormask > input {\r\n    position: absolute;\r\n    display: inline-block;\r\n    background-color: transparent;\r\n    color: transparent;\r\n    -webkit-appearance: caret;\r\n    -moz-appearance: caret;\r\n    appearance: caret;\r\n    border-style: none;\r\n    left: 0; /*calculated*/\r\n}\r\n\r\ndiv.im-colormask > input:focus {\r\n    outline: none;\r\n}\r\n\r\ndiv.im-colormask > input::-moz-selection{\r\n    background: none;\r\n}\r\n\r\ndiv.im-colormask > input::selection{\r\n    background: none;\r\n}\r\ndiv.im-colormask > input::-moz-selection{\r\n    background: none;\r\n}\r\n\r\ndiv.im-colormask > div {\r\n    color: black;\r\n    display: inline-block;\r\n    width: 100px; /*calculated*/\r\n}", "" ]);
21352}, function(module, exports) {
21353    function cssWithMappingToString(item, useSourceMap) {
21354        var content = item[1] || "", cssMapping = item[3];
21355        if (!cssMapping) return content;
21356        if (useSourceMap && "function" == typeof btoa) {
21357            var sourceMapping = toComment(cssMapping), sourceURLs = cssMapping.sources.map(function(source) {
21358                return "/*# sourceURL=" + cssMapping.sourceRoot + source + " */";
21359            });
21360            return [ content ].concat(sourceURLs).concat([ sourceMapping ]).join("\n");
21361        }
21362        return [ content ].join("\n");
21363    }
21364    function toComment(sourceMap) {
21365        return "/*# " + ("sourceMappingURL=data:application/json;charset=utf-8;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))) + " */";
21366    }
21367    module.exports = function(useSourceMap) {
21368        var list = [];
21369        return list.toString = function() {
21370            return this.map(function(item) {
21371                var content = cssWithMappingToString(item, useSourceMap);
21372                return item[2] ? "@media " + item[2] + "{" + content + "}" : content;
21373            }).join("");
21374        }, list.i = function(modules, mediaQuery) {
21375            "string" == typeof modules && (modules = [ [ null, modules, "" ] ]);
21376            for (var alreadyImportedModules = {}, i = 0; i < this.length; i++) {
21377                var id = this[i][0];
21378                "number" == typeof id && (alreadyImportedModules[id] = !0);
21379            }
21380            for (i = 0; i < modules.length; i++) {
21381                var item = modules[i];
21382                "number" == typeof item[0] && alreadyImportedModules[item[0]] || (mediaQuery && !item[2] ? item[2] = mediaQuery : mediaQuery && (item[2] = "(" + item[2] + ") and (" + mediaQuery + ")"), 
21383                list.push(item));
21384            }
21385        }, list;
21386    };
21387}, function(module, exports, __webpack_require__) {
21388    function addStylesToDom(styles, options) {
21389        for (var i = 0; i < styles.length; i++) {
21390            var item = styles[i], domStyle = stylesInDom[item.id];
21391            if (domStyle) {
21392                domStyle.refs++;
21393                for (j = 0; j < domStyle.parts.length; j++) domStyle.parts[j](item.parts[j]);
21394                for (;j < item.parts.length; j++) domStyle.parts.push(addStyle(item.parts[j], options));
21395            } else {
21396                for (var parts = [], j = 0; j < item.parts.length; j++) parts.push(addStyle(item.parts[j], options));
21397                stylesInDom[item.id] = {
21398                    id: item.id,
21399                    refs: 1,
21400                    parts: parts
21401                };
21402            }
21403        }
21404    }
21405    function listToStyles(list, options) {
21406        for (var styles = [], newStyles = {}, i = 0; i < list.length; i++) {
21407            var item = list[i], id = options.base ? item[0] + options.base : item[0], part = {
21408                css: item[1],
21409                media: item[2],
21410                sourceMap: item[3]
21411            };
21412            newStyles[id] ? newStyles[id].parts.push(part) : styles.push(newStyles[id] = {
21413                id: id,
21414                parts: [ part ]
21415            });
21416        }
21417        return styles;
21418    }
21419    function insertStyleElement(options, style) {
21420        var target = getElement(options.insertInto);
21421        if (!target) throw new Error("Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invali
21421d.");
21422        var lastStyleElementInsertedAtTop = stylesInsertedAtTop[stylesInsertedAtTop.length - 1];
21423        if ("top" === options.insertAt) lastStyleElementInsertedAtTop ? lastStyleElementInsertedAtTop.nextSibling ? target.insertBefore(style, lastStyleElementInsertedAtTop.nextSibling) : target.appendChild(style) : target.insertBefore(style, target.firstChild), 
21424        stylesInsertedAtTop.push(style); else if ("bottom" === options.insertAt) target.appendChild(style); else {
21425            if ("object" != typeof options.insertAt || !options.insertAt.before) throw new Error("[Style Loader]\n\n Invalid value for parameter 'insertAt' ('options.insertAt') found.\n Must be 'top', 'bottom', or Object.\n (https://github.com/webpack-contrib/style-loader#insertat)\n");
21426            var nextSibling = getElement(options.insertInto + " " + options.insertAt.before);
21427            target.insertBefore(style, nextSibling);
21428        }
21429    }
21430    function removeStyleElement(style) {
21431        if (null === style.parentNode) return !1;
21432        style.parentNode.removeChild(style);
21433        var idx = stylesInsertedAtTop.indexOf(style);
21434        idx >= 0 && stylesInsertedAtTop.splice(idx, 1);
21435    }
21436    function createStyleElement(options) {
21437        var style = document.createElement("style");
21438        return options.attrs.type = "text/css", addAttrs(style, options.attrs), insertStyleElement(options, style), 
21439        style;
21440    }
21441    function createLinkElement(options) {
21442        var link = document.createElement("link");
21443        return options.attrs.type = "text/css", options.attrs.rel = "stylesheet", addAttrs(link, options.attrs), 
21444        insertStyleElement(options, link), link;
21445    }
21446    function addAttrs(el, attrs) {
21447        Object.keys(attrs).forEach(function(key) {
21448            el.setAttribute(key, attrs[key]);
21449        });
21450    }
21451    function addStyle(obj, options) {
21452        var style, update, remove, result;
21453        if (options.transform && obj.css) {
21454            if (!(result = options.transform(obj.css))) return function() {};
21455            obj.css = result;
21456        }
21457        if (options.singleton) {
21458            var styleIndex = singletonCounter++;
21459            style = singleton || (singleton = createStyleElement(options)), update = applyToSingletonTag.bind(null, style, styleIndex, !1), 
21460            remove = applyToSingletonTag.bind(null, style, styleIndex, !0);
21461        } else obj.sourceMap && "function" == typeof URL && "function" == typeof URL.createObjectURL && "function" == typeof URL.revokeObjectURL && "function" == typeof Blob && "function" == typeof btoa ? (style = createLinkElement(options), 
21462        update = updateLink.bind(null, style, options), remove = function() {
21463            removeStyleElement(style), style.href && URL.revokeObjectURL(style.href);
21464        }) : (style = createStyleElement(options), update = applyToTag.bind(null, style), 
21465        remove = function() {
21466            removeStyleElement(style);
21467        });
21468        return update(obj), function(newObj) {
21469            if (newObj) {
21470                if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap) return;
21471                update(obj = newObj);
21472            } else remove();
21473        };
21474    }
21475    function applyToSingletonTag(style, index, remove, obj) {
21476        var css = remove ? "" : obj.css;
21477        if (style.styleSheet) style.styleSheet.cssText = replaceText(index, css); else {
21478            var cssNode = document.createTextNode(css), childNodes = style.childNodes;
21479            childNodes[index] && style.removeChild(childNodes[index]), childNodes.length ? style.insertBefore(cssNode, childNodes[index]) : style.appendChild(cssNode);
21480        }
21481    }
21482    function applyToTag(style, obj) {
21483        var css = obj.css, media = obj.media;
21484        if (media && style.setAttribute("media", media), style.styleSheet) style.styleSheet.cssText = css; else {
21485            for (;style.firstChild; ) style.removeChild(style.firstChild);
21486            style.appendChild(document.createTextNode(css));
21487        }
21488    }
21489    function updateLink(link, options, obj) {
21490        var css = obj.css, sourceMap = obj.sourceMap, autoFixUrls = void 0 === options.convertToAbsoluteUrls && sourceMap;
21491        (options.convertToAbsoluteUrls || autoFixUrls) && (css = fixUrls(css)), sourceMap && (css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)
21491))) + " */");
21492        var blob = new Blob([ css ], {
21493            type: "text/css"
21494        }), oldSrc = link.href;
21495        link.href = URL.createObjectURL(blob), oldSrc && URL.revokeObjectURL(oldSrc);
21496    }
21497    var stylesInDom = {}, isOldIE = function(fn) {
21498        var memo;
21499        return function() {
21500            return void 0 === memo && (memo = fn.apply(this, arguments)), memo;
21501        };
21502    }(function() {
21503        return window && document && document.all && !window.atob;
21504    }), getElement = function(fn) {
21505        var memo = {};
21506        return function(selector) {
21507            if (void 0 === memo[selector]) {
21508                var styleTarget = fn.call(this, selector);
21509                if (styleTarget instanceof window.HTMLIFrameElement) try {
21510                    styleTarget = styleTarget.contentDocument.head;
21511                } catch (e) {
21512                    styleTarget = null;
21513                }
21514                memo[selector] = styleTarget;
21515            }
21516            return memo[selector];
21517        };
21518    }(function(target) {
21519        return document.querySelector(target);
21520    }), singleton = null, singletonCounter = 0, stylesInsertedAtTop = [], fixUrls = __webpack_require__(8);
21521    module.exports = function(list, options) {
21522        if ("undefined" != typeof DEBUG && DEBUG && "object" != typeof document) throw new Error("The style-loader cannot be used in a non-browser environment");
21523        (options = options || {}).attrs = "object" == typeof options.attrs ? options.attrs : {}, 
21524        options.singleton || (options.singleton = isOldIE()), options.insertInto || (options.insertInto = "head"), 
21525        options.insertAt || (options.insertAt = "bottom");
21526        var styles = listToStyles(list, options);
21527        return addStylesToDom(styles, options), function(newList) {
21528            for (var mayRemove = [], i = 0; i < styles.length; i++) {
21529                var item = styles[i];
21530                (domStyle = stylesInDom[item.id]).refs--, mayRemove.push(domStyle);
21531            }
21532            newList && addStylesToDom(listToStyles(newList, options), options);
21533            for (i = 0; i < mayRemove.length; i++) {
21534                var domStyle = mayRemove[i];
21535                if (0 === domStyle.refs) {
21536                    for (var j = 0; j < domStyle.parts.length; j++) domStyle.parts[j]();
21537                    delete stylesInDom[domStyle.id];
21538                }
21539            }
21540        };
21541    };
21542    var replaceText = function() {
21543        var textStore = [];
21544        return function(index, replacement) {
21545            return textStore[index] = replacement, textStore.filter(Boolean).join("\n");
21546        };
21547    }();
21548}, function(module, exports) {
21549    module.exports = function(css) {
21550        var location = "undefined" != typeof window && window.location;
21551        if (!location) throw new Error("fixUrls requires window.location");
21552        if (!css || "string" != typeof css) return css;
21553        var baseUrl = location.protocol + "//" + location.host, currentDir = baseUrl + location.pathname.replace(/\/[^\/]*$/, "/");
21554        return css.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi, function(fullMatch, origUrl) {
21555            var unquotedOrigUrl = origUrl.trim().replace(/^"(.*)"$/, function(o, $1) {
21556                return $1;
21557            }).replace(/^'(.*)'$/, function(o, $1) {
21558                return $1;
21559            });
21560            if (/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/)/i.test(unquotedOrigUrl)) return fullMatch;
21561            var newUrl;
21562            return newUrl = 0 === unquotedOrigUrl.indexOf("//") ? unquotedOrigUrl : 0 === unquotedOrigUrl.indexOf("/") ? baseUrl + unquotedOrigUrl : currentDir + unquotedOrigUrl.replace(/^\.\//, ""), 
21563            "url(" + JSON.stringify(newUrl) + ")";
21564        });
21565    };
21566}, function(module, exports, __webpack_require__) {
21567    "use strict";
21568    var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
21569    "function" == typeof Symbol && Symbol.iterator;
21570    !function(factory) {
21571        __WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(0), __webpack_require__(1) ], 
21572        void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = "function" == typeof (__WEBPACK_AMD_DEFINE_FACTORY__ = factory) ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
21573    }(function($, Inputmask) {
21574        function isLeapYear(year) {
21575            return isNaN(year) || 29 === new Date(year, 2, 0).getDate();
21576        }
21577        return Inputmask.extendAliases({
21578            "dd/mm/yyyy": {
21579                mask: "1/2/y",
21580                placeholder: "dd/mm/yyyy",
21581                regex: {
21582                    val1pre: new RegExp("[0-3]"),
21583                    val1: new RegExp("0[1-9]|[12][0-9]|3[01]"),
21584                    val2pre: function(separator) {
21585                        var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
21586                        return new RegExp("((0[1-9]|[12][0-9]|3[01])" + escapedSeparator + "[01])");
21587                    },
21588                    val2: function(separator) {
21589                        var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
21590                        return new RegExp("((0[1-9]|[12][0-9])" + escapedSeparator + "(0[1-9]|1[012]))|(30" + escapedSeparator + "(0[13-9]|1[012]))|(31" + escapedSeparator + "(0[13578]|1[02]))");
21591                    }
21592                },
21593                leapday: "29/02/",
21594                separator: "/",
21595                yearrange: {
21596                    minyear: 1900,
21597                    maxyear: 2099
21598                },
21599                isInYearRange: function(chrs, minyear, maxyear) {
21600                    if (isNaN(chrs)) return !1;
21601                    var enteredyear = parseInt(chrs.concat(minyear.toString().slice(chrs.length))), enteredyear2 = parseInt(chrs.concat(maxyear.toString().slice(chrs.length)));
21602                    return !isNaN(enteredyear) && (minyear <= enteredyear && enteredyear <= maxyear) || !isNaN(enteredyear2) && (minyear <= enteredyear2 && enteredyear2 <= maxyear);
21603                },
21604                determinebaseyear: function(minyear, maxyear, hint) {
21605                    var currentyear = new Date().getFullYear();
21606                    if (minyear > currentyear) return minyear;
21607                    if (maxyear < currentyear) {
21608                        for (var maxYearPrefix = maxyear.toString().slice(0, 2), maxYearPostfix = maxyear.toString().slice(2, 4); maxyear < maxYearPrefix + hint; ) maxYearPrefix--;
21609                        var maxxYear = maxYearPrefix + maxYearPostfix;
21610                        return minyear > maxxYear ? minyear : maxxYear;
21611                    }
21612                    if (minyear <= currentyear && currentyear <= maxyear) {
21613                        for (var currentYearPrefix = currentyear.toString().slice(0, 2); maxyear < currentYearPrefix + hint; ) currentYearPrefix--;
21614                        var currentYearAndHint = currentYearPrefix + hint;
21615                        return currentYearAndHint < minyear ? minyear : currentYearAndHint;
21616                    }
21617                    return currentyear;
21618                },
21619                onKeyDown: function(e, buffer, caretPos, opts) {
21620                    var $input = $(this);
21621                    if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) {
21622                        var today = new Date();
21623                        $input.val(today.getDate().toString() + (today.getMonth() + 1).toString() + today.getFullYear().toString()), 
21624                        $input.trigger("setvalue");
21625                    }
21626                },
21627                getFrontValue: function(mask, buffer, opts) {
21628                    for (var start = 0, length = 0, i = 0; i < mask.length && "2" !== mask.charAt(i); i++) {
21629                        var definition = opts.definitions[mask.charAt(i)];
21630                        definition ? (start += length, length = definition.cardinality) : length++;
21631                    }
21632                    return buffer.join("").substr(start, length);
21633                },
21634                postValidation: function(buffer, currentResult, opts) {
21635                    var dayMonthValue, year, bufferStr = buffer.join("");
21636                    return 0 === opts.mask.indexOf("y") ? (year = bufferStr.substr(0, 4), dayMonthValue = bufferStr.substring(4, 10)) : (year = bufferStr.substring(6, 10), 
21637                    dayMonthValue = bufferStr.substr(0, 6)), currentResult && (dayMonthValue !== opts.leapday || isLeapYear(year));
21638                },
21639                definitions: {
21640                    "1": {
21641                        validator: function(chrs, maskset, pos, strict, opts) {
21642                            var isValid = opts.regex.val1.test(chrs);
21643                            return strict || isValid || chrs.charAt(1) !== opts.separator && -1 === "-./".indexOf(chrs.charAt(1)) || !(isValid = opts.regex.val1.test("0" + chrs.charAt(0))) ? isValid : (maskset.buffer[pos - 1] = "0", 
21644                            {
21645                                refreshFromBuffer: {
21646                                    start: pos - 1,
21647                                    end: pos
21648                                },
21649                                pos: pos,
21650                                c: chrs.charAt(0)
21651                            });
21652                        },
21653                        cardinality: 2,
21654                        prevalidator: [ {
21655                            validator: function(chrs, maskset, pos, strict, opts) {
21656                                var pchrs = chrs;
21657                                isNaN(maskset.buffer[pos + 1]) || (pchrs += maskset.buffer[pos + 1]);
21658                                var isValid = 1 === pchrs.length ? opts.regex.val1pre.test(pchrs) : opts.regex.val1.test(pchrs);
21659                                if (isValid && maskset.validPositions[pos] && (opts.regex.val2(opts.separator).test(chrs + maskset.validPositions[pos].input) || (maskset.validPositions[pos].input = "0" === chrs ? "1" : "0")), 
21660                                !strict && !isValid) {
21661                                    if (isValid = opts.regex.val1.test(chrs + "0")) return maskset.buffer[pos] = chrs, 
21662                                    maskset.buffer[++pos] = "0", {
21663                                        pos: pos,
21664                                        c: "0"
21665                                    };
21666                                    if (isValid = opts.regex.val1.test("0" + chrs)) return maskset.buffer[pos] = "0", 
21667                                    pos++, {
21668                                        pos: pos
21669                                    };
21670                                }
21671                                return isValid;
21672                            },
21673                            cardinality: 1
21674                        } ]
21675                    },
21676                    "2": {
21677                        validator: function(chrs, maskset, pos, strict, opts) {
21678                            var frontValue = opts.getFrontValue(maskset.mask, maskset.buffer, opts);
21679                            -1 !== frontValue.indexOf(opts.placeholder[0]) && (frontValue = "01" + opts.separator);
21680                            var isValid = opts.regex.val2(opts.separator).test(frontValue + chrs);
21681                            return strict || isValid || chrs.charAt(1) !== opts.separator && -1 === "-./".indexOf(chrs.charAt(1)) || !(isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs.charAt(0))) ? isValid : (maskset.buffer[pos - 1] = "0", 
21682                            {
21683                                refreshFromBuffer: {
21684                                    start: pos - 1,
21685                                    end: pos
21686                                },
21687                                pos: pos,
21688                                c: chrs.charAt(0)
21689                            });
21690                        },
21691                        cardinality: 2,
21692                        prevalidator: [ {
21693                            validator: function(chrs, maskset, pos, strict, opts) {
21694                                isNaN(maskset.buffer[pos + 1]) || (chrs += maskset.buffer[pos + 1]);
21695                                var frontValue = opts.getFrontValue(maskset.mask, maskset.buffer, opts);
21696                                -1 !== frontValue.indexOf(opts.placeholder[0]) && (frontValue = "01" + opts.separator);
21697                                var isValid = 1 === chrs.length ? opts.regex.val2pre(opts.separator).test(frontValue + chrs) : opts.regex.val2(opts.separator).test(frontValue + chrs);
21698                                return isValid && maskset.validPositions[pos] && (opts.regex.val2(opts.separator).test(chrs + maskset.validPositions[pos].input) || (maskset.validPositions[pos].input = "0" === chrs ? "1" : "0")), 
21699                                strict || isValid || !(isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs)) ? isValid : (maskset.buffer[pos] = "0", 
21700                                pos++, {
21701                                    pos: pos
21702                                });
21703                            },
21704                            cardinality: 1
21705                        } ]
21706                    },
21707                    y: {
21708                        validator: function(chrs, maskset, pos, strict, opts) {
21709                            return opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
21710                        },
21711                        cardinality: 4,
21712                        prevalidator: [ {
21713                            validator: function(chrs, maskset, pos, strict, opts) {
21714                                var isValid = opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
21715                                if (!strict && !isValid) {
21716                                    var yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs + "0").toString().slice(0, 1);
21717                                    if (isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos++] = yearPrefix.charAt(0), 
21718                                    {
21719                                        pos: pos
21720                                    };
21721                                    if (yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs + "0").toString().slice(0, 2), 
21722                                    isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos++] = yearPrefix.charAt(0), 
21723                                    maskset.buffer[pos++] = yearPrefix.charAt(1), {
21724                                        pos: pos
21725                                    };
21726                                }
21727                                return isValid;
21728                            },
21729                            cardinality: 1
21730                        }, {
21731                            validator: function(chrs, maskset, pos, strict, opts) {
21732                                var isValid = opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
21733                                if (!strict && !isValid) {
21734                                    var yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs).toString().slice(0, 2);
21735                                    if (isValid = opts.isInYearRange(chrs[0] + yearPrefix[1] + chrs[1], opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos++] = yearPrefix.charAt(1), 
21736                                    {
21737                                        pos: pos
21738                                    };
21739                                    if (yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs).toString().slice(0, 2), 
21740                                    isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos - 1] = yearPrefix.charAt(0), 
21741                                    maskset.buffer[pos++] = yearPrefix.charAt(1), maskset.buffer[pos++] = chrs.charAt(0), 
21742                                    {
21743                                        refreshFromBuffer: {
21744                                            start: pos - 3,
21745                                            end: pos
21746                                        },
21747                                        pos: pos
21748                                    };
21749                                }
21750                                return isValid;
21751                            },
21752                            cardinality: 2
21753                        }, {
21754                            validator: function(chrs, maskset, pos, strict, opts) {
21755                                return opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
21756                            },
21757                            cardinality: 3
21758                        } ]
21759                    }
21760                },
21761                insertMode: !1,
21762                autoUnmask: !1
21763            },
21764            "mm/dd/yyyy": {
21765                placeholder: "mm/dd/yyyy",
21766                alias: "dd/mm/yyyy",
21767                regex: {
21768                    val2pre: function(separator) {
21769                        var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
21770                        return new RegExp("((0[13-9]|1[012])" + escapedSeparator + "[0-3])|(02" + escapedSeparator + "[0-2])");
21771                    },
21772                    val2: function(separator) {
21773                        var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
21774                        return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[13-9]|1[012])" + escapedSeparator + "30)|((0[13578]|1[02])" + escapedSeparator + "31)");
21775                    },
21776                    val1pre: new RegExp("[01]"),
21777                    val1: new RegExp("0[1-9]|1[012]")
21778                },
21779                leapday: "02/29/",
21780                onKeyDown: function(e, buffer, caretPos, opts) {
21781                    var $input = $(this);
21782                    if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) {
21783                        var today = new Date();
21784                        $input.val((today.getMonth() + 1).toString() + today.getDate().toString() + today.getFullYear().toString()), 
21785                        $input.trigger("setvalue");
21786                    }
21787                }
21788            },
21789            "yyyy/mm/dd": {
21790                mask: "y/1/2",
21791                placeholder: "yyyy/mm/dd",
21792                alias: "mm/dd/yyyy",
21793                leapday: "/02/29",
21794                onKeyDown: function(e, buffer, caretPos, opts) {
21795                    var $input = $(this);
21796                    if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) {
21797                        var today = new Date();
21798                        $input.val(today.getFullYear().toString() + (today.getMonth() + 1).toString() + today.getDate().toString()), 
21799                        $input.trigger("setvalue");
21800                    }
21801                }
21802            },
21803            "dd.mm.yyyy": {
21804                mask: "1.2.y",
21805                placeholder: "dd.mm.yyyy",
21806                leapday: "29.02.",
21807                separator: ".",
21808                alias: "dd/mm/yyyy"
21809            },
21810            "dd-mm-yyyy": {
21811                mask: "1-2-y",
21812                placeholder: "dd-mm-yyyy",
21813                leapday: "29-02-",
21814                separator: "-",
21815                alias: "dd/mm/yyyy"
21816            },
21817            "mm.dd.yyyy": {
21818                mask: "1.2.y",
21819                placeholder: "mm.dd.yyyy",
21820                leapday: "02.29.",
21821                separator: ".",
21822                alias: "mm/dd/yyyy"
21823            },
21824            "mm-dd-yyyy": {
21825                mask: "1-2-y",
21826                placeholder: "mm-dd-yyyy",
21827                leapday: "02-29-",
21828                separator: "-",
21829                alias: "mm/dd/yyyy"
21830            },
21831            "yyyy.mm.dd": {
21832                mask: "y.1.2",
21833                placeholder: "yyyy.mm.dd",
21834                leapday: ".02.29",
21835                separator: ".",
21836                alias: "yyyy/mm/dd"
21837            },
21838            "yyyy-mm-dd": {
21839                mask: "y-1-2",
21840                placeholder: "yyyy-mm-dd",
21841                leapday: "-02-29",
21842                separator: "-",
21843                alias: "yyyy/mm/dd"
21844            },
21845            datetime: {
21846                mask: "1/2/y h:s",
21847                placeholder: "dd/mm/yyyy hh:mm",
21848                alias: "dd/mm/yyyy",
21849                regex: {
21850                    hrspre: new RegExp("[012]"),
21851                    hrs24: new RegExp("2[0-4]|1[3-9]"),
21852                    hrs: new RegExp("[01][0-9]|2[0-4]"),
21853                    ampm: new RegExp("^[a|p|A|P][m|M]"),
21854                    mspre: new RegExp("[0-5]"),
21855                    ms: new RegExp("[0-5][0-9]")
21856                },
21857                timeseparator: ":",
21858                hourFormat: "24",
21859                definitions: {
21860                    h: {
21861                        validator: function(chrs, maskset, pos, strict, opts) {
21862                            if ("24" === opts.hourFormat && 24 === parseInt(chrs, 10)) return maskset.buffer[pos - 1] = "0", 
21863                            maskset.buffer[pos] = "0", {
21864                                refreshFromBuffer: {
21865                                    start: pos - 1,
21866                                    end: pos
21867                                },
21868                                c: "0"
21869                            };
21870                            var isValid = opts.regex.hrs.test(chrs);
21871                            if (!strict && !isValid && (chrs.charAt(1) === opts.timeseparator || -1 !== "-.:".indexOf(chrs.charAt(1))) && (isValid = opts.regex.hrs.test("0" + chrs.charAt(0)))) return maskset.buffer[pos - 1] = "0", 
21872                            maskset.buffer[pos] = chrs.charAt(0), pos++, {
21873                                refreshFromBuffer: {
21874                                    start: pos - 2,
21875                                    end: pos
21876                                },
21877                                pos: pos,
21878                                c: opts.timeseparator
21879                            };
21880                            if (isValid && "24" !== opts.hourFormat && opts.regex.hrs24.test(chrs)) {
21881                                var tmp = parseInt(chrs, 10);
21882                                return 24 === tmp ? (maskset.buffer[pos + 5] = "a", maskset.buffer[pos + 6] = "m") : (maskset.buffer[pos + 5] = "p", 
21883                                maskset.buffer[pos + 6] = "m"), (tmp -= 12) < 10 ? (maskset.buffer[pos] = tmp.toString(), 
21884                                maskset.buffer[pos - 1] = "0") : (maskset.buffer[pos] = tmp.toString().charAt(1), 
21885                                maskset.buffer[pos - 1] = tmp.toString().charAt(0)), {
21886                                    refreshFromBuffer: {
21887                                        start: pos - 1,
21888                                        end: pos + 6
21889                                    },
21890                                    c: maskset.buffer[pos]
21891                                };
21892                            }
21893                            return isValid;
21894                        },
21895                        cardinality: 2,
21896                        prevalidator: [ {
21897                            validator: function(chrs, maskset, pos, strict, opts) {
21898                                var isValid = opts.regex.hrspre.test(chrs);
21899                                return strict || isValid || !(isValid = opts.regex.hrs.test("0" + chrs)) ? isValid : (maskset.buffer[pos] = "0", 
21900                                pos++, {
21901                                    pos: pos
21902                                });
21903                            },
21904                            cardinality: 1
21905                        } ]
21906                    },
21907                    s: {
21908                        validator: "[0-5][0-9]",
21909                        cardinality: 2,
21910                        prevalidator: [ {
21911                            validator: function(chrs, maskset, pos, strict, opts) {
21912                                var isValid = opts.regex.mspre.test(chrs);
21913                                return strict || isValid || !(isValid = opts.regex.ms.test("0" + chrs)) ? isValid : (maskset.buffer[pos] = "0", 
21914                                pos++, {
21915                                    pos: pos
21916                                });
21917                            },
21918                            cardinality: 1
21919                        } ]
21920                    },
21921                    t: {
21922                        validator: function(chrs, maskset, pos, strict, opts) {
21923                            return opts.regex.ampm.test(chrs + "m");
21924                        },
21925                        casing: "lower",
21926                        cardinality: 1
21927                    }
21928                },
21929                insertMode: !1,
21930                autoUnmask: !1
21931            },
21932            datetime12: {
21933                mask: "1/2/y h:s t\\m",
21934                placeholder: "dd/mm/yyyy hh:mm xm",
21935                alias: "datetime",
21936                hourFormat: "12"
21937            },
21938            "mm/dd/yyyy hh:mm xm": {
21939                mask: "1/2/y h:s t\\m",
21940                placeholder: "mm/dd/yyyy hh:mm xm",
21941                alias: "datetime12",
21942                regex: {
21943                    val2pre: function(separator) {
21944                        var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
21945                        return new RegExp("((0[13-9]|1[012])" + escapedSeparator + "[0-3])|(02" + escapedSeparator + "[0-2])");
21946                    },
21947                    val2: function(separator) {
21948                        var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
21949                        return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[13-9]|1[012])" + escapedSeparator + "30)|((0[13578]|1[02])" + escapedSeparator + "31)");
21950                    },
21951                    val1pre: new RegExp("[01]"),
21952                    val1: new RegExp("0[1-9]|1[012]")
21953                },
21954                leapday: "02/29/",
21955                onKeyDown: function(e, buffer, caretPos, opts) {
21956                    var $input = $(this);
21957                    if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) {
21958                        var today = new Date();
21959                        $input.val((today.getMonth() + 1).toString() + today.getDate().toString() + today.getFullYear().toString()), 
21960                        $input.trigger("setvalue");
21961                    }
21962                }
21963            },
21964            "hh:mm t": {
21965                mask: "h:s t\\m",
21966                placeholder: "hh:mm xm",
21967                alias: "datetime",
21968                hourFormat: "12"
21969            },
21970            "h:s t": {
21971                mask: "h:s t\\m",
21972                placeholder: "hh:mm xm",
21973                alias: "datetime",
21974                hourFormat: "12"
21975            },
21976            "hh:mm:ss": {
21977                mask: "h:s:s",
21978                placeholder: "hh:mm:ss",
21979                alias: "datetime",
21980                autoUnmask: !1
21981            },
21982            "hh:mm": {
21983                mask: "h:s",
21984                placeholder: "hh:mm",
21985                alias: "datetime",
21986                autoUnmask: !1
21987            },
21988            date: {
21989                alias: "dd/mm/yyyy"
21990            },
21991            "mm/yyyy": {
21992                mask: "1/y",
21993                placeholder: "mm/yyyy",
21994                leapday: "donotuse",
21995                separator: "/",
21996                alias: "mm/dd/yyyy"
21997            },
21998            shamsi: {
21999                regex: {
22000                    val2pre: function(separator) {
22001                        var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
22002                        return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "[0-3])");
22003                    },
22004                    val2: function(separator) {
22005                        var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
22006                        return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[1-9]|1[012])" + escapedSeparator + "30)|((0[1-6])" + escapedSeparator + "31)");
22007                    },
22008                    val1pre: new RegExp("[01]"),
22009                    val1: new RegExp("0[1-9]|1[012]")
22010                },
22011                yearrange: {
22012                    minyear: 1300,
22013                    maxyear: 1499
22014                },
22015                mask: "y/1/2",
22016                leapday: "/12/30",
22017                placeholder: "yyyy/mm/dd",
22018                alias: "mm/dd/yyyy",
22019                clearIncomplete: !0
22020            },
22021            "yyyy-mm-dd hh:mm:ss": {
22022                mask: "y-1-2 h:s:s",
22023                placeholder: "yyyy-mm-dd hh:mm:ss",
22024                alias: "datetime",
22025                separator: "-",
22026                leapday: "-02-29",
22027                regex: {
22028                    val2pre: function(separator) {
22029                        var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
22030                        return new RegExp("((0[13-9]|1[012])" + escapedSeparator + "[0-3])|(02" + escapedSeparator + "[0-2])");
22031                    },
22032                    val2: function(separator) {
22033                        var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
22034                        return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[13-9]|1[012])" + escapedSeparator + "30)|((0[13578]|1[02])" + escapedSeparator + "31)");
22035                    },
22036                    val1pre: new RegExp("[01]"),
22037                    val1: new RegExp("0[1-9]|1[012]")
22038                },
22039                onKeyDown: function(e, buffer, caretPos, opts) {}
22040            }
22041        }), Inputmask;
22042    });
22043}, function(module, exports, __webpack_require__) {
22044    "use strict";
22045    var __WEBPACK_AMD_DEFINE_RESULT__;
22046    "function" == typeof Symbol && Symbol.iterator;
22047    void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = function() {
22048        return window;
22049    }.call(exports, __webpack_require__, exports, module)) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
22050}, function(module, exports, __webpack_require__) {
22051    "use strict";
22052    var __WEBPACK_AMD_DEFINE_RESULT__;
22053    "function" == typeof Symbol && Symbol.iterator;
22054    void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = function() {
22055        return document;
22056    }.call(exports, __webpack_require__, exports, module)) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
22057}, function(module, exports, __webpack_require__) {
22058    "use strict";
22059    var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
22060    "function" == typeof Symbol && Symbol.iterator;
22061    !function(factory) {
22062        __WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(0), __webpack_require__(1) ], 
22063        void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = "function" == typeof (__WEBPACK_AMD_DEFINE_FACTORY__ = factory) ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
22064    }(function($, Inputmask) {
22065        return Inputmask.extendDefinitions({
22066            A: {
22067                validator: "[A-Za-zА-яЁёÀ-ÿµ]",
22068                cardinality: 1,
22069                casing: "upper"
22070            },
22071            "&": {
22072                validator: "[0-9A-Za-zА-яЁёÀ-ÿµ]",
22073                cardinality: 1,
22074                casing: "upper"
22075            },
22076            "#": {
22077                validator: "[0-9A-Fa-f]",
22078                cardinality: 1,
22079                casing: "upper"
22080            }
22081        }), Inputmask.extendAliases({
22082            url: {
22083                definitions: {
22084                    i: {
22085                        validator: ".",
22086                        cardinality: 1
22087                    }
22088                },
22089                mask: "(\\http://)|(\\http\\s://)|(ftp://)|(ftp\\s://)i{+}",
22090                insertMode: !1,
22091                autoUnmask: !1,
22092                inputmode: "url"
22093            },
22094            ip: {
22095                mask: "i[i[i]].i[i[i]].i[i[i]].i[i[i]]",
22096                definitions: {
22097                    i: {
22098                        validator: function(chrs, maskset, pos, strict, opts) {
22099                            return pos - 1 > -1 && "." !== maskset.buffer[pos - 1] ? (chrs = maskset.buffer[pos - 1] + chrs, 
22100                            chrs = pos - 2 > -1 && "." !== maskset.buffer[pos - 2] ? maskset.buffer[pos - 2] + chrs : "0" + chrs) : chrs = "00" + chrs, 
22101                            new RegExp("25[0-5]|2[0-4][0-9]|[01][0-9][0-9]").test(chrs);
22102                        },
22103                        cardinality: 1
22104                    }
22105                },
22106                onUnMask: function(maskedValue, unmaskedValue, opts) {
22107                    return maskedValue;
22108                },
22109                inputmode: "numeric"
22110            },
22111            email: {
22112                mask: "*{1,64}[.*{1,64}][.*{1,64}][.*{1,63}]@-{1,63}.-{1,63}[.-{1,63}][.-{1,63}]",
22113                greedy: !1,
22114                onBeforePaste: function(pastedValue, opts) {
22115                    return (pastedValue = pastedValue.toLowerCase()).replace("mailto:", "");
22116                },
22117                definitions: {
22118                    "*": {
22119                        validator: "[0-9A-Za-z!#$%&'*+/=?^_`{|}~-]",
22120                        cardinality: 1,
22121                        casing: "lower"
22122                    },
22123                    "-": {
22124                        validator: "[0-9A-Za-z-]",
22125                        cardinality: 1,
22126                        casing: "lower"
22127                    }
22128                },
22129                onUnMask: function(maskedValue, unmaskedValue, opts) {
22130                    return maskedValue;
22131                },
22132                inputmode: "email"
22133            },
22134            mac: {
22135                mask: "##:##:##:##:##:##"
22136            },
22137            vin: {
22138                mask: "V{13}9{4}",
22139                definitions: {
22140                    V: {
22141                        validator: "[A-HJ-NPR-Za-hj-npr-z\\d]",
22142                        cardinality: 1,
22143                        casing: "upper"
22144                    }
22145                },
22146                clearIncomplete: !0,
22147                autoUnmask: !0
22148            }
22149        }), Inputmask;
22150    });
22151}, function(module, exports, __webpack_require__) {
22152    "use strict";
22153    var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
22154    "function" == typeof Symbol && Symbol.iterator;
22155    !function(factory) {
22156        __WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(0), __webpack_require__(1) ], 
22157        void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = "function" == typeof (__WEBPACK_AMD_DEFINE_FACTORY__ = factory) ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
22158    }(function($, Inputmask, undefined) {
22159        function autoEscape(txt, opts) {
22160            for (var escapedTxt = "", i = 0; i < txt.length; i++) Inputmask.prototype.definitions[txt.charAt(i)] || opts.definitions[txt.charAt(i)] || opts.optionalmarker.start === txt.charAt(i) || opts.optionalmarker.end === txt.charAt(i) || opts.quantifiermarker.start === txt.charAt(i) || opts.quantifiermarker.end === txt.charAt(i) || opts.groupmarker.start === txt.charAt(i) || opts.groupmarker.end === txt.charAt(i) || opts.alternatormarker === txt.charAt(i) ? escapedTxt += "\\" + txt.charAt(i) : escapedTxt += txt.charAt(i);
22161            return escapedTxt;
22162        }
22163        return Inputmask.extendAliases({
22164            numeric: {
22165                mask: function(opts) {
22166                    if (0 !== opts.repeat && isNaN(opts.integerDigits) && (opts.integerDigits = opts.repeat), 
22167                    opts.repeat = 0, opts.groupSeparator === opts.radixPoint && ("." === opts.radixPoint ? opts.groupSeparator = "," : "," === opts.radixPoint ? opts.groupSeparator = "." : opts.groupSeparator = ""), 
22168                    " " === opts.groupSeparator && (opts.skipOptionalPartCharacter = undefined), opts.autoGroup = opts.autoGroup && "" !== opts.groupSeparator, 
22169                    opts.autoGroup && ("string" == typeof opts.groupSize && isFinite(opts.groupSize) && (opts.groupSize = parseInt(opts.groupSize)), 
22170                    isFinite(opts.integerDigits))) {
22171                        var seps = Math.floor(opts.integerDigits / opts.groupSize), mod = opts.integerDigits % opts.groupSize;
22172                        opts.integerDigits = parseInt(opts.integerDigits) + (0 === mod ? seps - 1 : seps), 
22173                        opts.integerDigits < 1 && (opts.integerDigits = "*");
22174                    }
22175                    opts.placeholder.length > 1 && (opts.placeholder = opts.placeholder.charAt(0)), 
22176                    "radixFocus" === opts.positionCaretOnClick && "" === opts.placeholder && !1 === opts.integerOptional && (opts.positionCaretOnClick = "lvp"), 
22177                    opts.definitions[";"] = opts.definitions["~"], opts.definitions[";"].definitionSymbol = "~", 
22178                    !0 === opts.numericInput && (opts.positionCaretOnClick = "radixFocus" === opts.positionCaretOnClick ? "lvp" : opts.positionCaretOnClick, 
22179                    opts.digitsOptional = !1, isNaN(opts.digits) && (opts.digits = 2), opts.decimalProtect = !1);
22180                    var mask = "[+]";
22181                    if (mask += autoEscape(opts.prefix, opts), !0 === opts.integerOptional ? mask += "~{1," + opts.integerDigits + "}" : mask += "~{" + opts.integerDigits + "}", 
22182                    opts.digits !== undefined) {
22183                        opts.radixPointDefinitionSymbol = opts.decimalProtect ? ":" : opts.radixPoint;
22184                        var dq = opts.digits.toString().split(",");
22185                        isFinite(dq[0] && dq[1] && isFinite(dq[1])) ? mask += opts.radixPointDefinitionSymbol + ";{" + opts.digits + "}" : (isNaN(opts.digits) || parseInt(opts.digits) > 0) && (opts.digitsOptional ? mask += "[" + opts.radixPointDefinitionSymbol + ";{1," + opts.digits + "}]" : mask += opts.radixPointDefinitionSymbol + ";{" + opts.digits + "}");
22186                    }
22187                    return mask += autoEscape(opts.suffix, opts), mask += "[-]", opts.greedy = !1, mask;
22188                },
22189                placeholder: "",
22190                greedy: !1,
22191                digits: "*",
22192                digitsOptional: !0,
22193                enforceDigitsOnBlur: !1,
22194                radixPoint: ".",
22195                positionCaretOnClick: "radixFocus",
22196                groupSize: 3,
22197                groupSeparator: "",
22198                autoGroup: !1,
22199                allowMinus: !0,
22200                negationSymbol: {
22201                    front: "-",
22202                    back: ""
22203                },
22204                integerDigits: "+",
22205                integerOptional: !0,
22206                prefix: "",
22207                suffix: "",
22208                rightAlign: !0,
22209                decimalProtect: !0,
22210                min: null,
22211                max: null,
22212                step: 1,
22213                insertMode: !0,
22214                autoUnmask: !1,
22215                unmaskAsNumber: !1,
22216                inputmode: "numeric",
22217                preValidation: function(buffer, pos, c, isSelection, opts) {
22218                    if ("-" === c || c === opts.negationSymbol.front) return !0 === opts.allowMinus && (opts.isNegative = opts.isNegative === undefined || !opts.isNegative, 
22219                    "" === buffer.join("") || {
22220                        caret: pos,
22221                        dopost: !0
22222                    });
22223                    if (!1 === isSelection && c === opts.radixPoint && opts.digits !== undefined && (isNaN(opts.digits) || parseInt(opts.digits) > 0)) {
22224                        var radixPos = $.inArray(opts.radixPoint, buffer);
22225                        if (-1 !== radixPos) return !0 === opts.numericInput ? pos === radixPos : {
22226                            caret: radixPos + 1
22227                        };
22228                    }
22229                    return !0;
22230                },
22231                postValidation: function(buffer, currentResult, opts) {
22232                    var suffix = opts.suffix.split(""), prefix = opts.prefix.split("");
22233                    if (currentResult.pos === undefined && currentResult.caret !== undefined && !0 !== currentResult.dopost) return currentResult;
22234                    var caretPos = currentResult.caret !== undefined ? currentResult.caret : currentResult.pos, maskedValue = buffer.slice();
22235                    opts.numericInput && (caretPos = maskedValue.length - caretPos - 1, maskedValue = maskedValue.reverse());
22236                    var charAtPos = maskedValue[caretPos];
22237                    if (charAtPos === opts.groupSeparator && (charAtPos = maskedValue[caretPos += 1]), 
22238                    caretPos === maskedValue.length - opts.suffix.length - 1 && charAtPos === opts.radixPoint) return currentResult;
22239                    charAtPos !== undefined && charAtPos !== opts.radixPoint && charAtPos !== opts.negationSymbol.front && charAtPos !== opts.negationSymbol.back && (maskedValue[caretPos] = "?", 
22240                    opts.prefix.length > 0 && caretPos >= (!1 === opts.isNegative ? 1 : 0) && caretPos < opts.prefix.length - 1 + (!1 === opts.isNegative ? 1 : 0) ? prefix[caretPos - (!1 === opts.isNegative ? 1 : 0)] = "?" : opts.suffix.length > 0 && caretPos >= maskedValue.length - opts.suffix.length - (!1 === opts.isNegative ? 1 : 0) && (suffix[caretPos - (maskedValue.length - opts.suffix.length - (!1 === opts.isNegative ? 1 : 0))] = "?")), 
22241                    prefix = prefix.join(""), suffix = suffix.join("");
22242                    var processValue = maskedValue.join("").replace(prefix, "");
22243                    if (processValue = processValue.replace(suffix, ""), processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
22244                    processValue = processValue.replace(new RegExp("[-" + Inputmask.escapeRegex(opts.negationSymbol.front) + "]", "g"), ""), 
22245                    processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), ""), 
22246                    isNaN(opts.placeholder) && (processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.placeholder), "g"), "")), 
22247                    processValue.length > 1 && 1 !== processValue.indexOf(opts.radixPoint) && ("0" === charAtPos && (processValue = processValue.replace(/^\?/g, "")), 
22248                    processValue = processValue.replace(/^0/g, "")), processValue.charAt(0) === opts.radixPoint && "" !== opts.radixPoint && !0 !== opts.numericInput && (processValue = "0" + processValue), 
22249                    "" !== processValue) {
22250                        if (processValue = processValue.split(""), (!opts.digitsOptional || opts.enforceDigitsOnBlur && "blur" === currentResult.event) && isFinite(opts.digits)) {
22251                            var radixPosition = $.inArray(opts.radixPoint, processValue), rpb = $.inArray(opts.radixPoint, maskedValue);
22252                            -1 === radixPosition && (processValue.push(opts.radixPoint), radixPosition = processValue.length - 1);
22253                            for (var i = 1; i <= opts.digits; i++) opts.digitsOptional && (!opts.enforceDigitsOnBlur || "blur" !== currentResult.event) || processValue[radixPosition + i] !== undefined && processValue[radixPosition + i] !== opts.placeholder.charAt(0) ? -1 !== rpb && maskedValue[rpb + i] !== undefined && (processValue[radixPosition + i] = processValue[radixPosition + i] || maskedValue[rpb + i]) : processValue[radixPosition + i] = currentResult.placeholder || opts.placeholder.charAt(0);
22254                        }
22255                        if (!0 !== opts.autoGroup || "" === opts.groupSeparator || charAtPos === opts.radixPoint && currentResult.pos === undefined && !currentResult.dopost) processValue = processValue.join(""); else {
22256                            var addRadix = processValue[processValue.length - 1] === opts.radixPoint && currentResult.c === opts.radixPoint;
22257                            processValue = Inputmask(function(buffer, opts) {
22258                                var postMask = "";
22259                                if (postMask += "(" + opts.groupSeparator + "*{" + opts.groupSize + "}){*}", "" !== opts.radixPoint) {
22260                                    var radixSplit = buffer.join("").split(opts.radixPoint);
22261                                    radixSplit[1] && (postMask += opts.radixPoint + "*{" + radixSplit[1].match(/^\d*\??\d*/)[0].length + "}");
22262                                }
22263                                return postMask;
22264                            }(processValue, opts), {
22265                                numericInput: !0,
22266                                jitMasking: !0,
22267                                definitions: {
22268                                    "*": {
22269                                        validator: "[0-9?]",
22270                                        cardinality: 1
22271                                    }
22272                                }
22273                            }).format(processValue.join("")), addRadix && (processValue += opts.radixPoint), 
22274                            processValue.charAt(0) === opts.groupSeparator && processValue.substr(1);
22275                        }
22276                    }
22277                    if (opts.isNegative && "blur" === currentResult.event && (opts.isNegative = "0" !== processValue), 
22278                    processValue = prefix + processValue, processValue += suffix, opts.isNegative && (processValue = opts.negationSymbol.front + processValue, 
22279                    processValue += opts.negationSymbol.back), processValue = processValue.split(""), 
22280                    charAtPos !== undefined) if (charAtPos !== opts.radixPoint && charAtPos !== opts.negationSymbol.front && charAtPos !== opts.negationSymbol.back) (caretPos = $.inArray("?", processValue)) > -1 ? processValue[caretPos] = charAtPos : caretPos = currentResult.caret || 0; else if (charAtPos === opts.radixPoint || charAtPos === opts.negationSymbol.front || charAtPos === opts.negationSymbol.back) {
22281                        var newCaretPos = $.inArray(charAtPos, processValue);
22282                        -1 !== newCaretPos && (caretPos = newCaretPos);
22283                    }
22284                    opts.numericInput && (caretPos = processValue.length - caretPos - 1, processValue = processValue.reverse());
22285                    var rslt = {
22286                        caret: charAtPos === undefined || currentResult.pos !== undefined ? caretPos + (opts.numericInput ? -1 : 1) : caretPos,
22287                        buffer: processValue,
22288                        refreshFromBuffer: currentResult.dopost || buffer.join("") !== processValue.join("")
22289                    };
22290                    return rslt.refreshFromBuffer ? rslt : currentResult;
22291                },
22292                onBeforeWrite: function(e, buffer, caretPos, opts) {
22293                    if (e) switch (e.type) {
22294                      case "keydown":
22295                        return opts.postValidation(buffer, {
22296                            caret: caretPos,
22297                            dopost: !0
22298                        }, opts);
22299
22300                      case "blur":
22301                      case "checkval":
22302                        var unmasked;
22303                        if (function(opts) {
22304                            opts.parseMinMaxOptions === undefined && (null !== opts.min && (opts.min = opts.min.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
22305                            "," === opts.radixPoint && (opts.min = opts.min.replace(opts.radixPoint, ".")), 
22306                            opts.min = isFinite(opts.min) ? parseFloat(opts.min) : NaN, isNaN(opts.min) && (opts.min = Number.MIN_VALUE)), 
22307                            null !== opts.max && (opts.max = opts.max.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
22308                            "," === opts.radixPoint && (opts.max = opts.max.replace(opts.radixPoint, ".")), 
22309                            opts.max = isFinite(opts.max) ? parseFloat(opts.max) : NaN, isNaN(opts.max) && (opts.max = Number.MAX_VALUE)), 
22310                            opts.parseMinMaxOptions = "done");
22311                        }(opts), null !== opts.min || null !== opts.max) {
22312                            if (unmasked = opts.onUnMask(buffer.join(""), undefined, $.extend({}, opts, {
22313                                unmaskAsNumber: !0
22314                            })), null !== opts.min && unmasked < opts.min) return opts.isNegative = opts.min < 0, 
22315                            opts.postValidation(opts.min.toString().replace(".", opts.radixPoint).split(""), {
22316                                caret: caretPos,
22317                                dopost: !0,
22318                                placeholder: "0"
22319                            }, opts);
22320                            if (null !== opts.max && unmasked > opts.max) return opts.isNegative = opts.max < 0, 
22321                            opts.postValidation(opts.max.toString().replace(".", opts.radixPoint).split(""), {
22322                                caret: caretPos,
22323                                dopost: !0,
22324                                placeholder: "0"
22325                            }, opts);
22326                        }
22327                        return opts.postValidation(buffer, {
22328                            caret: caretPos,
22329                            placeholder: "0",
22330                            event: "blur"
22331                        }, opts);
22332
22333                      case "_checkval":
22334                        return {
22335                            caret: caretPos
22336                        };
22337                    }
22338                },
22339                regex: {
22340                    integerPart: function(opts, emptyCheck) {
22341                        return emptyCheck ? new RegExp("[" + Inputmask.escapeRegex(opts.negationSymbol.front) + "+]?") : new RegExp("[" + Inputmask.escapeRegex(opts.negationSymbol.front) + "+]?\\d+");
22342                    },
22343                    integerNPart: function(opts) {
22344                        return new RegExp("[\\d" 
22344+ Inputmask.escapeRegex(opts.groupSeparator) + Inputmask.escapeRegex(opts.placeholder.charAt(0)) + "]+");
22345                    }
22346                },
22347                definitions: {
22348                    "~": {
22349                        validator: function(chrs, maskset, pos, strict, opts, isSelection) {
22350                            var isValid = strict ? new RegExp("[0-9" + Inputmask.escapeRegex(opts.groupSeparator) + "]").test(chrs) : new RegExp("[0-9]").test(chrs);
22351                            if (!0 === isValid) {
22352                                if (!0 !== opts.numericInput && maskset.validPositions[pos] !== undefined && "~" === maskset.validPositions[pos].match.def && !isSelection) {
22353                                    var processValue = maskset.buffer.join(""), pvRadixSplit = (processValue = (processValue = processValue.replace(new RegExp("[-" + Inputmask.escapeRegex(opts.negationSymbol.front) + "]", "g"), "")).replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), "")).split(opts.radixPoint);
22354                                    pvRadixSplit.length > 1 && (pvRadixSplit[1] = pvRadixSplit[1].replace(/0/g, opts.placeholder.charAt(0))), 
22355                                    "0" === pvRadixSplit[0] && (pvRadixSplit[0] = pvRadixSplit[0].replace(/0/g, opts.placeholder.charAt(0))), 
22356                                    processValue = pvRadixSplit[0] + opts.radixPoint + pvRadixSplit[1] || "";
22357                                    var bufferTemplate = maskset._buffer.join("");
22358                                    for (processValue === opts.radixPoint && (processValue = bufferTemplate); null === processValue.match(Inputmask.escapeRegex(bufferTemplate) + "$"); ) bufferTemplate = bufferTemplate.slice(1);
22359                                    isValid = (processValue = (processValue = processValue.replace(bufferTemplate, "")).split(""))[pos] === undefined ? {
22360                                        pos: pos,
22361                                        remove: pos
22362                                    } : {
22363                                        pos: pos
22364                                    };
22365                                }
22366                            } else strict || chrs !== opts.radixPoint || maskset.validPositions[pos - 1] !== undefined || (maskset.buffer[pos] = "0", 
22367                            isValid = {
22368                                pos: pos + 1
22369                            });
22370                            return isValid;
22371                        },
22372                        cardinality: 1
22373                    },
22374                    "+": {
22375                        validator: function(chrs, maskset, pos, strict, opts) {
22376                            return opts.allowMinus && ("-" === chrs || chrs === opts.negationSymbol.front);
22377                        },
22378                        cardinality: 1,
22379                        placeholder: ""
22380                    },
22381                    "-": {
22382                        validator: function(chrs, maskset, pos, strict, opts) {
22383                            return opts.allowMinus && chrs === opts.negationSymbol.back;
22384                        },
22385                        cardinality: 1,
22386                        placeholder: ""
22387                    },
22388                    ":": {
22389                        validator: function(chrs, maskset, pos, strict, opts) {
22390                            var radix = "[" + Inputmask.escapeRegex(opts.radixPoint) + "]", isValid = new RegExp(radix).test(chrs);
22391                            return isValid && maskset.validPositions[pos] && maskset.validPositions[pos].match.placeholder === opts.radixPoint && (isValid = {
22392                                caret: pos + 1
22393                            }), isValid;
22394                        },
22395                        cardinality: 1,
22396                        placeholder: function(opts) {
22397                            return opts.radixPoint;
22398                        }
22399                    }
22400                },
22401                onUnMask: function(maskedValue, unmaskedValue, opts) {
22402                    if ("" === unmaskedValue && !0 === opts.nullable) return unmaskedValue;
22403                    var processValue = maskedValue.replace(opts.prefix, "");
22404                    return processValue = processValue.replace(opts.suffix, ""), processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
22405                    "" !== opts.placeholder.charAt(0) && (processValue = processValue.replace(new RegExp(opts.placeholder.charAt(0), "g"), "0")), 
22406                    opts.unmaskAsNumber ? ("" !== opts.radixPoint && -1 !== processValue.indexOf(opts.radixPoint) && (processValue = processValue.replace(Inputmask.escapeRegex.call(this, opts.radixPoint), ".")), 
22407                    processValue = processValue.replace(new RegExp("^" + Inputmask.escapeRegex(opts.negationSymbol.front)), "-"), 
22408                    processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), ""), 
22409                    Number(processValue)) : processValue;
22410                },
22411                isComplete: function(buffer, opts) {
22412                    var maskedValue = buffer.join("");
22413                    if (buffer.slice().join("") !== maskedValue) return !1;
22414                    var processValue = maskedValue.replace(opts.prefix, "");
22415                    return processValue = processValue.replace(opts.suffix, ""), processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
22416                    "," === opts.radixPoint && (processValue = processValue.replace(Inputmask.escapeRegex(opts.radixPoint), ".")), 
22417                    isFinite(processValue);
22418                },
22419                onBeforeMask: function(initialValue, opts) {
22420                    if (opts.isNegative = undefined, initialValue = initialValue.toString().charAt(initialValue.length - 1) === opts.radixPoint ? initialValue.toString().substr(0, initialValue.length - 1) : initialValue.toString(), 
22421                    "" !== opts.radixPoint && isFinite(initialValue)) {
22422                        var vs = initialValue.split("."), groupSize = "" !== opts.groupSeparator ? parseInt(opts.groupSize) : 0;
22423                        2 === vs.length && (vs[0].length > groupSize || vs[1].length > groupSize || vs[0].length <= groupSize && vs[1].length < groupSize) && (initialValue = initialValue.replace(".", opts.radixPoint));
22424                    }
22425                    var kommaMatches = initialValue.match(/,/g), dotMatches = initialValue.match(/\./g);
22426                    if (initialValue = dotMatches && kommaMatches ? dotMatches.length > kommaMatches.length ? (initialValue = initialValue.replace(/\./g, "")).replace(",", opts.radixPoint) : kommaMatches.length > dotMatches.length ? (initialValue = initialValue.replace(/,/g, "")).replace(".", opts.radixPoint) : initialValue.indexOf(".") < initialValue.indexOf(",") ? initialValue.replace(/\./g, "") : initialValue.replace(/,/g, "") : initialValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
22427                    0 === opts.digits && (-1 !== initialValue.indexOf(".") ? initialValue = initialValue.substring(0, initialValue.indexOf(".")) : -1 !== initialValue.indexOf(",") && (initialValue = initialValue.substring(0, initialValue.indexOf(",")))), 
22428                    "" !== opts.radixPoint && isFinite(opts.digits) && -1 !== initialValue.indexOf(opts.radixPoint)) {
22429                        var decPart = initialValue.split(opts.radixPoint)[1].match(new RegExp("\\d*"))[0];
22430                        if (parseInt(opts.digits) < decPart.toString().length) {
22431                            var digitsFactor = Math.pow(10, parseInt(opts.digits));
22432                            initialValue = initialValue.replace(Inputmask.escapeRegex(opts.radixPoint), "."), 
22433                            initialValue = (initialValue = Math.round(parseFloat(initialValue) * digitsFactor) / digitsFactor).toString().replace(".", opts.radixPoint);
22434                        }
22435                    }
22436                    return initialValue;
22437                },
22438                canClearPosition: function(maskset, position, lvp, strict, opts) {
22439                    var vp = maskset.validPositions[position], canClear = vp.input !== opts.radixPoint || null !== maskset.validPositions[position].match.fn && !1 === opts.decimalProtect || vp.input === opts.radixPoint && maskset.validPositions[position + 1] && null === maskset.validPositions[position + 1].match.fn || isFinite(vp.input) || position === lvp || vp.input === opts.groupSeparator || vp.input === opts.negationSymbol.front || vp.input === opts.negationSymbol.back;
22440                    return !canClear || "+" !== vp.match.nativeDef && "-" !== vp.match.nativeDef || (opts.isNegative = !1), 
22441                    canClear;
22442                },
22443                onKeyDown: function(e, buffer, caretPos, opts) {
22444                    var $input = $(this);
22445                    if (e.ctrlKey) switch (e.keyCode) {
22446                      case Inputmask.keyCode.UP:
22447                        $input.val(parseFloat(this.inputmask.unmaskedvalue()) + parseInt(opts.step)), $input.trigger("setvalue");
22448                        break;
22449
22450                      case Inputmask.keyCode.DOWN:
22451                        $input.val(parseFloat(this.inputmask.unmaskedvalue()) - parseInt(opts.step)), $input.trigger("setvalue");
22452                    }
22453                }
22454            },
22455            currency: {
22456                prefix: "$ ",
22457                groupSeparator: ",",
22458                alias: "numeric",
22459                placeholder: "0",
22460                autoGroup: !0,
22461                digits: 2,
22462                digitsOptional: !1,
22463                clearMaskOnLostFocus: !1
22464            },
22465            decimal: {
22466                alias: "numeric"
22467            },
22468            integer: {
22469                alias: "numeric",
22470                digits: 0,
22471                radixPoint: ""
22472            },
22473            percentage: {
22474                alias: "numeric",
22475                digits: 2,
22476                digitsOptional: !0,
22477                radixPoint: ".",
22478                placeholder: "0",
22479                autoGroup: !1,
22480                min: 0,
22481                max: 100,
22482                suffix: " %",
22483                allowMinus: !1
22484            }
22485        }), Inputmask;
22486    });
22487}, function(module, exports, __webpack_require__) {
22488    "use strict";
22489    var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
22490    "function" == typeof Symbol && Symbol.iterator;
22491    !function(factory) {
22492        __WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(0), __webpack_require__(1) ], 
22493        void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = "function" == typeof (__WEBPACK_AMD_DEFINE_FACTORY__ = factory) ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
22494    }(function($, Inputmask) {
22495        function maskSort(a, b) {
22496            var maska = (a.mask || a).replace(/#/g, "9").replace(/\)/, "9").replace(/[+()#-]/g, ""), maskb = (b.mask || b).replace(/#/g, "9").replace(/\)/, "9").replace(/[+()#-]/g, ""), maskas = (a.mask || a).split("#")[0], maskbs = (b.mask || b).split("#")[0];
22497            return 0 === maskbs.indexOf(maskas) ? -1 : 0 === maskas.indexOf(maskbs) ? 1 : maska.localeCompare(maskb);
22498        }
22499        var analyseMaskBase = Inputmask.prototype.analyseMask;
22500        return Inputmask.prototype.analyseMask = function(mask, regexMask, opts) {
22501            function reduceVariations(masks, previousVariation, previousmaskGroup) {
22502                previousVariation = previousVariation || "", previousmaskGroup = previousmaskGroup || maskGroups, 
22503                "" !== previousVariation && (previousmaskGroup[previousVariation] = {});
22504                for (var variation = "", maskGroup = previousmaskGroup[previousVariation] || previousmaskGroup, i = masks.length - 1; i >= 0; i--) maskGroup[variation = (mask = masks[i].mask || masks[i]).substr(0, 1)] = maskGroup[variation] || [], 
22505                maskGroup[variation].unshift(mask.substr(1)), masks.splice(i, 1);
22506                for (var ndx in maskGroup) maskGroup[ndx].length > 500 && reduceVariations(maskGroup[ndx].slice(), ndx, maskGroup);
22507            }
22508            function rebuild(maskGroup) {
22509                var mask = "", submasks = [];
22510                for (var ndx in maskGroup) $.isArray(maskGroup[ndx]) ? 1 === maskGroup[ndx].length ? submasks.push(ndx + maskGroup[ndx]) : submasks.push(ndx + opts.groupmarker.start + maskGroup[ndx].join(opts.groupmarker.end + opts.alternatormarker + opts.groupmarker.start) + opts.groupmarker.end) : submasks.push(ndx + rebuild(maskGroup[ndx]));
22511                return 1 === submasks.length ? mask += submasks[0] : mask += opts.groupmarker.start + submasks.join(opts.groupmarker.end + opts.alternatormarker + opts.groupmarker.start) + opts.groupmarker.end, 
22512                mask;
22513            }
22514            var maskGroups = {};
22515            return opts.phoneCodes && (opts.phoneCodes && opts.phoneCodes.length > 1e3 && (reduceVariations((mask = mask.substr(1, mask.length - 2)).split(opts.groupmarker.end + opts.alternatormarker + opts.groupmarker.start)), 
22516            mask = rebuild(maskGroups)), mask = mask.replace(/9/g, "\\9")), analyseMaskBase.call(this, mask, regexMask, opts);
22517        }, Inputmask.extendAliases({
22518            abstractphone: {
22519                groupmarker: {
22520                    start: "<",
22521                    end: ">"
22522                },
22523                countrycode: "",
22524                phoneCodes: [],
22525                mask: function(opts) {
22526                    return opts.definitions = {
22527                        "#": Inputmask.prototype.definitions[9]
22528                    }, opts.phoneCodes.sort(maskSort);
22529                },
22530                keepStatic: !0,
22531                onBeforeMask: function(value, opts) {
22532                    var processedValue = value.replace(/^0{1,2}/, "").replace(/[\s]/g, "");
22533                    return (processedValue.indexOf(opts.countrycode) > 1 || -1 === processedValue.indexOf(opts.countrycode)) && (processedValue = "+" + opts.c
22533ountrycode + processedValue), 
22534                    processedValue;
22535                },
22536                onUnMask: function(maskedValue, unmaskedValue, opts) {
22537                    return maskedValue.replace(/[()#-]/g, "");
22538                },
22539                inputmode: "tel"
22540            }
22541        }), Inputmask;
22542    });
22543}, function(module, exports, __webpack_require__) {
22544    "use strict";
22545    var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
22546    "function" == typeof Symbol && Symbol.iterator;
22547    !function(factory) {
22548        __WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(0), __webpack_require__(1) ], 
22549        void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = "function" == typeof (__WEBPACK_AMD_DEFINE_FACTORY__ = factory) ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
22550    }(function($, Inputmask) {
22551        return Inputmask.extendAliases({
22552            Regex: {
22553                mask: "r",
22554                greedy: !1,
22555                repeat: "*",
22556                regex: null,
22557                regexTokens: null,
22558                tokenizer: /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g,
22559                quantifierFilter: /[0-9]+[^,]/,
22560                isComplete: function(buffer, opts) {
22561                    return new RegExp(opts.regex, opts.casing ? "i" : "").test(buffer.join(""));
22562                },
22563                definitions: {
22564                    r: {
22565                        validator: function(chrs, maskset, pos, strict, opts) {
22566                            function RegexToken(isGroup, isQuantifier) {
22567                                this.matches = [], this.isGroup = isGroup || !1, this.isQuantifier = isQuantifier || !1, 
22568                                this.quantifier = {
22569                                    min: 1,
22570                                    max: 1
22571                                }, this.repeaterPart = void 0;
22572                            }
22573                            function validateRegexToken(token, fromGroup) {
22574                                var isvalid = !1;
22575                                fromGroup && (regexPart += "(", openGroupCount++);
22576                                for (var mndx = 0; mndx < token.matches.length; mndx++) {
22577                                    var matchToken = token.matches[mndx];
22578                                    if (!0 === matchToken.isGroup) isvalid = validateRegexToken(matchToken, !0); else if (!0 === matchToken.isQuantifier) {
22579                                        var crrntndx = $.inArray(matchToken, token.matches), matchGroup = token.matches[crrntndx - 1], regexPartBak = regexPart;
22580                                        if (isNaN(matchToken.quantifier.max)) {
22581                                            for (;matchToken.repeaterPart && matchToken.repeaterPart !== regexPart && matchToken.repeaterPart.length > regexPart.length && !(isvalid = validateRegexToken(matchGroup, !0)); ) ;
22582                                            (isvalid = isvalid || validateRegexToken(matchGroup, !0)) && (matchToken.repeaterPart = regexPart), 
22583                                            regexPart = regexPartBak + matchToken.quantifier.max;
22584                                        } else {
22585                                            for (var i = 0, qm = matchToken.quantifier.max - 1; i < qm && !(isvalid = validateRegexToken(matchGroup, !0)); i++) ;
22586                                            regexPart = regexPartBak + "{" + matchToken.quantifier.min + "," + matchToken.quantifier.max + "}";
22587                                        }
22588                                    } else if (void 0 !== matchToken.matches) for (var k = 0; k < matchToken.length && !(isvalid = validateRegexToken(matchToken[k], fromGroup)); k++) ; else {
22589                                        var testExp;
22590                                        if ("[" == matchToken.charAt(0)) {
22591                                            testExp = regexPart, testExp += matchToken;
22592                                            for (j = 0; j < openGroupCount; j++) testExp += ")";
22593                                            isvalid = (exp = new RegExp("^(" + testExp + ")$", opts.casing ? "i" : "")).test(bufferStr);
22594                                        } else for (var l = 0, tl = matchToken.length; l < tl; l++) if ("\\" !== matchToken.charAt(l)) {
22595                                            testExp = regexPart, testExp = (testExp += matchToken.substr(0, l + 1)).replace(/\|$/, "");
22596                                            for (var j = 0; j < openGroupCount; j++) testExp += ")";
22597                                            var exp = new RegExp("^(" + testExp + ")$", opts.casing ? "i" : "");
22598                                            if (isvalid = exp.test(bufferStr)) break;
22599                                        }
22600                                        regexPart += matchToken;
22601                                    }
22602                                    if (isvalid) break;
22603                                }
22604                                return fromGroup && (regexPart += ")", openGroupCount--), isvalid;
22605                            }
22606                            var bufferStr, groupToken, cbuffer = maskset.buffer.slice(), regexPart = "", isValid = !1, openGroupCount = 0;
22607                            null === opts.regexTokens && function() {
22608                                var match, m, currentToken = new RegexToken(), opengroups = [];
22609                                for (opts.regexTokens = []; match = opts.tokenizer.exec(opts.regex); ) switch ((m = match[0]).charAt(0)) {
22610                                  case "(":
22611                                    opengroups.push(new RegexToken(!0));
22612                                    break;
22613
22614                                  case ")":
22615                                    groupToken = opengroups.pop(), opengroups.length > 0 ? opengroups[opengroups.length - 1].matches.push(groupToken) : currentToken.matches.push(groupToken);
22616                                    break;
22617
22618                                  case "{":
22619                                  case "+":
22620                                  case "*":
22621                                    var quantifierToken = new RegexToken(!1, !0), mq = (m = m.replace(/[{}]/g, "")).split(","), mq0 = isNaN(mq[0]) ? mq[0] : parseInt(mq[0]), mq1 = 1 === mq.length ? mq0 : isNaN(mq[1]) ? mq[1] : parseInt(mq[1]);
22622                                    if (quantifierToken.quantifier = {
22623                                        min: mq0,
22624                                        max: mq1
22625                                    }, opengroups.length > 0) {
22626                                        var matches = opengroups[opengroups.length - 1].matches;
22627                                        (match = matches.pop()).isGroup || ((groupToken = new RegexToken(!0)).matches.push(match), 
22628                                        match = groupToken), matches.push(match), matches.push(quantifierToken);
22629                                    } else (match = currentToken.matches.pop()).isGroup || ((groupToken = new RegexToken(!0)).matches.push(match), 
22630                                    match = groupToken), currentToken.matches.push(match), currentToken.matches.push(quantifierToken);
22631                                    break;
22632
22633                                  default:
22634                                    opengroups.length > 0 ? opengroups[opengroups.length - 1].matches.push(m) : currentToken.matches.push(m);
22635                                }
22636                                currentToken.matches.length > 0 && opts.regexTokens.push(currentToken);
22637                            }(), cbuffer.splice(pos, 0, chrs), bufferStr = cbuffer.join("");
22638                            for (var i = 0; i < opts.regexTokens.length; i++) {
22639                                var regexToken = opts.regexTokens[i];
22640                                if (isValid = validateRegexToken(regexToken, regexToken.isGroup)) break;
22641                            }
22642                            return isValid;
22643                        },
22644                        cardinality: 1
22645                    }
22646                }
22647            }
22648        }), Inputmask;
22649    });
22650}, function(module, exports, __webpack_require__) {
22651    "use strict";
22652    var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__, _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(obj) {
22653        return typeof obj;
22654    } : function(obj) {
22655        return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
22656    };
22657    !function(factory) {
22658        __WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(1) ], 
22659        void 0 !== (__WEBPACK_AMD_DEFINE_RESULT__ = "function" == typeof (__WEBPACK_AMD_DEFINE_FACTORY__ = factory) ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__) && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
22660    }(function($, Inputmask) {
22661        return void 0 === $.fn.inputmask && ($.fn.inputmask = function(fn, options) {
22662            var nptmask, input = this[0];
22663            if (void 0 === options && (options = {}), "string" == typeof fn) switch (fn) {
22664              case "unmaskedvalue":
22665                return input && input.inputmask ? input.inputmask.unmaskedvalue() : $(input).val();
22666
22667              case "remove":
22668                return this.each(function() {
22669                    this.inputmask && this.inputmask.remove();
22670                });
22671
22672              case "getemptymask":
22673                return input && input.inputmask ? input.inputmask.getemptymask() : "";
22674
22675              case "hasMaskedValue":
22676                return !(!input || !input.inputmask) && input.inputmask.hasMaskedValue();
22677
22678              case "isComplete":
22679                return !input || !input.inputmask || input.inputmask.isComplete();
22680
22681              case "getmetadata":
22682                return input && input.inputmask ? input.inputmask.getmetadata() : void 0;
22683
22684              case "setvalue":
22685                $(input).val(options), input && void 0 === input.inputmask && $(input).triggerHandler("setvalue");
22686                break;
22687
22688              case "option":
22689                if ("string" != typeof options) return this.each(function() {
22690                    if (void 0 !== this.inputmask) return this.inputmask.option(options);
22691                });
22692                if (input && void 0 !== input.inputmask) return input.inputmask.option(options);
22693                break;
22694
22695              default:
22696                return options.alias = fn, nptmask = new Inputmask(options), this.each(function() {
22697                    nptmask.mask(this);
22698                });
22699            } else {
22700                if ("object" == (void 0 === fn ? "undefined" : _typeof(fn))) return nptmask = new Inputmask(fn), 
22701                void 0 === fn.mask && void 0 === fn.alias ? this.each(function() {
22702                    if (void 0 !== this.inputmask) return this.inputmask.option(fn);
22703                    nptmask.mask(this);
22704                }) : this.each(function() {
22705                    nptmask.mask(this);
22706                });
22707                if (void 0 === fn) return this.each(function() {
22708                    (nptmask = new Inputmask(options)).mask(this);
22709                });
22710            }
22711        }), $.fn.inputmask;
22712    });
22713} ]);
22714/*!
22715* inputmask.date.extensions.js
22716* https://github.com/RobinHerbots/Inputmask
22717* Copyright (c) 2010 - 2017 Robin Herbots
22718* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
22719* Version: 3.3.11
22720*/
22721
22722!function(factory) {
22723    "function" == typeof define && define.amd ? define([ "./dependencyLibs/inputmask.dependencyLib", "./inputmask" ], factory) : "object" == typeof exports ? module.exports = factory(require("./dependencyLibs/inputmask.dependencyLib"), require("./inputmask")) : factory(window.dependencyLib || jQuery, window.Inputmask);
22724}(function($, Inputmask) {
22725    function isLeapYear(year) {
22726        return isNaN(year) || 29 === new Date(year, 2, 0).getDate();
22727    }
22728    return Inputmask.extendAliases({
22729        "dd/mm/yyyy": {
22730            mask: "1/2/y",
22731            placeholder: "dd/mm/yyyy",
22732            regex: {
22733                val1pre: new RegExp("[0-3]"),
22734                val1: new RegExp("0[1-9]|[12][0-9]|3[01]"),
22735                val2pre: function(separator) {
22736                    var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
22737                    return new RegExp("((0[1-9]|[12][0-9]|3[01])" + escapedSeparator + "[01])");
22738                },
22739                val2: function(separator) {
22740                    var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
22741                    return new RegExp("((0[1-9]|[12][0-9])" + escapedSeparator + "(0[1-9]|1[012]))|(30" + escapedSeparator + "(0[13-9]|1[012]))|(31" + escapedSeparator + "(0[13578]|1[02]))");
22742                }
22743            },
22744            leapday: "29/02/",
22745            separator: "/",
22746            yearrange: {
22747                minyear: 1900,
22748                maxyear: 2099
22749            },
22750            isInYearRange: function(chrs, minyear, maxyear) {
22751                if (isNaN(chrs)) return !1;
22752                var enteredyear = parseInt(chrs.concat(minyear.toString().slice(chrs.length))), enteredyear2 = parseInt(chrs.concat(maxyear.toString().slice(chrs.length)));
22753                return !isNaN(enteredyear) && (minyear <= enteredyear && enteredyear <= maxyear) || !isNaN(enteredyear2) && (minyear <= enteredyear2 && enteredyear2 <= maxyear);
22754            },
22755            determinebaseyear: function(minyear, maxyear, hint) {
22756                var currentyear = new Date().getFullYear();
22757                if (minyear > currentyear) return minyear;
22758                if (maxyear < currentyear) {
22759                    for (var maxYearPrefix = maxyear.toString().slice(0, 2), maxYearPostfix = maxyear.toString().slice(2, 4); maxyear < maxYearPrefix + hint; ) maxYearPrefix--;
22760                    var maxxYear = maxYearPrefix + maxYearPostfix;
22761                    return minyear > maxxYear ? minyear : maxxYear;
22762                }
22763                if (minyear <= currentyear && currentyear <= maxyear) {
22764                    for (var currentYearPrefix = currentyear.toString().slice(0, 2); maxyear < currentYearPrefix + hint; ) currentYearPrefix--;
22765                    var currentYearAndHint = currentYearPrefix + hint;
22766                    return currentYearAndHint < minyear ? minyear : currentYearAndHint;
22767                }
22768                return currentyear;
22769            },
22770            onKeyDown: function(e, buffer, caretPos, opts) {
22771                var $input = $(this);
22772                if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) {
22773                    var today = new Date();
22774                    $input.val(today.getDate().toString() + (today.getMonth() + 1).toString() + today.getFullYear().toString()), 
22775                    $input.trigger("setvalue");
22776                }
22777            },
22778            getFrontValue: function(mask, buffer, opts) {
22779                for (var start = 0, length = 0, i = 0; i < mask.length && "2" !== mask.charAt(i); i++) {
22780                    var definition = opts.definitions[mask.charAt(i)];
22781                    definition ? (start += length, length = definition.cardinality) : length++;
22782                }
22783                return buffer.join("").substr(start, length);
22784            },
22785            postValidation: function(buffer, currentResult, opts) {
22786                var dayMonthValue, year, bufferStr = buffer.join("");
22787                return 0 === opts.mask.indexOf("y") ? (year = bufferStr.substr(0, 4), dayMonthValue = bufferStr.substring(4, 10)) : (year = bufferStr.substring(6, 10), 
22788                dayMonthValue = bufferStr.substr(0, 6)), currentResult && (dayMonthValue !== opts.leapday || isLeapYear(year));
22789            },
22790            definitions: {
22791                "1": {
22792                    validator: function(chrs, maskset, pos, strict, opts) {
22793                        var isValid = opts.regex.val1.test(chrs);
22794                        return strict || isValid || chrs.charAt(1) !== opts.separator && -1 === "-./".indexOf(chrs.charAt(1)) || !(isValid = opts.regex.val1.test("0" + chrs.charAt(0))) ? isValid : (maskset.buffer[pos - 1] = "0", 
22795                        {
22796                            refreshFromBuffer: {
22797                                start: pos - 1,
22798                                end: pos
22799                            },
22800                            pos: pos,
22801                            c: chrs.charAt(0)
22802                        });
22803                    },
22804                    cardinality: 2,
22805                    prevalidator: [ {
22806                        validator: function(chrs, maskset, pos, strict, opts) {
22807                            var pchrs = chrs;
22808                            isNaN(maskset.buffer[pos + 1]) || (pchrs += maskset.buffer[pos + 1]);
22809                            var isValid = 1 === pchrs.length ? opts.regex.val1pre.test(pchrs) : opts.regex.val1.test(pchrs);
22810                            if (isValid && maskset.validPositions[pos] && (opts.regex.val2(opts.separator).test(chrs + maskset.validPositions[pos].input) || (maskset.validPositions[pos].input = "0" === chrs ? "1" : "0")), 
22811                            !strict && !isValid) {
22812                                if (isValid = opts.regex.val1.test(chrs + "0")) return maskset.buffer[pos] = chrs, 
22813                                maskset.buffer[++pos] = "0", {
22814                                    pos: pos,
22815                                    c: "0"
22816                                };
22817                                if (isValid = opts.regex.val1.test("0" + chrs)) return maskset.buffer[pos] = "0", 
22818                                pos++, {
22819                                    pos: pos
22820                                };
22821                            }
22822                            return isValid;
22823                        },
22824                        cardinality: 1
22825                    } ]
22826                },
22827                "2": {
22828                    validator: function(chrs, maskset, pos, strict, opts) {
22829                        var frontValue = opts.getFrontValue(maskset.mask, maskset.buffer, opts);
22830                        -1 !== frontValue.indexOf(opts.placeholder[0]) && (frontValue = "01" + opts.separator);
22831                        var isValid = opts.regex.val2(opts.separator).test(frontValue + chrs);
22832                        return strict || isValid || chrs.charAt(1) !== opts.separator && -1 === "-./".indexOf(chrs.charAt(1)) || !(isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs.charAt(0))) ? isValid : (maskset.buffer[pos - 1] = "0", 
22833                        {
22834                            refreshFromBuffer: {
22835                                start: pos - 1,
22836                                end: pos
22837                            },
22838                            pos: pos,
22839                            c: chrs.charAt(0)
22840                        });
22841                    },
22842                    cardinality: 2,
22843                    prevalidator: [ {
22844                        validator: function(chrs, maskset, pos, strict, opts) {
22845                            isNaN(maskset.buffer[pos + 1]) || (chrs += maskset.buffer[pos + 1]);
22846                            var frontValue = opts.getFrontValue(maskset.mask, maskset.buffer, opts);
22847                            -1 !== frontValue.indexOf(opts.placeholder[0]) && (frontValue = "01" + opts.separator);
22848                            var isValid = 1 === chrs.length ? opts.regex.val2pre(opts.separator).test(frontValue + chrs) : opts.regex.val2(opts.separator).test(frontValue + chrs);
22849                            return isValid && maskset.validPositions[pos] && (opts.regex.val2(opts.separator).test(chrs + maskset.validPositions[pos].input) || (maskset.validPositions[pos].input = "0" === chrs ? "1" : "0")), 
22850                            strict || isValid || !(isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs)) ? isValid : (maskset.buffer[pos] = "0", 
22851                            pos++, {
22852                                pos: pos
22853                            });
22854                        },
22855                        cardinality: 1
22856                    } ]
22857                },
22858                y: {
22859                    validator: function(chrs, maskset, pos, strict, opts) {
22860                        return opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
22861                    },
22862                    cardinality: 4,
22863                    prevalidator: [ {
22864                        validator: function(chrs, maskset, pos, strict, opts) {
22865                            var isValid = opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
22866                            if (!strict && !isValid) {
22867                                var yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs + "0").toString().slice(0, 1);
22868                                if (isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos++] = yearPrefix.charAt(0), 
22869                                {
22870                                    pos: pos
22871                                };
22872                                if (yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs + "0").toString().slice(0, 2), 
22873                                isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos++] = yearPrefix.charAt(0), 
22874                                maskset.buffer[pos++] = yearPrefix.charAt(1), {
22875                                    pos: pos
22876                                };
22877                            }
22878                            return isValid;
22879                        },
22880                        cardinality: 1
22881                    }, {
22882                        validator: function(chrs, maskset, pos, strict, opts) {
22883                            var isValid = opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
22884                            if (!strict && !isValid) {
22885                                var yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs).toString().slice(0, 2);
22886                                if (isValid = opts.isInYearRange(chrs[0] + yearPrefix[1] + chrs[1], opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos++] = yearPrefix.charAt(1), 
22887                                {
22888                                    pos: pos
22889                                };
22890                                if (yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs).toString().slice(0, 2), 
22891                                isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos - 1] = yearPrefix.charAt(0), 
22892                                maskset.buffer[pos++] = yearPrefix.charAt(1), maskset.buffer[pos++] = chrs.charAt(0), 
22893                                {
22894                                    refreshFromBuffer: {
22895                                        start: pos - 3,
22896                                        end: pos
22897                                    },
22898                                    pos: pos
22899                                };
22900                            }
22901                            return isValid;
22902                        },
22903                        cardinality: 2
22904                    }, {
22905                        validator: function(chrs, maskset, pos, strict, opts) {
22906                            return opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
22907                        },
22908                        cardinality: 3
22909                    } ]
22910                }
22911            },
22912            insertMode: !1,
22913            autoUnmask: !1
22914        },
22915        "mm/dd/yyyy": {
22916            placeholder: "mm/dd/yyyy",
22917            alias: "dd/mm/yyyy",
22918            regex: {
22919                val2pre: function(separator) {
22920                    var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
22921                    return new RegExp("((0[13-9]|1[012])" + escapedSeparator + "[0-3])|(02" + escapedSeparator + "[0-2])");
22922                },
22923                val2: function(separator) {
22924                    var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
22925                    return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[13-9]|1[012])" + escapedSeparator + "30)|((0[13578]|1[02])" + escapedSeparator + "31)");
22926                },
22927                val1pre: new RegExp("[01]"),
22928                val1: new RegExp("0[1-9]|1[012]")
22929            },
22930            leapday: "02/29/",
22931            onKeyDown: function(e, buffer, caretPos, opts) {
22932                var $input = $(this);
22933                if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) {
22934                    var today = new Date();
22935                    $input.val((today.getMonth() + 1).toString() + today.getDate().toString() + today.getFullYear().toString()), 
22936                    $input.trigger("setvalue");
22937                }
22938            }
22939        },
22940        "yyyy/mm/dd": {
22941            mask: "y/1/2",
22942            placeholder: "yyyy/mm/dd",
22943            alias: "mm/dd/yyyy",
22944            leapday: "/02/29",
22945            onKeyDown: function(e, buffer, caretPos, opts) {
22946                var $input = $(this);
22947                if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) {
22948                    var today = new Date();
22949                    $input.val(today.getFullYear().toString() + (today.getMonth() + 1).toString() + today.getDate().toString()), 
22950                    $input.trigger("setvalue");
22951                }
22952            }
22953        },
22954        "dd.mm.yyyy": {
22955            mask: "1.2.y",
22956            placeholder: "dd.mm.yyyy",
22957            leapday: "29.02.",
22958            separator: ".",
22959            alias: "dd/mm/yyyy"
22960        },
22961        "dd-mm-yyyy": {
22962            mask: "1-2-y",
22963            placeholder: "dd-mm-yyyy",
22964            leapday: "29-02-",
22965            separator: "-",
22966            alias: "dd/mm/yyyy"
22967        },
22968        "mm.dd.yyyy": {
22969            mask: "1.2.y",
22970            placeholder: "mm.dd.yyyy",
22971            leapday: "02.29.",
22972            separator: ".",
22973            alias: "mm/dd/yyyy"
22974        },
22975        "mm-dd-yyyy": {
22976            mask: "1-2-y",
22977            placeholder: "mm-dd-yyyy",
22978            leapday: "02-29-",
22979            separator: "-",
22980            alias: "mm/dd/yyyy"
22981        },
22982        "yyyy.mm.dd": {
22983            mask: "y.1.2",
22984            placeholder: "yyyy.mm.dd",
22985            leapday: ".02.29",
22986            separator: ".",
22987            alias: "yyyy/mm/dd"
22988        },
22989        "yyyy-mm-dd": {
22990            mask: "y-1-2",
22991            placeholder: "yyyy-mm-dd",
22992            leapday: "-02-29",
22993            separator: "-",
22994            alias: "yyyy/mm/dd"
22995        },
22996        datetime: {
22997            mask: "1/2/y h:s",
22998            placeholder: "dd/mm/yyyy hh:mm",
22999            alias: "dd/mm/yyyy",
23000            regex: {
23001                hrspre: new RegExp("[012]"),
23002                hrs24: new RegExp("2[0-4]|1[3-9]"),
23003                hrs: new RegExp("[01][0-9]|2[0-4]"),
23004                ampm: new RegExp("^[a|p|A|P][m|M]"),
23005                mspre: new RegExp("[0-5]"),
23006                ms: new RegExp("[0-5][0-9]")
23007            },
23008            timeseparator: ":",
23009            hourFormat: "24",
23010            definitions: {
23011                h: {
23012                    validator: function(chrs, maskset, pos, strict, opts) {
23013                        if ("24" === opts.hourFormat && 24 === parseInt(chrs, 10)) return maskset.buffer[pos - 1] = "0", 
23014                        maskset.buffer[pos] = "0", {
23015                            refreshFromBuffer: {
23016                                start: pos - 1,
23017                                end: pos
23018                            },
23019                            c: "0"
23020                        };
23021                        var isValid = opts.regex.hrs.test(chrs);
23022                        if (!strict && !isValid && (chrs.charAt(1) === opts.timeseparator || -1 !== "-.:".indexOf(chrs.charAt(1))) && (isValid = opts.regex.hrs.test("0" + chrs.charAt(0)))) return maskset.buffer[pos - 1] = "0", 
23023                        maskset.buffer[pos] = chrs.charAt(0), pos++, {
23024                            refreshFromBuffer: {
23025                                start: pos - 2,
23026                                end: pos
23027                            },
23028                            pos: pos,
23029                            c: opts.timeseparator
23030                        };
23031                        if (isValid && "24" !== opts.hourFormat && opts.regex.hrs24.test(chrs)) {
23032                            var tmp = parseInt(chrs, 10);
23033                            return 24 === tmp ? (maskset.buffer[pos + 5] = "a", maskset.buffer[pos + 6] = "m") : (maskset.buffer[pos + 5] = "p", 
23034                            maskset.buffer[pos + 6] = "m"), (tmp -= 12) < 10 ? (maskset.buffer[pos] = tmp.toString(), 
23035                            maskset.buffer[pos - 1] = "0") : (maskset.buffer[pos] = tmp.toString().charAt(1), 
23036                            maskset.buffer[pos - 1] = tmp.toString().charAt(0)), {
23037                                refreshFromBuffer: {
23038                                    start: pos - 1,
23039                                    end: pos + 6
23040                                },
23041                                c: maskset.buffer[pos]
23042                            };
23043                        }
23044                        return isValid;
23045                    },
23046                    cardinality: 2,
23047                    prevalidator: [ {
23048                        validator: function(chrs, maskset, pos, strict, opts) {
23049                            var isValid = opts.regex.hrspre.test(chrs);
23050                            return strict || isValid || !(isValid = opts.regex.hrs.test("0" + chrs)) ? isValid : (maskset.buffer[pos] = "0", 
23051                            pos++, {
23052                                pos: pos
23053                            });
23054                        },
23055                        cardinality: 1
23056                    } ]
23057                },
23058                s: {
23059                    validator: "[0-5][0-9]",
23060                    cardinality: 2,
23061                    prevalidator: [ {
23062                        validator: function(chrs, maskset, pos, strict, opts) {
23063                            var isValid = opts.regex.mspre.test(chrs);
23064                            return strict || isValid || !(isValid = opts.regex.ms.test("0" + chrs)) ? isValid : (maskset.buffer[pos] = "0", 
23065                            pos++, {
23066                                pos: pos
23067                            });
23068                        },
23069                        cardinality: 1
23070                    } ]
23071                },
23072                t: {
23073                    validator: function(chrs, maskset, pos, strict, opts) {
23074                        return opts.regex.ampm.test(chrs + "m");
23075                    },
23076                    casing: "lower",
23077                    cardinality: 1
23078                }
23079            },
23080            insertMode: !1,
23081            autoUnmask: !1
23082        },
23083        datetime12: {
23084            mask: "1/2/y h:s t\\m",
23085            placeholder: "dd/mm/yyyy hh:mm xm",
23086            alias: "datetime",
23087            hourFormat: "12"
23088        },
23089        "mm/dd/yyyy hh:mm xm": {
23090            mask: "1/2/y h:s t\\m",
23091            placeholder: "mm/dd/yyyy hh:mm xm",
23092            alias: "datetime12",
23093            regex: {
23094                val2pre: function(separator) {
23095                    var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
23096                    return new RegExp("((0[13-9]|1[012])" + escapedSeparator + "[0-3])|(02" + escapedSeparator + "[0-2])");
23097                },
23098                val2: function(separator) {
23099                    var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
23100                    return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[13-9]|1[012])" + escapedSeparator + "30)|((0[13578]|1[02])" + escapedSeparator + "31)");
23101                },
23102                val1pre: new RegExp("[01]"),
23103                val1: new RegExp("0[1-9]|1[012]")
23104            },
23105            leapday: "02/29/",
23106            onKeyDown: function(e, buffer, caretPos, opts) {
23107                var $input = $(this);
23108                if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) {
23109                    var today = new Date();
23110                    $input.val((today.getMonth() + 1).toString() + today.getDate().toString() + today.getFullYear().toString()), 
23111                    $input.trigger("setvalue");
23112                }
23113            }
23114        },
23115        "hh:mm t": {
23116            mask: "h:s t\\m",
23117            placeholder: "hh:mm xm",
23118            alias: "datetime",
23119            hourFormat: "12"
23120        },
23121        "h:s t": {
23122            mask: "h:s t\\m",
23123            placeholder: "hh:mm xm",
23124            alias: "datetime",
23125            hourFormat: "12"
23126        },
23127        "hh:mm:ss": {
23128            mask: "h:s:s",
23129            placeholder: "hh:mm:ss",
23130            alias: "datetime",
23131            autoUnmask: !1
23132        },
23133        "hh:mm": {
23134            mask: "h:s",
23135            placeholder: "hh:mm",
23136            alias: "datetime",
23137            autoUnmask: !1
23138        },
23139        date: {
23140            alias: "dd/mm/yyyy"
23141        },
23142        "mm/yyyy": {
23143            mask: "1/y",
23144            placeholder: "mm/yyyy",
23145            leapday: "donotuse",
23146            separator: "/",
23147            alias: "mm/dd/yyyy"
23148        },
23149        shamsi: {
23150            regex: {
23151                val2pre: function(separator) {
23152                    var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
23153                    return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "[0-3])");
23154                },
23155                val2: function(separator) {
23156                    var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
23157                    return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[1-9]|1[012])" + escapedSeparator + "30)|((0[1-6])" + escapedSeparator + "31)");
23158                },
23159                val1pre: new RegExp("[01]"),
23160                val1: new RegExp("0[1-9]|1[012]")
23161            },
23162            yearrange: {
23163                minyear: 1300,
23164                maxyear: 1499
23165            },
23166            mask: "y/1/2",
23167            leapday: "/12/30",
23168            placeholder: "yyyy/mm/dd",
23169            alias: "mm/dd/yyyy",
23170            clearIncomplete: !0
23171        },
23172        "yyyy-mm-dd hh:mm:ss": {
23173            mask: "y-1-2 h:s:s",
23174            placeholder: "yyyy-mm-dd hh:mm:ss",
23175            alias: "datetime",
23176            separator: "-",
23177            leapday: "-02-29",
23178            regex: {
23179                val2pre: function(separator) {
23180                    var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
23181                    return new RegExp("((0[13-9]|1[012])" + escapedSeparator + "[0-3])|(02" + escapedSeparator + "[0-2])");
23182                },
23183                val2: function(separator) {
23184                    var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
23185                    return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[13-9]|1[012])" + escapedSeparator + "30)|((0[13578]|1[02])" + escapedSeparator + "31)");
23186                },
23187                val1pre: new RegExp("[01]"),
23188                val1: new RegExp("0[1-9]|1[012]")
23189            },
23190            onKeyDown: function(e, buffer, caretPos, opts) {}
23191        }
23192    }), Inputmask;
23193});
23194/*!
23195* inputmask.numeric.extensions.js
23196* https://github.com/RobinHerbots/Inputmask
23197* Copyright (c) 2010 - 2017 Robin Herbots
23198* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
23199* Version: 3.3.11
23200*/
23201
23202!function(factory) {
23203    "function" == typeof define && define.amd ? define([ "./dependencyLibs/inputmask.dependencyLib", "./inputmask" ], factory) : "object" == typeof exports ? module.exports = factory(require("./dependencyLibs/inputmask.dependencyLib"), require("./inputmask")) : factory(window.dependencyLib || jQuery, window.Inputmask);
23204}(function($, Inputmask, undefined) {
23205    function autoEscape(txt, opts) {
23206        for (var escapedTxt = "", i = 0; i < txt.length;
23206 i++) Inputmask.prototype.definitions[txt.charAt(i)] || opts.definitions[txt.charAt(i)] || opts.optionalmarker.start === txt.charAt(i) || opts.optionalmarker.end === txt.charAt(i) || opts.quantifiermarker.start === txt.charAt(i) || opts.quantifiermarker.end === txt.charAt(i) || opts.groupmarker.start === txt.charAt(i) || opts.groupmarker.end === txt.charAt(i) || opts.alternatormarker === txt.charAt(i) ? escapedTxt += "\\" + txt.charAt(i) : escapedTxt += txt.charAt(i);
23207        return escapedTxt;
23208    }
23209    return Inputmask.extendAliases({
23210        numeric: {
23211            mask: function(opts) {
23212                if (0 !== opts.repeat && isNaN(opts.integerDigits) && (opts.integerDigits = opts.repeat), 
23213                opts.repeat = 0, opts.groupSeparator === opts.radixPoint && ("." === opts.radixPoint ? opts.groupSeparator = "," : "," === opts.radixPoint ? opts.groupSeparator = "." : opts.groupSeparator = ""), 
23214                " " === opts.groupSeparator && (opts.skipOptionalPartCharacter = undefined), opts.autoGroup = opts.autoGroup && "" !== opts.groupSeparator, 
23215                opts.autoGroup && ("string" == typeof opts.groupSize && isFinite(opts.groupSize) && (opts.groupSize = parseInt(opts.groupSize)), 
23216                isFinite(opts.integerDigits))) {
23217                    var seps = Math.floor(opts.integerDigits / opts.groupSize), mod = opts.integerDigits % opts.groupSize;
23218                    opts.integerDigits = parseInt(opts.integerDigits) + (0 === mod ? seps - 1 : seps), 
23219                    opts.integerDigits < 1 && (opts.integerDigits = "*");
23220                }
23221                opts.placeholder.length > 1 && (opts.placeholder = opts.placeholder.charAt(0)), 
23222                "radixFocus" === opts.positionCaretOnClick && "" === opts.placeholder && !1 === opts.integerOptional && (opts.positionCaretOnClick = "lvp"), 
23223                opts.definitions[";"] = opts.definitions["~"], opts.definitions[";"].definitionSymbol = "~", 
23224                !0 === opts.numericInput && (opts.positionCaretOnClick = "radixFocus" === opts.positionCaretOnClick ? "lvp" : opts.positionCaretOnClick, 
23225                opts.digitsOptional = !1, isNaN(opts.digits) && (opts.digits = 2), opts.decimalProtect = !1);
23226                var mask = "[+]";
23227                if (mask += autoEscape(opts.prefix, opts), !0 === opts.integerOptional ? mask += "~{1," + opts.integerDigits + "}" : mask += "~{" + opts.integerDigits + "}", 
23228                opts.digits !== undefined) {
23229                    opts.radixPointDefinitionSymbol = opts.decimalProtect ? ":" : opts.radixPoint;
23230                    var dq = opts.digits.toString().split(",");
23231                    isFinite(dq[0] && dq[1] && isFinite(dq[1])) ? mask += opts.radixPointDefinitionSymbol + ";{" + opts.digits + "}" : (isNaN(opts.digits) || parseInt(opts.digits) > 0) && (opts.digitsOptional ? mask += "[" + opts.radixPointDefinitionSymbol + ";{1," + opts.digits + "}]" : mask += opts.radixPointDefinitionSymbol + ";{" + opts.digits + "}");
23232                }
23233                return mask += autoEscape(opts.suffix, opts), mask += "[-]", opts.greedy = !1, mask;
23234            },
23235            placeholder: "",
23236            greedy: !1,
23237            digits: "*",
23238            digitsOptional: !0,
23239            enforceDigitsOnBlur: !1,
23240            radixPoint: ".",
23241            positionCaretOnClick: "radixFocus",
23242            groupSize: 3,
23243            groupSeparator: "",
23244            autoGroup: !1,
23245            allowMinus: !0,
23246            negationSymbol: {
23247                front: "-",
23248                back: ""
23249            },
23250            integerDigits: "+",
23251            integerOptional: !0,
23252            prefix: "",
23253            suffix: "",
23254            rightAlign: !0,
23255            decimalProtect: !0,
23256            min: null,
23257            max: null,
23258            step: 1,
23259            insertMode: !0,
23260            autoUnmask: !1,
23261            unmaskAsNumber: !1,
23262            inputmode: "numeric",
23263            preValidation: function(buffer, pos, c, isSelection, opts) {
23264                if ("-" === c || c === opts.negationSymbol.front) return !0 === opts.allowMinus && (opts.isNegative = opts.isNegative === undefined || !opts.isNegative, 
23265                "" === buffer.join("") || {
23266                    caret: pos,
23267                    dopost: !0
23268                });
23269                if (!1 === isSelection && c === opts.radixPoint && opts.digits !== undefined && (isNaN(opts.digits) || parseInt(opts.digits) > 0)) {
23270                    var radixPos = $.inArray(opts.radixPoint, buffer);
23271                    if (-1 !== radixPos) return !0 === opts.numericInput ? pos === radixPos : {
23272                        caret: radixPos + 1
23273                    };
23274                }
23275                return !0;
23276            },
23277            postValidation: function(buffer, currentResult, opts) {
23278                var suffix = opts.suffix.split(""), prefix = opts.prefix.split("");
23279                if (currentResult.pos === undefined && currentResult.caret !== undefined && !0 !== currentResult.dopost) return currentResult;
23280                var caretPos = currentResult.caret !== undefined ? currentResult.caret : currentResult.pos, maskedValue = buffer.slice();
23281                opts.numericInput && (caretPos = maskedValue.length - caretPos - 1, maskedValue = maskedValue.reverse());
23282                var charAtPos = maskedValue[caretPos];
23283                if (charAtPos === opts.groupSeparator && (charAtPos = maskedValue[caretPos += 1]), 
23284                caretPos === maskedValue.length - opts.suffix.length - 1 && charAtPos === opts.radixPoint) return currentResult;
23285                charAtPos !== undefined && charAtPos !== opts.radixPoint && charAtPos !== opts.negationSymbol.front && charAtPos !== opts.negationSymbol.back && (maskedValue[caretPos] = "?", 
23286                opts.prefix.length > 0 && caretPos >= (!1 === opts.isNegative ? 1 : 0) && caretPos < opts.prefix.length - 1 + (!1 === opts.isNegative ? 1 : 0) ? prefix[caretPos - (!1 === opts.isNegative ? 1 : 0)] = "?" : opts.suffix.length > 0 && caretPos >= maskedValue.length - opts.suffix.length - (!1 === opts.isNegative ? 1 : 0) && (suffix[caretPos - (maskedValue.length - opts.suffix.length - (!1 === opts.isNegative ? 1 : 0))] = "?")), 
23287                prefix = prefix.join(""), suffix = suffix.join("");
23288                var processValue = maskedValue.join("").replace(prefix, "");
23289                if (processValue = processValue.replace(suffix, ""), processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
23290                processValue = processValue.replace(new RegExp("[-" + Inputmask.escapeRegex(opts.negationSymbol.front) + "]", "g"), ""), 
23291                processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), ""), 
23292                isNaN(opts.placeholder) && (processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.placeholder), "g"), "")), 
23293                processValue.length > 1 && 1 !== processValue.indexOf(opts.radixPoint) && ("0" === charAtPos && (processValue = processValue.replace(/^\?/g, "")), 
23294                processValue = processValue.replace(/^0/g, "")), processValue.charAt(0) === opts.radixPoint && "" !== opts.radixPoint && !0 !== opts.numericInput && (processValue = "0" + processValue), 
23295                "" !== processValue) {
23296                    if (processValue = processValue.split(""), (!opts.digitsOptional || opts.enforceDigitsOnBlur && "blur" === currentResult.event) && isFinite(opts.digits)) {
23297                        var radixPosition = $.inArray(opts.radixPoint, processValue), rpb = $.inArray(opts.radixPoint, maskedValue);
23298                        -1 === radixPosition && (processValue.push(opts.radixPoint), radixPosition = processValue.length - 1);
23299                        for (var i = 1; i <= opts.digits; i++) opts.digitsOptional && (!opts.enforceDigitsOnBlur || "blur" !== currentResult.event) || processValue[radixPosition + i] !== undefined && processValue[radixPosition + i] !== opts.placeholder.charAt(0) ? -1 !== rpb && maskedValue[rpb + i] !== undefined && (processValue[radixPosition + i] = processValue[radixPosition + i] || maskedValue[rpb + i]) : processValue[radixPosition + i] = currentResult.placeholder || opts.placeholder.charAt(0);
23300                    }
23301                    if (!0 !== opts.autoGroup || "" === opts.groupSeparator || charAtPos === opts.radixPoint && currentResult.pos === undefined && !currentResult.dopost) processValue = processValue.join(""); else {
23302                        var addRadix = processValue[processValue.length - 1] === opts.radixPoint && currentResult.c === opts.radixPoint;
23303                        processValue = Inputmask(function(buffer, opts) {
23304                            var postMask = "";
23305                            if (postMask += "(" + opts.groupSeparator + "*{" + opts.groupSize + "}){*}", "" !== opts.radixPoint) {
23306                                var radixSplit = buffer.join("").split(opts.radixPoint);
23307                                radixSplit[1] && (postMask += opts.radixPoint + "*{" + radixSplit[1].match(/^\d*\??\d*/)[0].length + "}");
23308                            }
23309                            return postMask;
23310                        }(processValue, opts), {
23311                            numericInput: !0,
23312                            jitMasking: !0,
23313                            definitions: {
23314                                "*": {
23315                                    validator: "[0-9?]",
23316                                    cardinality: 1
23317                                }
23318                            }
23319                        }).format(processValue.join("")), addRadix && (processValue += opts.radixPoint), 
23320                        processValue.charAt(0) === opts.groupSeparator && processValue.substr(1);
23321                    }
23322                }
23323                if (opts.isNegative && "blur" === currentResult.event && (opts.isNegative = "0" !== processValue), 
23324                processValue = prefix + processValue, processValue += suffix, opts.isNegative && (processValue = opts.negationSymbol.front + processValue, 
23325                processValue += opts.negationSymbol.back), processValue = processValue.split(""), 
23326                charAtPos !== undefined) if (charAtPos !== opts.radixPoint && charAtPos !== opts.negationSymbol.front && charAtPos !== opts.negationSymbol.back) (caretPos = $.inArray("?", processValue)) > -1 ? processValue[caretPos] = charAtPos : caretPos = currentResult.caret || 0; else if (charAtPos === opts.radixPoint || charAtPos === opts.negationSymbol.front || charAtPos === opts.negationSymbol.back) {
23327                    var newCaretPos = $.inArray(charAtPos, processValue);
23328                    -1 !== newCaretPos && (caretPos = newCaretPos);
23329                }
23330                opts.numericInput && (caretPos = processValue.length - caretPos - 1, processValue = processValue.reverse());
23331                var rslt = {
23332                    caret: charAtPos === undefined || currentResult.pos !== undefined ? caretPos + (opts.numericInput ? -1 : 1) : caretPos,
23333                    buffer: processValue,
23334                    refreshFromBuffer: currentResult.dopost || buffer.join("") !== processValue.join("")
23335                };
23336                return rslt.refreshFromBuffer ? rslt : currentResult;
23337            },
23338            onBeforeWrite: function(e, buffer, caretPos, opts) {
23339                if (e) switch (e.type) {
23340                  case "keydown":
23341                    return opts.postValidation(buffer, {
23342                        caret: caretPos,
23343                        dopost: !0
23344                    }, opts);
23345
23346                  case "blur":
23347                  case "checkval":
23348                    var unmasked;
23349                    if (function(opts) {
23350                        opts.parseMinMaxOptions === undefined && (null !== opts.min && (opts.min = opts.min.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
23351                        "," === opts.radixPoint && (opts.min = opts.min.replace(opts.radixPoint, ".")), 
23352                        opts.min = isFinite(opts.min) ? parseFloat(opts.min) : NaN, isNaN(opts.min) && (opts.min = Number.MIN_VALUE)), 
23353                        null !== opts.max && (opts.max = opts.max.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
23354                        "," === opts.radixPoint && (opts.max = opts.max.replace(opts.radixPoint, ".")), 
23355                        opts.max = isFinite(opts.max) ? parseFloat(opts.max) : NaN, isNaN(opts.max) && (opts.max = Number.MAX_VALUE)), 
23356                        opts.parseMinMaxOptions = "done");
23357                    }(opts), null !== opts.min || null !== opts.max) {
23358                        if (unmasked = opts.onUnMask(buffer.join(""), undefined, $.extend({}, opts, {
23359                            unmaskAsNumber: !0
23360                        })), null !== opts.min && unmasked < opts.min) return opts.isNegative = opts.min < 0, 
23361                        opts.postValidation(opts.min.toString().replace(".", opts.radixPoint).split(""), {
23362                            caret: caretPos,
23363                            dopost: !0,
23364                            placeholder: "0"
23365                        }, opts);
23366                        if (null !== opts.max && unmasked > opts.max) return opts.isNegative = opts.max < 0, 
23367                        opts.postValidation(opts.max.toString().replace(".", opts.radixPoint).split(""), {
23368                            caret: caretPos,
23369                            dopost: !0,
23370                            placeholder: "0"
23371                        }, opts);
23372                    }
23373                    return opts.postValidation(buffer, {
23374                        caret: caretPos,
23375                        placeholder: "0",
23376                        event: "blur"
23377                    }, opts);
23378
23379                  case "_checkval":
23380                    return {
23381                        caret: caretPos
23382                    };
23383                }
23384            },
23385            regex: {
23386                integerPart: function(opts, emptyCheck) {
23387                    return emptyCheck ? new RegExp("[" + Inputmask.escapeRegex(opts.negationSymbol.front) + "+]?") : new RegExp("[" + Inputmask.escapeRegex(opts.negationSymbol.front) + "+]?\\d+");
23388                },
23389                integerNPart: function(opts) {
23390                    return new RegExp("[\\d" + Inputmask.escapeRegex(opts.groupSeparator) + Inputmask.escapeRegex(opts.placeholder.charAt(0)) + "]+");
23391                }
23392            },
23393            definitions: {
23394                "~": {
23395                    validator: function(chrs, maskset, pos, strict, opts, isSelection) {
23396                        var isValid = strict ? new RegExp("[0-9" + Inputmask.escapeRegex(opts.groupSeparator) + "]").test(chrs) : new RegExp("[0-9]").test(chrs);
23397                        if (!0 === isValid) {
23398                            if (!0 !== opts.numericInput && maskset.validPositions[pos] !== undefined && "~" === maskset.validPositions[pos].match.def && !isSelection) {
23399                                var processValue = maskset.buffer.join(""), pvRadixSplit = (processValue = (processValue = processValue.replace(new RegExp("[-" + Inputmask.escapeRegex(opts.negationSymbol.front) + "]", "g"), "")).replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), "")).split(opts.radixPoint);
23400                                pvRadixSplit.length > 1 && (pvRadixSplit[1] = pvRadixSplit[1].replace(/0/g, opts.placeholder.charAt(0))), 
23401                                "0" === pvRadixSplit[0] && (pvRadixSplit[0] = pvRadixSplit[0].replace(/0/g, opts.placeholder.charAt(0))), 
23402                                processValue = pvRadixSplit[0] + opts.radixPoint + pvRadixSplit[1] || "";
23403                                var bufferTemplate = maskset._buffer.join("");
23404                                for (processValue === opts.radixPoint && (processValue = bufferTemplate); null === processValue.match(Inputmask.escapeRegex(bufferTemplate) + "$"); ) bufferTemplate = bufferTemplate.slice(1);
23405                                isValid = (processValue = (processValue = processValue.replace(bufferTemplate, "")).split(""))[pos] === undefined ? {
23406                                    pos: pos,
23407                                    remove: pos
23408                                } : {
23408
23409                                    pos: pos
23410                                };
23411                            }
23412                        } else strict || chrs !== opts.radixPoint || maskset.validPositions[pos - 1] !== undefined || (maskset.buffer[pos] = "0", 
23413                        isValid = {
23414                            pos: pos + 1
23415                        });
23416                        return isValid;
23417                    },
23418                    cardinality: 1
23419                },
23420                "+": {
23421                    validator: function(chrs, maskset, pos, strict, opts) {
23422                        return opts.allowMinus && ("-" === chrs || chrs === opts.negationSymbol.front);
23423                    },
23424                    cardinality: 1,
23425                    placeholder: ""
23426                },
23427                "-": {
23428                    validator: function(chrs, maskset, pos, strict, opts) {
23429                        return opts.allowMinus && chrs === opts.negationSymbol.back;
23430                    },
23431                    cardinality: 1,
23432                    placeholder: ""
23433                },
23434                ":": {
23435                    validator: function(chrs, maskset, pos, strict, opts) {
23436                        var radix = "[" + Inputmask.escapeRegex(opts.radixPoint) + "]", isValid = new RegExp(radix).test(chrs);
23437                        return isValid && maskset.validPositions[pos] && maskset.validPositions[pos].match.placeholder === opts.radixPoint && (isValid = {
23438                            caret: pos + 1
23439                        }), isValid;
23440                    },
23441                    cardinality: 1,
23442                    placeholder: function(opts) {
23443                        return opts.radixPoint;
23444                    }
23445                }
23446            },
23447            onUnMask: function(maskedValue, unmaskedValue, opts) {
23448                if ("" === unmaskedValue && !0 === opts.nullable) return unmaskedValue;
23449                var processValue = maskedValue.replace(opts.prefix, "");
23450                return processValue = processValue.replace(opts.suffix, ""), processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
23451                "" !== opts.placeholder.charAt(0) && (processValue = processValue.replace(new RegExp(opts.placeholder.charAt(0), "g"), "0")), 
23452                opts.unmaskAsNumber ? ("" !== opts.radixPoint && -1 !== processValue.indexOf(opts.radixPoint) && (processValue = processValue.replace(Inputmask.escapeRegex.call(this, opts.radixPoint), ".")), 
23453                processValue = processValue.replace(new RegExp("^" + Inputmask.escapeRegex(opts.negationSymbol.front)), "-"), 
23454                processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), ""), 
23455                Number(processValue)) : processValue;
23456            },
23457            isComplete: function(buffer, opts) {
23458                var maskedValue = buffer.join("");
23459                if (buffer.slice().join("") !== maskedValue) return !1;
23460                var processValue = maskedValue.replace(opts.prefix, "");
23461                return processValue = processValue.replace(opts.suffix, ""), processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
23462                "," === opts.radixPoint && (processValue = processValue.replace(Inputmask.escapeRegex(opts.radixPoint), ".")), 
23463                isFinite(processValue);
23464            },
23465            onBeforeMask: function(initialValue, opts) {
23466                if (opts.isNegative = undefined, initialValue = initialValue.toString().charAt(initialValue.length - 1) === opts.radixPoint ? initialValue.toString().substr(0, initialValue.length - 1) : initialValue.toString(), 
23467                "" !== opts.radixPoint && isFinite(initialValue)) {
23468                    var vs = initialValue.split("."), groupSize = "" !== opts.groupSeparator ? parseInt(opts.groupSize) : 0;
23469                    2 === vs.length && (vs[0].length > groupSize || vs[1].length > groupSize || vs[0].length <= groupSize && vs[1].length < groupSize) && (initialValue = initialValue.replace(".", opts.radixPoint));
23470                }
23471                var kommaMatches = initialValue.match(/,/g), dotMatches = initialValue.match(/\./g);
23472                if (initialValue = dotMatches && kommaMatches ? dotMatches.length > kommaMatches.length ? (initialValue = initialValue.replace(/\./g, "")).replace(",", opts.radixPoint) : kommaMatches.length > dotMatches.length ? (initialValue = initialValue.replace(/,/g, "")).replace(".", opts.radixPoint) : initialValue.indexOf(".") < initialValue.indexOf(",") ? initialValue.replace(/\./g, "") : initialValue.replace(/,/g, "") : initialValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
23473                0 === opts.digits && (-1 !== initialValue.indexOf(".") ? initialValue = initialValue.substring(0, initialValue.indexOf(".")) : -1 !== initialValue.indexOf(",") && (initialValue = initialValue.substring(0, initialValue.indexOf(",")))), 
23474                "" !== opts.radixPoint && isFinite(opts.digits) && -1 !== initialValue.indexOf(opts.radixPoint)) {
23475                    var decPart = initialValue.split(opts.radixPoint)[1].match(new RegExp("\\d*"))[0];
23476                    if (parseInt(opts.digits) < decPart.toString().length) {
23477                        var digitsFactor = Math.pow(10, parseInt(opts.digits));
23478                        initialValue = initialValue.replace(Inputmask.escapeRegex(opts.radixPoint), "."), 
23479                        initialValue = (initialValue = Math.round(parseFloat(initialValue) * digitsFactor) / digitsFactor).toString().replace(".", opts.radixPoint);
23480                    }
23481                }
23482                return initialValue;
23483            },
23484            canClearPosition: function(maskset, position, lvp, strict, opts) {
23485                var vp = maskset.validPositions[position], canClear = vp.input !== opts.radixPoint || null !== maskset.validPositions[position].match.fn && !1 === opts.decimalProtect || vp.input === opts.radixPoint && maskset.validPositions[position + 1] && null === maskset.validPositions[position + 1].match.fn || isFinite(vp.input) || position === lvp || vp.input === opts.groupSeparator || vp.input === opts.negationSymbol.front || vp.input === opts.negationSymbol.back;
23486                return !canClear || "+" !== vp.match.nativeDef && "-" !== vp.match.nativeDef || (opts.isNegative = !1), 
23487                canClear;
23488            },
23489            onKeyDown: function(e, buffer, caretPos, opts) {
23490                var $input = $(this);
23491                if (e.ctrlKey) switch (e.keyCode) {
23492                  case Inputmask.keyCode.UP:
23493                    $input.val(parseFloat(this.inputmask.unmaskedvalue()) + parseInt(opts.step)), $input.trigger("setvalue");
23494                    break;
23495
23496                  case Inputmask.keyCode.DOWN:
23497                    $input.val(parseFloat(this.inputmask.unmaskedvalue()) - parseInt(opts.step)), $input.trigger("setvalue");
23498                }
23499            }
23500        },
23501        currency: {
23502            prefix: "$ ",
23503            groupSeparator: ",",
23504            alias: "numeric",
23505            placeholder: "0",
23506            autoGroup: !0,
23507            digits: 2,
23508            digitsOptional: !1,
23509            clearMaskOnLostFocus: !1
23510        },
23511        decimal: {
23512            alias: "numeric"
23513        },
23514        integer: {
23515            alias: "numeric",
23516            digits: 0,
23517            radixPoint: ""
23518        },
23519        percentage: {
23520            alias: "numeric",
23521            digits: 2,
23522            digitsOptional: !0,
23523            radixPoint: ".",
23524            placeholder: "0",
23525            autoGroup: !1,
23526            min: 0,
23527            max: 100,
23528            suffix: " %",
23529            allowMinus: !1
23530        }
23531    }), Inputmask;
23532});
23533/*!
23534* inputmask.phone.extensions.js
23535* https://github.com/RobinHerbots/Inputmask
23536* Copyright (c) 2010 - 2017 Robin Herbots
23537* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
23538* Version: 3.3.11
23539*/
23540
23541!function(factory) {
23542    "function" == typeof define && define.amd ? define([ "./dependencyLibs/inputmask.dependencyLib", "./inputmask" ], factory) : "object" == typeof exports ? module.exports = factory(require("./dependencyLibs/inputmask.dependencyLib"), require("./inputmask")) : factory(window.dependencyLib || jQuery, window.Inputmask);
23543}(function($, Inputmask) {
23544    function maskSort(a, b) {
23545        var maska = (a.mask || a).replace(/#/g, "9").replace(/\)/, "9").replace(/[+()#-]/g, ""), maskb = (b.mask || b).replace(/#/g, "9").replace(/\)/, "9").replace(/[+()#-]/g, ""), maskas = (a.mask || a).split("#")[0], maskbs = (b.mask || b).split("#")[0];
23546        return 0 === maskbs.indexOf(maskas) ? -1 : 0 === maskas.indexOf(maskbs) ? 1 : maska.localeCompare(maskb);
23547    }
23548    var analyseMaskBase = Inputmask.prototype.analyseMask;
23549    return Inputmask.prototype.analyseMask = function(mask, regexMask, opts) {
23550        function reduceVariations(masks, previousVariation, previousmaskGroup) {
23551            previousVariation = previousVariation || "", previousmaskGroup = previousmaskGroup || maskGroups, 
23552            "" !== previousVariation && (previousmaskGroup[previousVariation] = {});
23553            for (var variation = "", maskGroup = previousmaskGroup[previousVariation] || previousmaskGroup, i = masks.length - 1; i >= 0; i--) maskGroup[variation = (mask = masks[i].mask || masks[i]).substr(0, 1)] = maskGroup[variation] || [], 
23554            maskGroup[variation].unshift(mask.substr(1)), masks.splice(i, 1);
23555            for (var ndx in maskGroup) maskGroup[ndx].length > 500 && reduceVariations(maskGroup[ndx].slice(), ndx, maskGroup);
23556        }
23557        function rebuild(maskGroup) {
23558            var mask = "", submasks = [];
23559            for (var ndx in maskGroup) $.isArray(maskGroup[ndx]) ? 1 === maskGroup[ndx].length ? submasks.push(ndx + maskGroup[ndx]) : submasks.push(ndx + opts.groupmarker.start + maskGroup[ndx].join(opts.groupmarker.end + opts.alternatormarker + opts.groupmarker.start) + opts.groupmarker.end) : submasks.push(ndx + rebuild(maskGroup[ndx]));
23560            return 1 === submasks.length ? mask += submasks[0] : mask += opts.groupmarker.start + submasks.join(opts.groupmarker.end + opts.alternatormarker + opts.groupmarker.start) + opts.groupmarker.end, 
23561            mask;
23562        }
23563        var maskGroups = {};
23564        return opts.phoneCodes && (opts.phoneCodes && opts.phoneCodes.length > 1e3 && (reduceVariations((mask = mask.substr(1, mask.length - 2)).split(opts.groupmarker.end + opts.alternatormarker + opts.groupmarker.start)), 
23565        mask = rebuild(maskGroups)), mask = mask.replace(/9/g, "\\9")), analyseMaskBase.call(this, mask, regexMask, opts);
23566    }, Inputmask.extendAliases({
23567        abstractphone: {
23568            groupmarker: {
23569                start: "<",
23570                end: ">"
23571            },
23572            countrycode: "",
23573            phoneCodes: [],
23574            mask: function(opts) {
23575                return opts.definitions = {
23576                    "#": Inputmask.prototype.definitions[9]
23577                }, opts.phoneCodes.sort(maskSort);
23578            },
23579            keepStatic: !0,
23580            onBeforeMask: function(value, opts) {
23581                var processedValue = value.replace(/^0{1,2}/, "").replace(/[\s]/g, "");
23582                return (processedValue.indexOf(opts.countrycode) > 1 || -1 === processedValue.indexOf(opts.countrycode)) && (processedValue = "+" + opts.c
vendor: 4,864 bytes, lines 23582-23755
23582ountrycode + processedValue), 
23583                processedValue;
23584            },
23585            onUnMask: function(maskedValue, unmaskedValue, opts) {
23586                return maskedValue.replace(/[()#-]/g, "");
23587            },
23588            inputmode: "tel"
23589        }
23590    }), Inputmask;
23591});
23592/*! nouislider - 10.1.0 - 2017-07-28 17:11:18 */
23593
23594(function (factory) {
23595
23596    if ( typeof define === 'function' && define.amd ) {
23597
23598        // AMD. Register as an anonymous module.
23599        define([], factory);
23600
23601    } else if ( typeof exports === 'object' ) {
23602
23603        // Node/CommonJS
23604        module.exports = factory();
23605
23606    } else {
23607
23608        // Browser globals
23609        window.noUiSlider = factory();
23610    }
23611
23612}(function( ){
23613
23614	'use strict';
23615
23616	var VERSION = '10.1.0';
23617
23618
23619	function isValidFormatter ( entry ) {
23620		return typeof entry === 'object' && typeof entry.to === 'function' && typeof entry.from === 'function';
23621	}
23622
23623	function removeElement ( el ) {
23624		el.parentElement.removeChild(el);
23625	}
23626
23627	// Bindable version
23628	function preventDefault ( e ) {
23629		e.preventDefault();
23630	}
23631
23632	// Removes duplicates from an array.
23633	function unique ( array ) {
23634		return array.filter(function(a){
23635			return !this[a] ? this[a] = true : false;
23636		}, {});
23637	}
23638
23639	// Round a value to the closest 'to'.
23640	function closest ( value, to ) {
23641		return Math.round(value / to) * to;
23642	}
23643
23644	// Current position of an element relative to the document.
23645	function offset ( elem, orientation ) {
23646
23647		var rect = elem.getBoundingClientRect();
23648		var doc = elem.ownerDocument;
23649		var docElem = doc.documentElement;
23650		var pageOffset = getPageOffset(doc);
23651
23652		// getBoundingClientRect contains left scroll in Chrome on Android.
23653		// I haven't found a feature detection that proves this. Worst case
23654		// scenario on mis-match: the 'tap' feature on horizontal sliders breaks.
23655		if ( /webkit.*Chrome.*Mobile/i.test(navigator.userAgent) ) {
23656			pageOffset.x = 0;
23657		}
23658
23659		return orientation ? (rect.top + pageOffset.y - docElem.clientTop) : (rect.left + pageOffset.x - docElem.clientLeft);
23660	}
23661
23662	// Checks whether a value is numerical.
23663	function isNumeric ( a ) {
23664		return typeof a === 'number' && !isNaN( a ) && isFinite( a );
23665	}
23666
23667	// Sets a class and removes it after [duration] ms.
23668	function addClassFor ( element, className, duration ) {
23669		if (duration > 0) {
23670		addClass(element, className);
23671			setTimeout(function(){
23672				removeClass(element, className);
23673			}, duration);
23674		}
23675	}
23676
23677	// Limits a value to 0 - 100
23678	function limit ( a ) {
23679		return Math.max(Math.min(a, 100), 0);
23680	}
23681
23682	// Wraps a variable as an array, if it isn't one yet.
23683	// Note that an input array is returned by reference!
23684	function asArray ( a ) {
23685		return Array.isArray(a) ? a : [a];
23686	}
23687
23688	// Counts decimals
23689	function countDecimals ( numStr ) {
23690		numStr = String(numStr);
23691		var pieces = numStr.split(".");
23692		return pieces.length > 1 ? pieces[1].length : 0;
23693	}
23694
23695	// http://youmightnotneedjquery.com/#add_class
23696	function addClass ( el, className ) {
23697		if ( el.classList ) {
23698			el.classList.add(className);
23699		} else {
23700			el.className += ' ' + className;
23701		}
23702	}
23703
23704	// http://youmightnotneedjquery.com/#remove_class
23705	function removeClass ( el, className ) {
23706		if ( el.classList ) {
23707			el.classList.remove(className);
23708		} else {
23709			el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
23710		}
23711	}
23712
23713	// https://plainjs.com/javascript/attributes/adding-removing-and-testing-for-classes-9/
23714	function hasClass ( el, className ) {
23715		return el.classList ? el.classList.contains(className) : new RegExp('\\b' + className + '\\b').test(el.className);
23716	}
23717
23718	// https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY#Notes
23719	function getPageOffset ( doc ) {
23720
23721		var supportPageOffset = window.pageXOffset !== undefined;
23722		var isCSS1Compat = ((doc.compatMode || "") === "CSS1Compat");
23723		var x = supportPageOffset ? window.pageXOffset : isCSS1Compat ? doc.documentElement.scrollLeft : doc.body.scrollLeft;
23724		var y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? doc.documentElement.scrollTop : doc.body.scrollTop;
23725
23726		return {
23727			x: x,
23728			y: y
23729		};
23730	}
23731
23732	// we provide a function to compute constants instead
23733	// of accessing window.* as soon as the module needs it
23734	// so that we do not compute anything if not needed
23735	function getActions ( ) {
23736
23737		// Determine the events to bind. IE11 implements pointerEvents without
23738		// a prefix, which breaks compatibility with the IE10 implementation.
23739		return window.navigator.pointerEnabled ? {
23740			start: 'pointerdown',
23741			move: 'pointermove',
23742			end: 'pointerup'
23743		} : window.navigator.msPointerEnabled ? {
23744			start: 'MSPointerDown',
23745			move: 'MSPointerMove',
23746			end: 'MSPointerUp'
23747		} : {
23748			start: 'mousedown touchstart',
23749			move: 'mousemove touchmove',
23750			end: 'mouseup touchend'
23751		};
23752	}
23753
23754	// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
23755	// Issue #785
23756	function getSupportsPassive ( ) {
23757
23758		var supportsPassive = false;
23759
23760		try {
23761
23762			var opts = Object.defineProperty({}, 'passive', {
23763				get: function() {
23764					supportsPassive = true;
23765				}
23766			});
23767
23768			window.addEventListener('test', null, opts);
23769
23770		} catch (e) {}
23771
23772		return supportsPassive;
23773	}
23774
23775	function getSupportsTouchActionNone ( ) {
23776		return window.CSS && CSS.supports && CSS.supports('touch-action', 'none');
23777	}
23778
23779
23780// Value calculation
23781
23782	// Determine the size of a sub-range in relation to a full range.
23783	function subRangeRatio ( pa, pb ) {
23784		return (100 / (pb - pa));
23785	}
23786
23787	// (percentage) How many percent is this value of this range?
23788	function fromPercentage ( range, value ) {
23789		return (value * 100) / ( range[1] - range[0] );
23790	}
23791
23792	// (percentage) Where is this value on this range?
23793	function toPercentage ( range, value ) {
23794		return fromPercentage( range, range[0] < 0 ?
23795			value + Math.abs(range[0]) :
23796				value - range[0] );
23797	}
23798
23799	// (value) How much is this percentage on this range?
23800	function isPercentage ( range, value ) {
23801		return ((value * ( range[1] - range[0] )) / 100) + range[0];
23802	}
23803
23804
23805// Range conversion
23806
23807	function getJ ( value, arr ) {
23808
23809		var j = 1;
23810
23811		while ( value >= arr[j] ){
23812			j += 1;
23813		}
23814
23815		return j;
23816	}
23817
23818	// (percentage) Input a value, find where, on a scale of 0-100, it applies.
23819	function toStepping ( xVal, xPct, value ) {
23820
23821		if ( value >= xVal.slice(-1)[0] ){
23822			return 100;
23823		}
23824
23825		var j = getJ( value, xVal ), va, vb, pa, pb;
23826
23827		va = xVal[j-1];
23828		vb = xVal[j];
23829		pa = xPct[j-1];
23830		pb = xPct[j];
23831
23832		return pa + (toPercentage([va, vb], value) / subRangeRatio (pa, pb));
23833	}
23834
23835	// (value) Input a percentage, find where it is on the specified range.
23836	function fromStepping ( xVal, xPct, value ) {
23837
23838		// There is no range group that fits 100
23839		if ( value >= 100 ){
23840			return xVal.slice(-1)[0];
23841		}
23842
23843		var j = getJ( value, xPct ), va, vb, pa, pb;
23844
23845		va = xVal[j-1];
23846		vb = xVal[j];
23847		pa = xPct[j-1];
23848		pb = xPct[j];
23849
23850		return isPercentage([va, vb], (value - pa) * subRangeRatio (pa, pb));
23851	}
23852
23853	// (percentage) Get the step that applies at a certain value.
23854	function getStep ( xPct, xSteps, snap, value ) {
23855
23856		if ( value === 100 ) {
23857			return value;
23858		}
23859
23860		var j = getJ( value, xPct ), a, b;
23861
23862		// If 'snap' is set, steps are used as fixed points on the slider.
23863		if ( snap ) {
23864
23865			a = xPct[j-1];
23866			b = xPct[j];
23867
23868			// Find the closest position, a or b.
23869			if ((value - a) > ((b-a)/2)){
23870				return b;
23871			}
23872
23873			return a;
23874		}
23875
23876		if ( !xSteps[j-1] ){
23877			return value;
23878		}
23879
23880		return xPct[j-1] + closest(
23881			value - xPct[j-1],
23882			xSteps[j-1]
23883		);
23884	}
23885
23886
23887// Entry parsing
23888
23889	function handleEntryPoint ( index, value, that ) {
23890
23891		var percentage;
23892
23893		// Wrap numerical input in an array.
23894		if ( typeof value === "number" ) {
23895			value = [value];
23896		}
23897
23898		// Reject any invalid input, by testing whether value is an array.
23899		if ( Object.prototype.toString.call( value ) !== '[object Array]' ){
23900			throw new Error("noUiSlider (" + VERSION + "): 'range' contains invalid value.");
23901		}
23902
23903		// Covert min/max syntax to 0 and 100.
23904		if ( index === 'min' ) {
23905			percentage = 0;
23906		} else if ( index === 'max' ) {
23907			percentage = 100;
23908		} else {
23909			percentage = parseFloat( index );
23910		}
23911
23912		// Check for correct input.
23913		if ( !isNumeric( percentage ) || !isNumeric( value[0] ) ) {
23914			throw new Error("noUiSlider (" + VERSION + "): 'range' value isn't numeric.");
23915		}
23916
23917		// Store values.
23918		that.xPct.push( percentage );
23919		that.xVal.push( value[0] );
23920
23921		// NaN will evaluate to false too, but to keep
23922		// logging clear, set step explicitly. Make sure
23923		// not to override the 'step' setting with false.
23924		if ( !percentage ) {
23925			if ( !isNaN( value[1] ) ) {
23926				that.xSteps[0] = value[1];
23927			}
23928		} else {
23929			that.xSteps.push( isNaN(value[1]) ? false : value[1] );
23930		}
23931
23932		that.xHighestCompleteStep.push(0);
23933	}
23934
23935	function handleStepPoint ( i, n, that ) {
23936
23937		// Ignore 'false' stepping.
23938		if ( !n ) {
23939			return true;
23940		}
23941
23942		// Factor to range ratio
23943		that.xSteps[i] = fromPercentage([
23944			 that.xVal[i]
23945			,that.xVal[i+1]
23946		], n) / subRangeRatio (
23947			that.xPct[i],
23948			that.xPct[i+1] );
23949
23950		var totalSteps = (that.xVal[i+1] - that.xVal[i]) / that.xNumSteps[i];
23951		var highestStep = Math.ceil(Number(totalSteps.toFixed(3)) - 1);
23952		var step = that.xVal[i] + (that.xNumSteps[i] * highestStep);
23953
23954		that.xHighestCompleteStep[i] = step;
23955	}
23956
23957
23958// Interface
23959
23960	function Spectrum ( entry, snap, singleStep ) {
23961
23962		this.xPct = [];
23963		this.xVal = [];
23964		this.xSteps = [ singleStep || false ];
23965		this.xNumSteps = [ false ];
23966		this.xHighestCompleteStep = [];
23967
23968		this.snap = snap;
23969
23970		var index, ordered = [ /* [0, 'min'], [1, '50%'], [2, 'max'] */ ];
23971
23972		// Map the object keys to an array.
23973		for ( index in entry ) {
23974			if ( entry.hasOwnProperty(index) ) {
23975				ordered.push([entry[index], index]);
23976			}
23977		}
23978
23979		// Sort all entries by value (numeric sort).
23980		if ( ordered.length && typeof ordered[0][0] === "object" ) {
23981			ordered.sort(function(a, b) { return a[0][0] - b[0][0]; });
23982		} else {
23983			ordered.sort(function(a, b) { return a[0] - b[0]; });
23984		}
23985
23986
23987		// Convert all entries to subranges.
23988		for ( index = 0; index < ordered.length; index++ ) {
23989			handleEntryPoint(ordered[index][1], ordered[index][0], this);
23990		}
23991
23992		// Store the actual step values.
23993		// xSteps is sorted in the same order as xPct and xVal.
23994		this.xNumSteps = this.xSteps.slice(0);
23995
23996		// Convert all numeric steps to the percentage of the subrange they represent.
23997		for ( index = 0; index < this.xNumSteps.length; index++ ) {
23998			handleStepPoint(index, this.xNumSteps[index], this);
23999		}
24000	}
24001
24002	Spectrum.prototype.getMargin = function ( value ) {
24003
24004		var step = this.xNumSteps[0];
24005
24006		if ( step && ((value / step) % 1) !== 0 ) {
24007			throw new Error("noUiSlider (" + VERSION + "): 'limit', 'margin' and 'padding' must be divisible by step.");
24008		}
24009
24010		return this.xPct.length === 2 ? fromPercentage(this.xVal, value) : false;
24011	};
24012
24013	Spectrum.prototype.toStepping = function ( value ) {
24014
24015		value = toStepping( this.xVal, this.xPct, value );
24016
24017		return value;
24018	};
24019
24020	Spectrum.prototype.fromStepping = function ( value ) {
24021
24022		return fromStepping( this.xVal, this.xPct, value );
24023	};
24024
24025	Spectrum.prototype.getStep = function ( value ) {
24026
24027		value = getStep(this.xPct, this.xSteps, this.snap, value );
24028
24029		return value;
24030	};
24031
24032	Spectrum.prototype.getNearbySteps = function ( value ) {
24033
24034		var j = getJ(value, this.xPct);
24035
24036		return {
24037			stepBefore: { startValue: this.xVal[j-2], step: this.xNumSteps[j-2], highestStep: this.xHighestCompleteStep[j-2] },
24038			thisStep: { startValue: this.xVal[j-1], step: this.xNumSteps[j-1], highestStep: this.xHighestCompleteStep[j-1] },
24039			stepAfter: { startValue: this.xVal[j-0], step: this.xNumSteps[j-0], highestStep: this.xHighestCompleteStep[j-0] }
24040		};
24041	};
24042
24043	Spectrum.prototype.countStepDecimals = function () {
24044		var stepDecimals = this.xNumSteps.map(countDecimals);
24045		return Math.max.apply(null, stepDecimals);
24046 	};
24047
24048	// Outside testing
24049	Spectrum.prototype.convert = function ( value ) {
24050		return this.getStep(this.toStepping(value));
24051	};
24052
24053/*	Every input option is tested and parsed. This'll prevent
24054	endless validation in internal methods. These tests are
24055	structured with an item for every option available. An
24056	option can be marked as required by setting the 'r' flag.
24057	The testing function is provided with three arguments:
24058		- The provided value for the option;
24059		- A reference to the options object;
24060		- The name for the option;
24061
24062	The testing function returns false when an error is detected,
24063	or true when everything is OK. It can also modify the option
24064	object, to make sure all values can be correctly looped elsewhere. */
24065
24066	var defaultFormatter = { 'to': function( value ){
24067		return value !== undefined && value.toFixed(2);
24068	}, 'from': Number };
24069
24070	function validateFormat ( entry ) {
24071
24072		// Any object with a to and from method is supported.
24073		if ( isValidFormatter(entry) ) {
24074			return true;
24075		}
24076
24077		throw new Error("noUiSlider (" + VERSION + "): 'format' requires 'to' and 'from' methods.");
24078	}
24079
24080	function testStep ( parsed, entry ) {
24081
24082		if ( !isNumeric( entry ) ) {
24083			throw new Error("noUiSlider (" + VERSION + "): 'step' is not numeric.");
24084		}
24085
24086		// The step option can still be used to set stepping
24087		// for linear sliders. Overwritten if set in 'range'.
24088		parsed.singleStep = entry;
24089	}
24090
24091	function testRange ( parsed, entry ) {
24092
24093		// Filter incorrect input.
24094		if ( typeof entry !== 'object' || Array.isArray(entry) ) {
24095			throw new Error("noUiSlider (" + VERSION + "): 'range' is not an object.");
24096		}
24097
24098		// Catch missing start or end.
24099		if ( entry.min === undefined || entry.max === undefined ) {
24100			throw new Error("noUiSlider (" + VERSION + "): Missing 'min' or 'max' in 'range'.");
24101		}
24102
24103		// Catch equal start or end.
24104		if ( entry.min === entry.max ) {
24105			throw new Error("noUiSlider (" + VERSION + "): 'range' 'min' and 'max' cannot be equal.");
24106		}
24107
24108		parsed.spectrum = new Spectrum(entry, parsed.snap, parsed.singleStep);
24109	}
24110
24111	function testStart ( parsed, entry ) {
24112
24113		entry = asArray(entry);
24114
24115		// Validate input. Values aren't tested, as the public .val method
24116		// will always provide a valid location.
24117		if ( !Array.isArray( entry ) || !entry.length ) {
24118			throw new Error("noUiSlider (" + VERSION + "): 'start' option is incorrect.");
24119		}
24120
24121		// Store the number of handles.
24122		parsed.handles = entry.length;
24123
24124		// When the slider is initialized, the .val method will
24125		// be called with the start options.
24126		parsed.start = entry;
24127	}
24128
24129	function testSnap ( parsed, entry ) {
24130
24131		// Enforce 100% stepping within subranges.
24132		parsed.snap = entry;
24133
24134		if ( typeof entry !== 'boolean' ){
24135			throw new Error("noUiSlider (" + VERSION + "): 'snap' option must be a boolean.");
24136		}
24137	}
24138
24139	function testAnimate ( parsed, entry ) {
24140
24141		// Enforce 100% stepping within subranges.
24142		parsed.animate = entry;
24143
24144		if ( typeof entry !== 'boolean' ){
24145			throw new Error("noUiSlider (" + VERSION + "): 'animate' option must be a boolean.");
24146		}
24147	}
24148
24149	function testAnimationDuration ( parsed, entry ) {
24150
24151		parsed.animationDuration = entry;
24152
24153		if ( typeof entry !== 'number' ){
24154			throw new Error("noUiSlider (" + VERSION + "): 'animationDuration' option must be a number.");
24155		}
24156	}
24157
24158	function testConnect ( parsed, entry ) {
24159
24160		var connect = [false];
24161		var i;
24162
24163		// Map legacy options
24164		if ( entry === 'lower' ) {
24165			entry = [true, false];
24166		}
24167
24168		else if ( entry === 'upper' ) {
24169			entry = [false, true];
24170		}
24171
24172		// Handle boolean options
24173		if ( entry === true || entry === false ) {
24174
24175			for ( i = 1; i < parsed.handles; i++ ) {
24176				connect.push(entry);
24177			}
24178
24179			connect.push(false);
24180		}
24181
24182		// Reject invalid input
24183		else if ( !Array.isArray( entry ) || !entry.length || entry.length !== parsed.handles + 1 ) {
24184			throw new Error("noUiSlider (" + VERSION + "): 'connect' option doesn't match handle count.");
24185		}
24186
24187		else {
24188			connect = entry;
24189		}
24190
24191		parsed.connect = connect;
24192	}
24193
24194	function testOrientation ( parsed, entry ) {
24195
24196		// Set orientation to an a numerical value for easy
24197		// array selection.
24198		switch ( entry ){
24199		  case 'horizontal':
24200			parsed.ort = 0;
24201			break;
24202		  case 'vertical':
24203			parsed.ort = 1;
24204			break;
24205		  default:
24206			throw new Error("noUiSlider (" + VERSION + "): 'orientation' option is invalid.");
24207		}
24208	}
24209
24210	function testMargin ( parsed, entry ) {
24211
24212		if ( !isNumeric(entry) ){
24213			throw new Error("noUiSlider (" + VERSION + "): 'margin' option must be numeric.");
24214		}
24215
24216		// Issue #582
24217		if ( entry === 0 ) {
24218			return;
24219		}
24220
24221		parsed.margin = parsed.spectrum.getMargin(entry);
24222
24223		if ( !parsed.margin ) {
24224			throw new Error("noUiSlider (" + VERSION + "): 'margin' option is only supported on linear sliders.");
24225		}
24226	}
24227
24228	function testLimit ( parsed, entry ) {
24229
24230		if ( !isNumeric(entry) ){
24231			throw new Error("noUiSlider (" + VERSION + "): 'limit' option must be numeric.");
24232		}
24233
24234		parsed.limit = parsed.spectrum.getMargin(entry);
24235
24236		if ( !parsed.limit || parsed.handles < 2 ) {
24237			throw new Error("noUiSlider (" + VERSION + "): 'limit' option is only supported on linear sliders with 2 or more handles.");
24238		}
24239	}
24240
24241	function testPadding ( parsed, entry ) {
24242
24243		if ( !isNumeric(entry) ){
24244			throw new Error("noUiSlider (" + VERSION + "): 'padding' option must be numeric.");
24245		}
24246
24247		if ( entry === 0 ) {
24248			return;
24249		}
24250
24251		parsed.padding = parsed.spectrum.getMargin(entry);
24252
24253		if ( !parsed.padding ) {
24254			throw new Error("noUiSlider (" + VERSION + "): 'padding' option is only supported on linear sliders.");
24255		}
24256
24257		if ( parsed.padding < 0 ) {
24258			throw new Error("noUiSlider (" + VERSION + "): 'padding' option must be a positive number.");
24259		}
24260
24261		if ( parsed.padding >= 50 ) {
24262			throw new Error("noUiSlider (" + VERSION + "): 'padding' option must be less than half the range.");
24263		}
24264	}
24265
24266	function testDirection ( parsed, entry ) {
24267
24268		// Set direction as a numerical value for easy parsing.
24269		// Invert connection for RTL sliders, so that the proper
24270		// handles get the connect/background classes.
24271		switch ( entry ) {
24272		  case 'ltr':
24273			parsed.dir = 0;
24274			break;
24275		  case 'rtl':
24276			parsed.dir = 1;
24277			break;
24278		  default:
24279			throw new Error("noUiSlider (" + VERSION + "): 'direction' option was not recognized.");
24280		}
24281	}
24282
24283	function testBehaviour ( parsed, entry ) {
24284
24285		// Make sure the input is a string.
24286		if ( typeof entry !== 'string' ) {
24287			throw new Error("noUiSlider (" + VERSION + "): 'behaviour' must be a string containing options.");
24288		}
24289
24290		// Check if the string contains any keywords.
24291		// None are required.
24292		var tap = entry.indexOf('tap') >= 0;
24293		var drag = entry.indexOf('drag') >= 0;
24294		var fixed = entry.indexOf('fixed') >= 0;
24295		var snap = entry.indexOf('snap') >= 0;
24296		var hover = entry.indexOf('hover') >= 0;
24297
24298		if ( fixed ) {
24299
24300			if ( parsed.handles !== 2 ) {
24301				throw new Error("noUiSlider (" + VERSION + "): 'fixed' behaviour must be used with 2 handles");
24302			}
24303
24304			// Use margin to enforce fixed state
24305			testMargin(parsed, parsed.start[1] - parsed.start[0]);
24306		}
24307
24308		parsed.events = {
24309			tap: tap || snap,
24310			drag: drag,
24311			fixed: fixed,
24312			snap: snap,
24313			hover: hover
24314		};
24315	}
24316
24317	function testMultitouch ( parsed, entry ) {
24318		parsed.multitouch = entry;
24319
24320		if ( typeof entry !== 'boolean' ){
24321			throw new Error("noUiSlider (" + VERSION + "): 'multitouch' option must be a boolean.");
24322		}
24323	}
24324
24325	function testTooltips ( parsed, entry ) {
24326
24327		if ( entry === false ) {
24328			return;
24329		}
24330
24331		else if ( entry === true ) {
24332
24333			parsed.tooltips = [];
24334
24335			for ( var i = 0; i < parsed.handles; i++ ) {
24336				parsed.tooltips.push(true);
24337			}
24338		}
24339
24340		else {
24341
24342			parsed.tooltips = asArray(entry);
24343
24344			if ( parsed.tooltips.length !== parsed.handles ) {
24345				throw new Error("noUiSlider (" + VERSION + "): must pass a formatter for all handles.");
24346			}
24347
24348			parsed.tooltips.forEach(function(formatter){
24349				if ( typeof formatter !== 'boolean' && (typeof formatter !== 'object' || typeof formatter.to !== 'function') ) {
24350					throw new Error("noUiSlider (" + VERSION + "): 'tooltips' must be passed a formatter or 'false'.");
24351				}
24352			});
24353		}
24354	}
24355
24356	function testAriaFormat ( parsed, entry ) {
24357		parsed.ariaFormat = entry;
24358		validateFormat(entry);
24359	}
24360
24361	function testFormat ( parsed, entry ) {
24362		parsed.format = entry;
24363		validateFormat(entry);
24364	}
24365
24366	function testCssPrefix ( parsed, entry ) {
24367
24368		if ( entry !== undefined && typeof entry !== 'string' && entry !== false ) {
24369			throw new Error("noUiSlider (" + VERSION + "): 'cssPrefix' must be a string or `false`.");
24370		}
24371
24372		parsed.cssPrefix = entry;
24373	}
24374
24375	function testCssClasses ( parsed, entry ) {
24376
24377		if ( entry !== undefined && typeof entry !== 'object' ) {
24378			throw new Error("noUiSlider (" + VERSION + "): 'cssClasses' must be an object.");
24379		}
24380
24381		if ( typeof parsed.cssPrefix === 'string' ) {
24382			parsed.cssClasses = {};
24383
24384			for ( var key in entry ) {
24385				if ( !entry.hasOwnProperty(key) ) { continue; }
24386
24387				parsed.cssClasses[key] = parsed.cssPrefix + entry[key];
24388			}
24389		} else {
24390			parsed.cssClasses = entry;
24391		}
24392	}
24393
24394	function testUseRaf ( parsed, entry ) {
24395		if ( entry === true || entry === false ) {
24396			parsed.useRequestAnimationFrame = entry;
24397		} else {
24398			throw new Error("noUiSlider (" + VERSION + "): 'useRequestAnimationFrame' option should be true (default) or false.");
24399		}
24400	}
24401
24402	// Test all developer settings and parse to assumption-safe values.
24403	function testOptions ( options ) {
24404
24405		// To prove a fix for #537, freeze options here.
24406		// If the object is modified, an error will be thrown.
24407		// Object.freeze(options);
24408
24409		var parsed = {
24410			margin: 0,
24411			limit: 0,
24412			padding: 0,
24413			animate: true,
24414			animationDuration: 300,
24415			ariaFormat: defaultFormatter,
24416			format: defaultFormatter
24417		};
24418
24419		// Tests are executed in the order they are presented here.
24420		var tests = {
24421			'step': { r: false, t: testStep },
24422			'start': { r: true, t: testStart },
24423			'connect': { r: true, t: testConnect },
24424			'direction': { r: true, t: testDirection },
24425			'snap': { r: false, t: testSnap },
24426			'animate': { r: false, t: testAnimate },
24427			'animationDuration': { r: false, t: testAnimationDuration },
24428			'range': { r: true, t: testRange },
24429			'orientation': { r: false, t: testOrientation },
24430			'margin': { r: false, t: testMargin },
24431			'limit': { r: false, t: testLimit },
24432			'padding': { r: false, t: testPadding },
24433			'behaviour': { r: true, t: testBehaviour },
24434			'multitouch': { r: true, t: testMultitouch },
24435			'ariaFormat': { r: false, t: testAriaFormat },
24436			'format': { r: false, t: testFormat },
24437			'tooltips': { r: false, t: testTooltips },
24438			'cssPrefix': { r: false, t: testCssPrefix },
24439			'cssClasses': { r: false, t: testCssClasses },
24440			'useRequestAnimationFrame': { r: false, t: testUseRaf }
24441		};
24442
24443		var defaults = {
24444			'connect': false,
24445			'direction': 'ltr',
24446			'behaviour': 'tap',
24447			'multitouch': false,
24448			'orientation': 'horizontal',
24449			'cssPrefix' : 'noUi-',
24450			'cssClasses': {
24451				target: 'target',
24452				base: 'base',
24453				origin: 'origin',
24454				handle: 'handle',
24455				handleLower: 'handle-lower',
24456				handleUpper: 'handle-upper',
24457				horizontal: 'horizontal',
24458				vertical: 'vertical',
24459				background: 'background',
24460				connect: 'connect',
24461				ltr: 'ltr',
24462				rtl: 'rtl',
24463				draggable: 'draggable',
24464				drag: 'state-drag',
24465				tap: 'state-tap',
24466				active: 'active',
24467				tooltip: 'tooltip',
24468				pips: 'pips',
24469				pipsHorizontal: 'pips-horizontal',
24470				pipsVertical: 'pips-vertical',
24471				marker: 'marker',
24472				markerHorizontal: 'marker-horizontal',
24473				markerVertical: 'marker-vertical',
24474				markerNormal: 'marker-normal',
24475				markerLarge: 'marker-large',
24476				markerSub: 'marker-sub',
24477				value: 'value',
24478				valueHorizontal: 'value-horizontal',
24479				valueVertical: 'value-vertical',
24480				valueNormal: 'value-normal',
24481				valueLarge: 'value-large',
24482				valueSub: 'value-sub'
24483			},
24484			'useRequestAnimationFrame': true
24485		};
24486
24487		// AriaFormat defaults to regular format, if any.
24488		if ( options.format && !options.ariaFormat ) {
24489			options.ariaFormat = options.format;
24490		}
24491
24492		// Run all options through a testing mechanism to ensure correct
24493		// input. It should be noted that options might get modified to
24494		// be handled properly. E.g. wrapping integers in arrays.
24495		Object.keys(tests).forEach(function( name ){
24496
24497			// If the option isn't set, but it is required, throw an error.
24498			if ( options[name] === undefined && defaults[name] === undefined ) {
24499
24500				if ( tests[name].r ) {
24501					throw new Error("noUiSlider (" + VERSION + "): '" + name + "' is required.");
24502				}
24503
24504				return true;
24505			}
24506
24507			tests[name].t( parsed, options[name] === undefined ? defaults[name] : options[name] );
24508		});
24509
24510		// Forward pips options
24511		parsed.pips = options.pips;
24512
24513		var styles = [['left', 'top'], ['right', 'bottom']];
24514
24515		// Pre-define the styles.
24516		parsed.style = styles[parsed.dir][parsed.ort];
24517		parsed.styleOposite = styles[parsed.dir?0:1][parsed.ort];
24518
24519		return parsed;
24520	}
24521
24522
24523function closure ( target, options, originalOptions ){
24524
24525	var actions = getActions();
24526	var supportsTouchActionNone = getSupportsTouchActionNone();
24527	var supportsPassive = supportsTouchActionNone && getSupportsPassive();
24528
24529	// All variables local to 'closure' are prefixed with 'scope_'
24530	var scope_Target = target;
24531	var scope_Locations = [];
24532	var scope_Base;
24533	var scope_Handles;
24534	var scope_HandleNumbers = [];
24535	var scope_ActiveHandlesCount = 0;
24536	var scope_Connects;
24537	var scope_Spectrum = options.spectrum;
24538	var scope_Values = [];
24539	var scope_Events = {};
24540	var scope_Self;
24541	var scope_Pips;
24542	var scope_Document = target.ownerDocument;
24543	var scope_DocumentElement = scope_Document.documentElement;
24544	var scope_Body = scope_Document.body;
24545
24546
24547	// Creates a node, adds it to target, returns the new node.
24548	function addNodeTo ( target, className ) {
24549
24550		var div = scope_Document.createElement('div');
24551
24552		if ( className ) {
24553			addClass(div, className);
24554		}
24555
24556		target.appendChild(div);
24557
24558		return div;
24559	}
24560
24561	// Append a origin to the base
24562	function addOrigin ( base, handleNumber ) {
24563
24564		var origin = addNodeTo(base, options.cssClasses.origin);
24565		var handle = addNodeTo(origin, options.cssClasses.handle);
24566
24567		handle.setAttribute('data-handle', handleNumber);
24568
24569		// https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
24570		// 0 = focusable and reachable
24571		handle.setAttribute('tabindex', '0');
24572		handle.setAttribute('role', 'slider');
24573		handle.setAttribute('aria-orientation', options.ort ? 'vertical' : 'horizontal');
24574
24575		if ( handleNumber === 0 ) {
24576			addClass(handle, options.cssClasses.handleLower);
24577		}
24578
24579		else if ( handleNumber === options.handles - 1 ) {
24580			addClass(handle, options.cssClasses.handleUpper);
24581		}
24582
24583		return origin;
24584	}
24585
24586	// Insert nodes for connect elements
24587	function addConnect ( base, add ) {
24588
24589		if ( !add ) {
24590			return false;
24591		}
24592
24593		return addNodeTo(base, options.cssClasses.connect);
24594	}
24595
24596	// Add handles to the slider base.
24597	function addElements ( connectOptions, base ) {
24598
24599		scope_Handles = [];
24600		scope_Connects = [];
24601
24602		scope_Connects.push(addConnect(base, connectOptions[0]));
24603
24604		// [::::O====O====O====]
24605		// connectOptions = [0, 1, 1, 1]
24606
24607		for ( var i = 0; i < options.handles; i++ ) {
24608			// Keep a list of all added handles.
24609			scope_Handles.push(addOrigin(base, i));
24610			scope_HandleNumbers[i] = i;
24611			scope_Connects.push(addConnect(base, connectOptions[i + 1]));
24612		}
24613	}
24614
24615	// Initialize a single slider.
24616	function addSlider ( target ) {
24617
24618		// Apply classes and data to the target.
24619		addClass(target, options.cssClasses.target);
24620
24621		if ( options.dir === 0 ) {
24622			addClass(target, options.cssClasses.ltr);
24623		} else {
24624			addClass(target, options.cssClasses.rtl);
24625		}
24626
24627		if ( options.ort === 0 ) {
24628			addClass(target, options.cssClasses.horizontal);
24629		} else {
24630			addClass(target, options.cssClasses.vertical);
24631		}
24632
24633		scope_Base = addNodeTo(target, options.cssClasses.base);
24634	}
24635
24636
24637	function addTooltip ( handle, handleNumber ) {
24638
24639		if ( !options.tooltips[handleNumber] ) {
24640			return false;
24641		}
24642
24643		return addNodeTo(handle.firstChild, options.cssClasses.tooltip);
24644	}
24645
24646	// The tooltips option is a shorthand for using the 'update' event.
24647	function tooltips ( ) {
24648
24649		// Tooltips are added with options.tooltips in original order.
24650		var tips = scope_Handles.map(addTooltip);
24651
24652		bindEvent('update', function(values, handleNumber, unencoded) {
24653
24654			if ( !tips[handleNumber] ) {
24655				return;
24656			}
24657
24658			var formattedValue = values[handleNumber];
24659
24660			if ( options.tooltips[handleNumber] !== true ) {
24661				formattedValue = options.tooltips[handleNumber].to(unencoded[handleNumber]);
24662			}
24663
24664			tips[handleNumber].innerHTML = formattedValue;
24665		});
24666	}
24667
24668
24669	function aria ( ) {
24670
24671		bindEvent('update', function ( values, handleNumber, unencoded, tap, positions ) {
24672
24673			// Update Aria Values for all handles, as a change in one changes min and max values for the next.
24674			scope_HandleNumbers.forEach(function( handleNumber ){
24675
24676				var handle = scope_Handles[handleNumber];
24677
24678				var min = checkHandlePosition(scope_Locations, handleNumber, 0, true, true, true);
24679				var max = checkHandlePosition(scope_Locations, handleNumber, 100, true, true, true);
24680
24681				var now = positions[handleNumber];
24682				var text = options.ariaFormat.to(unencoded[handleNumber]);
24683
24684				handle.children[0].setAttribute('aria-valuemin', min.toFixed(1));
24685				handle.children[0].setAttribute('aria-valuemax', max.toFixed(1));
24686				handle.children[0].setAttribute('aria-valuenow', now.toFixed(1));
24687				handle.children[0].setAttribute('aria-valuetext', text);
24688			});
24689		});
24690	}
24691
24692
24693	function getGroup ( mode, values, stepped ) {
24694
24695		// Use the range.
24696		if ( mode === 'range' || mode === 'steps' ) {
24697			return scope_Spectrum.xVal;
24698		}
24699
24700		if ( mode === 'count' ) {
24701
24702			if ( !values ) {
24703				throw new Error("noUiSlider (" + VERSION + "): 'values' required for mode 'count'.");
24704			}
24705
24706			// Divide 0 - 100 in 'count' parts.
24707			var spread = ( 100 / (values - 1) );
24708			var v;
24709			var i = 0;
24710
24711			values = [];
24712
24713			// List these parts and have them handled as 'positions'.
24714			while ( (v = i++ * spread) <= 100 ) {
24715				values.push(v);
24716			}
24717
24718			mode = 'positions';
24719		}
24720
24721		if ( mode === 'positions' ) {
24722
24723			// Map all percentages to on-range values.
24724			return values.map(function( value ){
24725				return scope_Spectrum.fromStepping( stepped ? scope_Spectrum.getStep( value ) : value );
24726			});
24727		}
24728
24729		if ( mode === 'values' ) {
24730
24731			// If the value must be stepped, it needs to be converted to a percentage first.
24732			if ( stepped ) {
24733
24734				return values.map(function( value ){
24735
24736					// Convert to percentage, apply step, return to value.
24737					return scope_Spectrum.fromStepping( scope_Spectrum.getStep( scope_Spectrum.toStepping( value ) ) );
24738				});
24739
24740			}
24741
24742			// Otherwise, we can simply use the values.
24743			return values;
24744		}
24745	}
24746
24747	function generateSpread ( density, mode, group ) {
24748
24749		function safeIncrement(value, increment) {
24750			// Avoid floating point variance by dropping the smallest decimal places.
24751			return (value + increment).toFixed(7) / 1;
24752		}
24753
24754		var indexes = {};
24755		var firstInRange = scope_Spectrum.xVal[0];
24756		var lastInRange = scope_Spectrum.xVal[scope_Spectrum.xVal.length-1];
24757		var ignoreFirst = false;
24758		var ignoreLast = false;
24759		var prevPct = 0;
24760
24761		// Create a copy of the group, sort it and filter away all duplicates.
24762		group = unique(group.slice().sort(function(a, b){ return a - b; }));
24763
24764		// Make sure the range starts with the first element.
24765		if ( group[0] !== firstInRange ) {
24766			group.unshift(firstInRange);
24767			ignoreFirst = true;
24768		}
24769
24770		// Likewise for the last one.
24771		if ( group[group.length - 1] !== lastInRange ) {
24772			group.push(lastInRange);
24773			ignoreLast = true;
24774		}
24775
24776		group.forEach(function ( current, index ) {
24777
24778			// Get the current step and the lower + upper positions.
24779			var step;
24780			var i;
24781			var q;
24782			var low = current;
24783			var high = group[index+1];
24784			var newPct;
24785			var pctDifference;
24786			var pctPos;
24787			var type;
24788			var steps;
24789			var realSteps;
24790			var stepsize;
24791
24792			// When using 'steps' mode, use the provided steps.
24793			// Otherwise, we'll step on to the next subrange.
24794			if ( mode === 'steps' ) {
24795				step = scope_Spectrum.xNumSteps[ index ];
24796			}
24797
24798			// Default to a 'full' step.
24799			if ( !step ) {
24800				step = high-low;
24801			}
24802
24803			// Low can be 0, so test for false. If high is undefined,
24804			// we are at the last subrange. Index 0 is already handled.
24805			if ( low === false || high === undefined ) {
24806				return;
24807			}
24808
24809			// Make sure step isn't 0, which would cause an infinite loop (#654)
24810			step = Math.max(step, 0.0000001);
24811
24812			// Find all steps in the subrange.
24813			for ( i = low; i <= high; i = safeIncrement(i, step) ) {
24814
24815				// Get the percentage value for the current step,
24816				// calculate the size for the subrange.
24817				newPct = scope_Spectrum.toStepping( i );
24818				pctDifference = newPct - prevPct;
24819
24820				steps = pctDifference / density;
24821				realSteps = Math.round(steps);
24822
24823				// This ratio represents the ammount of percentage-space a point indicates.
24824				// For a density 1 the points/percentage = 1. For density 2, that percentage needs to be re-devided.
24825				// Round the percentage offset to an even number, then divide by two
24826				// to spread the offset on both sides of the range.
24827				stepsize = pctDifference/realSteps;
24828
24829				// Divide all points evenly, adding the correct number to this subrange.
24830				// Run up to <= so that 100% gets a point, event if ignoreLast is set.
24831				for ( q = 1; q <= realSteps; q += 1 ) {
24832
24833					// The ratio between the rounded value and the actual size might be ~1% off.
24834					// Correct the percentage offset by the number of points
24835					// per subrange. density = 1 will result in 100 points on the
24836					// full range, 2 for 50, 4 for 25, etc.
24837					pctPos = prevPct + ( q * stepsize );
24838					indexes[pctPos.toFixed(5)] = ['x', 0];
24839				}
24840
24841				// Determine the point type.
24842				type = (group.indexOf(i) > -1) ? 1 : ( mode === 'steps' ? 2 : 0 );
24843
24844				// Enforce the 'ignoreFirst' option by overwriting the type for 0.
24845				if ( !index && ignoreFirst ) {
24846					type = 0;
24847				}
24848
24849				if ( !(i === high && ignoreLast)) {
24850					// Mark the 'type' of this point. 0 = plain, 1 = real value, 2 = step value.
24851					indexes[newPct.toFixed(5)] = [i, type];
24852				}
24853
24854				// Update the percentage count.
24855				prevPct = newPct;
24856			}
24857		});
24858
24859		return indexes;
24860	}
24861
24862	function addMarking ( spread, filterFunc, formatter ) {
24863
24864		var element = scope_Document.createElement('div');
24865
24866		var valueSizeClasses = [
24867			options.cssClasses.valueNormal,
24868			options.cssClasses.valueLarge,
24869			options.cssClasses.valueSub
24870		];
24871		var markerSizeClasses = [
24872			options.cssClasses.markerNormal,
24873			options.cssClasses.markerLarge,
24874			options.cssClasses.markerSub
24875		];
24876		var valueOrientationClasses = [
24877			options.cssClasses.valueHorizontal,
24878			options.cssClasses.valueVertical
24879		];
24880		var markerOrientationClasses = [
24881			options.cssClasses.markerHorizontal,
24882			options.cssClasses.markerVertical
24883		];
24884
24885		addClass(element, options.cssClasses.pips);
24886		addClass(element, options.ort === 0 ? options.cssClasses.pipsHorizontal : options.cssClasses.pipsVertical);
24887
24888		function getClasses( type, source ){
24889			var a = source === options.cssClasses.value;
24890			var orientationClasses = a ? valueOrientationClasses : markerOrientationClasses;
24891			var sizeClasses = a ? valueSizeClasses : markerSizeClasses;
24892
24893			return source + ' ' + orientationClasses[options.ort] + ' ' + sizeClasses[type];
24894		}
24895
24896		function addSpread ( offset, values ){
24897
24898			// Apply the filter function, if it is set.
24899			values[1] = (values[1] && filterFunc) ? filterFunc(values[0], values[1]) : values[1];
24900
24901			// Add a marker for every point
24902			var node = addNodeTo(element, false);
24903				node.className = getClasses(values[1], options.cssClasses.marker);
24904				node.style[options.style] = offset + '%';
24905
24906			// Values are only appended for points marked '1' or '2'.
24907			if ( values[1] ) {
24908				node = addNodeTo(element, false);
24909				node.className = getClasses(values[1], options.cssClasses.value);
24910				node.style[options.style] = offset + '%';
24911				node.innerText = formatter.to(values[0]);
24912			}
24913		}
24914
24915		// Append all points.
24916		Object.keys(spread).forEach(function(a){
24917			addSpread(a, spread[a]);
24918		});
24919
24920		return element;
24921	}
24922
24923	function removePips ( ) {
24924		if ( scope_Pips ) {
24925			removeElement(scope_Pips);
24926			scope_Pips = null;
24927		}
24928	}
24929
24930	function pips ( grid ) {
24931
24932		// Fix #669
24933		removePips();
24934
24935		var mode = grid.mode;
24936		var density = grid.density || 1;
24937		var filter = grid.filter || false;
24938		var values = grid.values || false;
24939		var stepped = grid.stepped || false;
24940		var group = getGroup( mode, values, stepped );
24941		var spread = generateSpread( density, mode, group );
24942		var format = grid.format || {
24943			to: Math.round
24944		};
24945
24946		scope_Pips = scope_Target.appendChild(addMarking(
24947			spread,
24948			filter,
24949			format
24950		));
24951
24952		return scope_Pips;
24953	}
24954
24955
24956	// Shorthand for base dimensions.
24957	function baseSize ( ) {
24958		var rect = scope_Base.getBoundingClientRect(), alt = 'offset' + ['Width', 'Height'][options.ort];
24959		return options.ort === 0 ? (rect.width||scope_Base[alt]) : (rect.height||scope_Base[alt]);
24960	}
24961
24962	// Handler for attaching events trough a proxy.
24963	function attachEvent ( events, element, callback, data ) {
24964
24965		// This function can be used to 'filter' events to the slider.
24966		// element is a node, not a nodeList
24967
24968		var method = function ( e ){
24969
24970			if ( scope_Target.hasAttribute('disabled') ) {
24971				return false;
24972			}
24973
24974			// Stop if an active 'tap' transition is taking place.
24975			if ( hasClass(scope_Target, options.cssClasses.tap) ) {
24976				return false;
24977			}
24978
24979			e = fixEvent(e, data.pageOffset, data.target || element);
24980
24981			// Handle reject of multitouch
24982			if ( !e ) {
24983				return false;
24984			}
24985
24986			// Ignore right or middle clicks on start #454
24987			if ( events === actions.start && e.buttons !== undefined && e.buttons > 1 ) {
24988				return false;
24989			}
24990
24991			// Ignore right or middle clicks on start #454
24992			if ( data.hover && e.buttons ) {
24993				return false;
24994			}
24995
24996			// 'supportsPassive' is only true if a browser also supports touch-action: none in CSS.
24997			// iOS safari does not, so it doesn't get to benefit from passive scrolling. iOS does support
24998			// touch-action: manipulation, but that allows panning, which breaks
24999			// sliders after zooming/on non-responsive pages.
25000			// See: https://bugs.webkit.org/show_bug.cgi?id=133112
25001			if ( !supportsPassive ) {
25002				e.preventDefault();
25003			}
25004
25005			e.calcPoint = e.points[ options.ort ];
25006
25007			// Call the event handler with the event [ and additional data ].
25008			callback ( e, data );
25009		};
25010
25011		var methods = [];
25012
25013		// Bind a closure on the target for every event type.
25014		events.split(' ').forEach(function( eventName ){
25015			element.addEventListener(eventName, method, supportsPassive ? { passive: true } : false);
25016			methods.push([eventName, method]);
25017		});
25018
25019		return methods;
25020	}
25021
25022	// Provide a clean event with standardized offset values.
25023	function fixEvent ( e, pageOffset, target ) {
25024
25025		// Filter the event to register the type, which can be
25026		// touch, mouse or pointer. Offset changes need to be
25027		// made on an event specific basis.
25028		var touch = e.type.indexOf('touch') === 0;
25029		var mouse = e.type.indexOf('mouse') === 0;
25030		var pointer = e.type.indexOf('pointer') === 0;
25031
25032		var x;
25033		var y;
25034
25035		// IE10 implemented pointer events with a prefix;
25036		if ( e.type.indexOf('MSPointer') === 0 ) {
25037			pointer = true;
25038		}
25039
25040
25041		// In the event that multitouch is activated, the only thing one handle should be concerned
25042		// about is the touches that originated on top of it.
25043		if ( touch && options.multitouch ) {
25044			// Returns true if a touch originated on the target.
25045			var isTouchOnTarget = function (touch) {
25046				return touch.target === target || target.contains(touch.target);
25047			};
25048			// In the case of touchstart events, we need to make sure there is still no more than one
25049			// touch on the target so we look amongst all touches.
25050			if (e.type === 'touchstart') {
25051				var targetTouches = Array.prototype.filter.call(e.touches, isTouchOnTarget);
vendor: 9,785 bytes, lines 25052-25376
25052				// Do not support more than one touch per handle.
25053				if ( targetTouches.length > 1 ) {
25054					return false;
25055				}
25056				x = targetTouches[0].pageX;
25057				y = targetTouches[0].pageY;
25058			} else {
25059			// In the other cases, find on changedTouches is enough.
25060				var targetTouch = Array.prototype.find.call(e.changedTouches, isTouchOnTarget);
25061				// Cancel if the target touch has not moved.
25062				if ( !targetTouch ) {
25063					return false;
25064				}
25065				x = targetTouch.pageX;
25066				y = targetTouch.pageY;
25067			}
25068		} else if ( touch ) {
25069			// Fix bug when user touches with two or more fingers on mobile devices.
25070			// It's useful when you have two or more sliders on one page,
25071			// that can be touched simultaneously.
25072			// #649, #663, #668
25073			if ( e.touches.length > 1 ) {
25074				return false;
25075			}
25076
25077			// noUiSlider supports one movement at a time,
25078			// so we can select the first 'changedTouch'.
25079			x = e.changedTouches[0].pageX;
25080			y = e.changedTouches[0].pageY;
25081		}
25082
25083		pageOffset = pageOffset || getPageOffset(scope_Document);
25084
25085		if ( mouse || pointer ) {
25086			x = e.clientX + pageOffset.x;
25087			y = e.clientY + pageOffset.y;
25088		}
25089
25090		e.pageOffset = pageOffset;
25091		e.points = [x, y];
25092		e.cursor = mouse || pointer; // Fix #435
25093
25094		return e;
25095	}
25096
25097	// Translate a coordinate in the document to a percentage on the slider
25098	function calcPointToPercentage ( calcPoint ) {
25099		var location = calcPoint - offset(scope_Base, options.ort);
25100		var proposal = ( location * 100 ) / baseSize();
25101		return options.dir ? 100 - proposal : proposal;
25102	}
25103
25104	// Find handle closest to a certain percentage on the slider
25105	function getClosestHandle ( proposal ) {
25106
25107		var closest = 100;
25108		var handleNumber = false;
25109
25110		scope_Handles.forEach(function(handle, index){
25111
25112			// Disabled handles are ignored
25113			if ( handle.hasAttribute('disabled') ) {
25114				return;
25115			}
25116
25117			var pos = Math.abs(scope_Locations[index] - proposal);
25118
25119			if ( pos < closest ) {
25120				handleNumber = index;
25121				closest = pos;
25122			}
25123		});
25124
25125		return handleNumber;
25126	}
25127
25128	// Moves handle(s) by a percentage
25129	// (bool, % to move, [% where handle started, ...], [index in scope_Handles, ...])
25130	function moveHandles ( upward, proposal, locations, handleNumbers ) {
25131
25132		var proposals = locations.slice();
25133
25134		var b = [!upward, upward];
25135		var f = [upward, !upward];
25136
25137		// Copy handleNumbers so we don't change the dataset
25138		handleNumbers = handleNumbers.slice();
25139
25140		// Check to see which handle is 'leading'.
25141		// If that one can't move the second can't either.
25142		if ( upward ) {
25143			handleNumbers.reverse();
25144		}
25145
25146		// Step 1: get the maximum percentage that any of the handles can move
25147		if ( handleNumbers.length > 1 ) {
25148
25149			handleNumbers.forEach(function(handleNumber, o) {
25150
25151				var to = checkHandlePosition(proposals, handleNumber, proposals[handleNumber] + proposal, b[o], f[o], false);
25152
25153				// Stop if one of the handles can't move.
25154				if ( to === false ) {
25155					proposal = 0;
25156				} else {
25157					proposal = to - proposals[handleNumber];
25158					proposals[handleNumber] = to;
25159				}
25160			});
25161		}
25162
25163		// If using one handle, check backward AND forward
25164		else {
25165			b = f = [true];
25166		}
25167
25168		var state = false;
25169
25170		// Step 2: Try to set the handles with the found percentage
25171		handleNumbers.forEach(function(handleNumber, o) {
25172			state = setHandle(handleNumber, locations[handleNumber] + proposal, b[o], f[o]) || state;
25173		});
25174
25175		// Step 3: If a handle moved, fire events
25176		if ( state ) {
25177			handleNumbers.forEach(function(handleNumber){
25178				fireEvent('update', handleNumber);
25179				fireEvent('slide', handleNumber);
25180			});
25181		}
25182	}
25183
25184	// External event handling
25185	function fireEvent ( eventName, handleNumber, tap ) {
25186
25187		Object.keys(scope_Events).forEach(function( targetEvent ) {
25188
25189			var eventType = targetEvent.split('.')[0];
25190
25191			if ( eventName === eventType ) {
25192				scope_Events[targetEvent].forEach(function( callback ) {
25193
25194					callback.call(
25195						// Use the slider public API as the scope ('this')
25196						scope_Self,
25197						// Return values as array, so arg_1[arg_2] is always valid.
25198						scope_Values.map(options.format.to),
25199						// Handle index, 0 or 1
25200						handleNumber,
25201						// Unformatted slider values
25202						scope_Values.slice(),
25203						// Event is fired by tap, true or false
25204						tap || false,
25205						// Left offset of the handle, in relation to the slider
25206						scope_Locations.slice()
25207					);
25208				});
25209			}
25210		});
25211	}
25212
25213
25214	// Fire 'end' when a mouse or pen leaves the document.
25215	function documentLeave ( event, data ) {
25216		if ( event.type === "mouseout" && event.target.nodeName === "HTML" && event.relatedTarget === null ){
25217			eventEnd (event, data);
25218		}
25219	}
25220
25221	// Handle movement on document for handle and range drag.
25222	function eventMove ( event, data ) {
25223
25224		// Fix #498
25225		// Check value of .buttons in 'start' to work around a bug in IE10 mobile (data.buttonsProperty).
25226		// https://connect.microsoft.com/IE/feedback/details/927005/mobile-ie10-windows-phone-buttons-property-of-pointermove-event-always-zero
25227		// IE9 has .buttons and .which zero on mousemove.
25228		// Firefox breaks the spec MDN defines.
25229		if ( navigator.appVersion.indexOf("MSIE 9") === -1 && event.buttons === 0 && data.buttonsProperty !== 0 ) {
25230			return eventEnd(event, data);
25231		}
25232
25233		// Check if we are moving up or down
25234		var movement = (options.dir ? -1 : 1) * (event.calcPoint - data.startCalcPoint);
25235
25236		// Convert the movement into a percentage of the slider width/height
25237		var proposal = (movement * 100) / data.baseSize;
25238
25239		moveHandles(movement > 0, proposal, data.locations, data.handleNumbers);
25240	}
25241
25242	// Unbind move events on document, call callbacks.
25243	function eventEnd ( event, data ) {
25244
25245		// The handle is no longer active, so remove the class.
25246		if ( data.handle ) {
25247			removeClass(data.handle, options.cssClasses.active);
25248			scope_ActiveHandlesCount -= 1;
25249		}
25250
25251		// Unbind the move and end events, which are added on 'start'.
25252		data.listeners.forEach(function( c ) {
25253			scope_DocumentElement.removeEventListener(c[0], c[1]);
25254		});
25255
25256		if ( scope_ActiveHandlesCount === 0 ) {
25257			// Remove dragging class.
25258			removeClass(scope_Target, options.cssClasses.drag);
25259			setZindex();
25260
25261			// Remove cursor styles and text-selection events bound to the body.
25262			if ( event.cursor ) {
25263				scope_Body.style.cursor = '';
25264				scope_Body.removeEventListener('selectstart', preventDefault);
25265			}
25266		}
25267
25268		data.handleNumbers.forEach(function(handleNumber){
25269			fireEvent('change', handleNumber);
25270			fireEvent('set', handleNumber);
25271			fireEvent('end', handleNumber);
25272		});
25273	}
25274
25275	// Bind move events on document.
25276	function eventStart ( event, data ) {
25277
25278		var handle;
25279		if ( data.handleNumbers.length === 1 ) {
25280
25281			var handleOrigin = scope_Handles[data.handleNumbers[0]];
25282
25283			// Ignore 'disabled' handles
25284			if ( handleOrigin.hasAttribute('disabled') ) {
25285				return false;
25286			}
25287
25288			handle = handleOrigin.children[0];
25289			scope_ActiveHandlesCount += 1;
25290
25291			// Mark the handle as 'active' so it can be styled.
25292			addClass(handle, options.cssClasses.active);
25293		}
25294
25295		// A drag should never propagate up to the 'tap' event.
25296		event.stopPropagation();
25297
25298		// Record the event listeners.
25299		var listeners = [];
25300
25301		// Attach the move and end events.
25302		var moveEvent = attachEvent(actions.move, scope_DocumentElement, eventMove, {
25303			// The event target has changed so we need to propagate the original one so that we keep
25304			// relying on it to extract target touches.
25305			target: event.target,
25306			handle: handle,
25307			listeners: listeners,
25308			startCalcPoint: event.calcPoint,
25309			baseSize: baseSize(),
25310			pageOffset: event.pageOffset,
25311			handleNumbers: data.handleNumbers,
25312			buttonsProperty: event.buttons,
25313			locations: scope_Locations.slice()
25314		});
25315
25316		var endEvent = attachEvent(actions.end, scope_DocumentElement, eventEnd, {
25317			target: event.target,
25318			handle: handle,
25319			listeners: listeners,
25320			handleNumbers: data.handleNumbers
25321		});
25322
25323		var outEvent = attachEvent("mouseout", scope_DocumentElement, documentLeave, {
25324			target: event.target,
25325			handle: handle,
25326			listeners: listeners,
25327			handleNumbers: data.handleNumbers
25328		});
25329
25330		// We want to make sure we pushed the listeners in the listener list rather than creating
25331		// a new one as it has already been passed to the event handlers.
25332		listeners.push.apply(listeners, moveEvent.concat(endEvent, outEvent));
25333
25334		// Text selection isn't an issue on touch devices,
25335		// so adding cursor styles can be skipped.
25336		if ( event.cursor ) {
25337
25338			// Prevent the 'I' cursor and extend the range-drag cursor.
25339			scope_Body.style.cursor = getComputedStyle(event.target).cursor;
25340
25341			// Mark the target with a dragging state.
25342			if ( scope_Handles.length > 1 ) {
25343				addClass(scope_Target, options.cssClasses.drag);
25344			}
25345
25346			// Prevent text selection when dragging the handles.
25347			// In noUiSlider <= 9.2.0, this was handled by calling preventDefault on mouse/touch start/move,
25348			// which is scroll blocking. The selectstart event is supported by FireFox starting from version 52,
25349			// meaning the only holdout is iOS Safari. This doesn't matter: text selection isn't triggered there.
25350			// The 'cursor' flag is false.
25351			// See: http://caniuse.com/#search=selectstart
25352			scope_Body.addEventListener('selectstart', preventDefault, false);
25353		}
25354
25355		data.handleNumbers.forEach(function(handleNumber){
25356			fireEvent('start', handleNumber);
25357		});
25358	}
25359
25360	// Move closest handle to tapped location.
25361	function eventTap ( event ) {
25362
25363		// The tap event shouldn't propagate up
25364		event.stopPropagation();
25365
25366		var proposal = calcPointToPercentage(event.calcPoint);
25367		var handleNumber = getClosestHandle(proposal);
25368
25369		// Tackle the case that all handles are 'disabled'.
25370		if ( handleNumber === false ) {
25371			return false;
25372		}
25373
25374		// Flag the slider as it is now in a transitional state.
25375		// Transition takes a configurable amount of ms (default 300). Re-enable the slider after that.
25376		if ( !options.events.snap ) {
25377			addClassFor(scope_Target, options.cssClasses.tap, options.animationDuration);
25378		}
25379
25380		setHandle(handleNumber, proposal, true, true);
25381
25382		setZindex();
25383
25384		fireEvent('slide', handleNumber, true);
25385		fireEvent('update', handleNumber, true);
25386		fireEvent('change', handleNumber, true);
25387		fireEvent('set', handleNumber, true);
25388
25389		if ( options.events.snap ) {
25390			eventStart(event, { handleNumbers: [handleNumber] });
25391		}
25392	}
25393
25394	// Fires a 'hover' event for a hovered mouse/pen position.
25395	function eventHover ( event ) {
25396
25397		var proposal = calcPointToPercentage(event.calcPoint);
25398
25399		var to = scope_Spectrum.getStep(proposal);
25400		var value = scope_Spectrum.fromStepping(to);
25401
25402		Object.keys(scope_Events).forEach(function( targetEvent ) {
25403			if ( 'hover' === targetEvent.split('.')[0] ) {
25404				scope_Events[targetEvent].forEach(function( callback ) {
25405					callback.call( scope_Self, value );
25406				});
25407			}
25408		});
25409	}
25410
25411	// Attach events to several slider parts.
25412	function bindSliderEvents ( behaviour ) {
25413
25414		// Attach the standard drag event to the handles.
25415		if ( !behaviour.fixed ) {
25416
25417			scope_Handles.forEach(function( handle, index ){
25418
25419				// These events are only bound to the visual handle
25420				// element, not the 'real' origin element.
25421				attachEvent ( actions.start, handle.children[0], eventStart, {
25422					handleNumbers: [index]
25423				});
25424			});
25425		}
25426
25427		// Attach the tap event to the slider base.
25428		if ( behaviour.tap ) {
25429			attachEvent (actions.start, scope_Base, eventTap, {});
25430		}
25431
25432		// Fire hover events
25433		if ( behaviour.hover ) {
25434			attachEvent (actions.move, scope_Base, eventHover, { hover: true });
25435		}
25436
25437		// Make the range draggable.
25438		if ( behaviour.drag ){
25439
25440			scope_Connects.forEach(function( connect, index ){
25441
25442				if ( connect === false || index === 0 || index === scope_Connects.length - 1 ) {
25443					return;
25444				}
25445
25446				var handleBefore = scope_Handles[index - 1];
25447				var handleAfter = scope_Handles[index];
25448				var eventHolders = [connect];
25449
25450				addClass(connect, options.cssClasses.draggable);
25451
25452				// When the range is fixed, the entire range can
25453				// be dragged by the handles. The handle in the first
25454				// origin will propagate the start event upward,
25455				// but it needs to be bound manually on the other.
25456				if ( behaviour.fixed ) {
25457					eventHolders.push(handleBefore.children[0]);
25458					eventHolders.push(handleAfter.children[0]);
25459				}
25460
25461				eventHolders.forEach(function( eventHolder ) {
25462					attachEvent ( actions.start, eventHolder, eventStart, {
25463						handles: [handleBefore, handleAfter],
25464						handleNumbers: [index - 1, index]
25465					});
25466				});
25467			});
25468		}
25469	}
25470
25471
25472	// Split out the handle positioning logic so the Move event can use it, too
25473	function checkHandlePosition ( reference, handleNumber, to, lookBackward, lookForward, getValue ) {
25474
25475		// For sliders with multiple handles, limit movement to the other handle.
25476		// Apply the margin option by adding it to the handle positions.
25477		if ( scope_Handles.length > 1 ) {
25478
25479			if ( lookBackward && handleNumber > 0 ) {
25480				to = Math.max(to, reference[handleNumber - 1] + options.margin);
25481			}
25482
25483			if ( lookForward && handleNumber < scope_Handles.length - 1 ) {
25484				to = Math.min(to, reference[handleNumber + 1] - options.margin);
25485			}
25486		}
25487
25488		// The limit option has the opposite effect, limiting handles to a
25489		// maximum distance from another. Limit must be > 0, as otherwise
25490		// handles would be unmoveable.
25491		if ( scope_Handles.length > 1 && options.limit ) {
25492
25493			if ( lookBackward && handleNumber > 0 ) {
25494				to = Math.min(to, reference[handleNumber - 1] + options.limit);
25495			}
25496
25497			if ( lookForward && handleNumber < scope_Handles.length - 1 ) {
25498				to = Math.max(to, reference[handleNumber + 1] - options.limit);
25499			}
25500		}
25501
25502		// The padding option keeps the handles a certain distance from the
25503		// edges of the slider. Padding must be > 0.
25504		if ( options.padding ) {
25505
25506			if ( handleNumber === 0 ) {
25507				to = Math.max(to, options.padding);
25508			}
25509
25510			if ( handleNumber === scope_Handles.length - 1 ) {
25511				to = Math.min(to, 100 - options.padding);
25512			}
25513		}
25514
25515		to = scope_Spectrum.getStep(to);
25516
25517		// Limit percentage to the 0 - 100 range
25518		to = limit(to);
25519
25520		// Return false if handle can't move
25521		if ( to === reference[handleNumber] && !getValue ) {
25522			return false;
25523		}
25524
25525		return to;
25526	}
25527
25528	function toPct ( pct ) {
25529		return pct + '%';
25530	}
25531
25532	// Updates scope_Locations and scope_Values, updates visual state
25533	function updateHandlePosition ( handleNumber, to ) {
25534
25535		// Update locations.
25536		scope_Locations[handleNumber] = to;
25537
25538		// Convert the value to the slider stepping/range.
25539		scope_Values[handleNumber] = scope_Spectrum.fromStepping(to);
25540
25541		// Called synchronously or on the next animationFrame
25542		var stateUpdate = function() {
25543			scope_Handles[handleNumber].style[options.style] = toPct(to);
25544			updateConnect(handleNumber);
25545			updateConnect(handleNumber + 1);
25546		};
25547
25548		// Set the handle to the new position.
25549		// Use requestAnimationFrame for efficient painting.
25550		// No significant effect in Chrome, Edge sees dramatic performace improvements.
25551		// Option to disable is useful for unit tests, and single-step debugging.
25552		if ( window.requestAnimationFrame && options.useRequestAnimationFrame ) {
25553			window.requestAnimationFrame(stateUpdate);
25554		} else {
25555			stateUpdate();
25556		}
25557	}
25558
25559	function setZindex ( ) {
25560
25561		scope_HandleNumbers.forEach(function(handleNumber){
25562			// Handles before the slider middle are stacked later = higher,
25563			// Handles after the middle later is lower
25564			// [[7] [8] .......... | .......... [5] [4]
25565			var dir = (scope_Locations[handleNumber] > 50 ? -1 : 1);
25566			var zIndex = 3 + (scope_Handles.length + (dir * handleNumber));
25567			scope_Handles[handleNumber].childNodes[0].style.zIndex = zIndex;
25568		});
25569	}
25570
25571	// Test suggested values and apply margin, step.
25572	function setHandle ( handleNumber, to, lookBackward, lookForward ) {
25573
25574		to = checkHandlePosition(scope_Locations, handleNumber, to, lookBackward, lookForward, false);
25575
25576		if ( to === false ) {
25577			return false;
25578		}
25579
25580		updateHandlePosition(handleNumber, to);
25581
25582		return true;
25583	}
25584
25585	// Updates style attribute for connect nodes
25586	function updateConnect ( index ) {
25587
25588		// Skip connects set to false
25589		if ( !scope_Connects[index] ) {
25590			return;
25591		}
25592
25593		var l = 0;
25594		var h = 100;
25595
25596		if ( index !== 0 ) {
25597			l = scope_Locations[index - 1];
25598		}
25599
25600		if ( index !== scope_Connects.length - 1 ) {
25601			h = scope_Locations[index];
25602		}
25603
25604		scope_Connects[index].style[options.style] = toPct(l);
25605		scope_Connects[index].style[options.styleOposite] = toPct(100 - h);
25606	}
25607
25608	// ...
25609	function setValue ( to, handleNumber ) {
25610
25611		// Setting with null indicates an 'ignore'.
25612		// Inputting 'false' is invalid.
25613		if ( to === null || to === false ) {
25614			return;
25615		}
25616
25617		// If a formatted number was passed, attemt to decode it.
25618		if ( typeof to === 'number' ) {
25619			to = String(to);
25620		}
25621
25622		to = options.format.from(to);
25623
25624		// Request an update for all links if the value was invalid.
25625		// Do so too if setting the handle fails.
25626		if ( to !== false && !isNaN(to) ) {
25627			setHandle(handleNumber, scope_Spectrum.toStepping(to), false, false);
25628		}
25629	}
25630
25631	// Set the slider value.
25632	function valueSet ( input, fireSetEvent ) {
25633
25634		var values = asArray(input);
25635		var isInit = scope_Locations[0] === undefined;
25636
25637		// Event fires by default
25638		fireSetEvent = (fireSetEvent === undefined ? true : !!fireSetEvent);
25639
25640		values.forEach(setValue);
25641
25642		// Animation is optional.
25643		// Make sure the initial values were set before using animated placement.
25644		if ( options.animate && !isInit ) {
25645			addClassFor(scope_Target, options.cssClasses.tap, options.animationDuration);
25646		}
25647
25648		// Now that all base values are set, apply constraints
25649		scope_HandleNumbers.forEach(function(handleNumber){
25650			setHandle(handleNumber, scope_Locations[handleNumber], true, false);
25651		});
25652
25653		setZindex();
25654
25655		scope_HandleNumbers.forEach(function(handleNumber){
25656
25657			fireEvent('update', handleNumber);
25658
25659			// Fire the event only for handles that received a new value, as per #579
25660			if ( values[handleNumber] !== null && fireSetEvent ) {
25661				fireEvent('set', handleNumber);
25662			}
25663		});
25664	}
25665
25666	// Reset slider to initial values
25667	function valueReset ( fireSetEvent ) {
25668		valueSet(options.start, fireSetEvent);
25669	}
25670
25671	// Get the slider value.
25672	function valueGet ( ) {
25673
25674		var values = scope_Values.map(options.format.to);
25675
25676		// If only one handle is used, return a single value.
25677		if ( values.length === 1 ){
25678			return values[0];
25679		}
25680
25681		return values;
25682	}
25683
25684	// Removes classes from the root and empties it.
25685	function destroy ( ) {
25686
25687		for ( var key in options.cssClasses ) {
25688			if ( !options.cssClasses.hasOwnProperty(key) ) { continue; }
25689			removeClass(scope_Target, options.cssClasses[key]);
25690		}
25691
25692		while (scope_Target.firstChild) {
25693			scope_Target.removeChild(scope_Target.firstChild);
25694		}
25695
25696		delete scope_Target.noUiSlider;
25697	}
25698
25699	// Get the current step size for the slider.
25700	function getCurrentStep ( ) {
25701
25702		// Check all locations, map them to their stepping point.
25703		// Get the step point, then find it in the input list.
25704		return scope_Locations.map(function( location, index ){
25705
25706			var nearbySteps = scope_Spectrum.getNearbySteps( location );
25707			var value = scope_Values[index];
25708			var increment = nearbySteps.thisStep.step;
25709			var decrement = null;
25710
25711			// If the next value in this step moves into the next step,
25712			// the increment is the start of the next step - the current value
25713			if ( increment !== false ) {
25714				if ( value + increment > nearbySteps.stepAfter.startValue ) {
25715					increment = nearbySteps.stepAfter.startValue - value;
25716				}
25717			}
25718
25719
25720			// If the value is beyond the starting point
25721			if ( value > nearbySteps.thisStep.startValue ) {
25722				decrement = nearbySteps.thisStep.step;
25723			}
25724
25725			else if ( nearbySteps.stepBefore.step === false ) {
25726				decrement = false;
25727			}
25728
25729			// If a handle is at the start of a step, it always steps back into the previous step first
25730			else {
25731				decrement = value - nearbySteps.stepBefore.highestStep;
25732			}
25733
25734
25735			// Now, if at the slider edges, there is not in/decrement
25736			if ( location === 100 ) {
25737				increment = null;
25738			}
25739
25740			else if ( location === 0 ) {
25741				decrement = null;
25742			}
25743
25744			// As per #391, the comparison for the decrement step can have some rounding issues.
25745			var stepDecimals = scope_Spectrum.countStepDecimals();
25746
25747			// Round per #391
25748			if ( increment !== null && increment !== false ) {
25749				increment = Number(increment.toFixed(stepDecimals));
25750			}
25751
25752			if ( decrement !== null && decrement !== false ) {
25753				decrement = Number(decrement.toFixed(stepDecimals));
25754			}
25755
25756			return [decrement, increment];
25757		});
25758	}
25759
25760	// Attach an event to this slider, possibly including a namespace
25761	function bindEvent ( namespacedEvent, callback ) {
25762		scope_Events[namespacedEvent] = scope_Events[namespacedEvent] || [];
25763		scope_Events[namespacedEvent].push(callback);
25764
25765		// If the event bound is 'update,' fire it immediately for all handles.
25766		if ( namespacedEvent.split('.')[0] === 'update' ) {
25767			scope_Handles.forEach(function(a, index){
25768				fireEvent('update', index);
25769			});
25770		}
25771	}
25772
25773	// Undo attachment of event
25774	function removeEvent ( namespacedEvent ) {
25775
25776		var event = namespacedEvent && namespacedEvent.split('.')[0];
25777		var namespace = event && namespacedEvent.substring(event.length);
25778
25779		Object.keys(scope_Events).forEach(function( bind ){
25780
25781			var tEvent = bind.split('.')[0],
25782				tNamespace = bind.substring(tEvent.length);
25783
25784			if ( (!event || event === tEvent) && (!namespace || namespace === tNamespace) ) {
25785				delete scope_Events[bind];
25786			}
25787		});
25788	}
25789
25790	// Updateable: margin, limit, padding, step, range, animate, snap
25791	function updateOptions ( optionsToUpdate, fireSetEvent ) {
25792
25793		// Spectrum is created using the range, snap, direction and step options.
25794		// 'snap' and 'step' can be updated.
25795		// If 'snap' and 'step' are not passed, they should remain unchanged.
25796		var v = valueGet();
25797
25798		var updateAble = ['margin', 'limit', 'padding', 'range', 'animate', 'snap', 'step', 'format'];
25799
25800		// Only change options that we're actually passed to update.
25801		updateAble.forEach(function(name){
25802			if ( optionsToUpdate[name] !== undefined ) {
25803				originalOptions[name] = optionsToUpdate[name];
25804			}
25805		});
25806
25807		var newOptions = testOptions(originalOptions);
25808
25809		// Load new options into the slider state
25810		updateAble.forEach(function(name){
25811			if ( optionsToUpdate[name] !== undefined ) {
25812				options[name] = newOptions[name];
25813			}
25814		});
25815
25816		scope_Spectrum = newOptions.spectrum;
25817
25818		// Limit, margin and padding depend on the spectrum but are stored outside of it. (#677)
25819		options.margin = newOptions.margin;
25820		options.limit = newOptions.limit;
25821		options.padding = newOptions.padding;
25822
25823		// Update pips, removes existing.
25824		if ( options.pips ) {
25825			pips(options.pips);
25826		}
25827
25828		// Invalidate the current positioning so valueSet forces an update.
25829		scope_Locations = [];
25830		valueSet(optionsToUpdate.start || v, fireSetEvent);
25831	}
25832
25833	// Throw an error if the slider was already initialized.
25834	if ( scope_Target.noUiSlider ) {
25835		throw new Error("noUiSlider (" + VERSION + "): Slider was already initialized.");
25836	}
25837
25838	// Create the base element, initialise HTML and set classes.
25839	// Add handles and connect elements.
25840	addSlider(scope_Target);
25841	addElements(options.connect, scope_Base);
25842
25843	scope_Self = {
25844		destroy: destroy,
25845		steps: getCurrentStep,
25846		on: bindEvent,
25847		off: removeEvent,
25848		get: valueGet,
25849		set: valueSet,
25850		reset: valueReset,
25851		// Exposed for unit testing, don't use this in your application.
25852		__moveHandles: function(a, b, c) { moveHandles(a, b, scope_Locations, c); },
25853		options: originalOptions, // Issue #600, #678
25854		updateOptions: updateOptions,
25855		target: scope_Target, // Issue #597
25856		removePips: removePips,
25857		pips: pips // Issue #594
25858	};
25859
25860	// Attach user events.
25861	bindSliderEvents(options.events);
25862
25863	// Use the public value method to set the start values.
25864	valueSet(options.start);
25865
25866	if ( options.pips ) {
25867		pips(options.pips);
25868	}
25869
25870	if ( options.tooltips ) {
25871		tooltips();
25872	}
25873
25874	aria();
25875
25876	return scope_Self;
25877
25878}
25879
25880
25881	// Run the standard initializer
25882	function initialize ( target, originalOptions ) {
25883
25884		if ( !target || !target.nodeName ) {
25885			throw new Error("noUiSlider (" + VERSION + "): create requires a single element, got: " + target);
25886		}
25887
25888		// Test the options and create the slider environment;
25889		var options = testOptions( originalOptions, target );
25890		var api = closure( target, options, originalOptions );
25891
25892		target.noUiSlider = api;
25893
25894		return api;
25895	}
25896
25897	// Use an object instead of a function for future expansibility;
25898	return {
25899		version: VERSION,
25900		create: initialize
25901	};
25902
25903}));
vendor: 23,216 bytes, lines 25904-26850
25904/**
25905 * Owl Carousel v2.3.4
25906 * Copyright 2013-2018 David Deutsch
25907 * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
25908 */
25909/**
25910 * Owl carousel
25911 * @version 2.3.4
25912 * @author Bartosz Wojciechowski
25913 * @author David Deutsch
25914 * @license The MIT License (MIT)
25915 * @todo Lazy Load Icon
25916 * @todo prevent animationend bubling
25917 * @todo itemsScaleUp
25918 * @todo Test Zepto
25919 * @todo stagePadding calculate wrong active classes
25920 */
25921;(function($, window, document, undefined) {
25922
25923	/**
25924	 * Creates a carousel.
25925	 * @class The Owl Carousel.
25926	 * @public
25927	 * @param {HTMLElement|jQuery} element - The element to create the carousel for.
25928	 * @param {Object} [options] - The options
25929	 */
25930	function Owl(element, options) {
25931
25932		/**
25933		 * Current settings for the carousel.
25934		 * @public
25935		 */
25936		this.settings = null;
25937
25938		/**
25939		 * Current options set by the caller including defaults.
25940		 * @public
25941		 */
25942		this.options = $.extend({}, Owl.Defaults, options);
25943
25944		/**
25945		 * Plugin element.
25946		 * @public
25947		 */
25948		this.$element = $(element);
25949
25950		/**
25951		 * Proxied event handlers.
25952		 * @protected
25953		 */
25954		this._handlers = {};
25955
25956		/**
25957		 * References to the running plugins of this carousel.
25958		 * @protected
25959		 */
25960		this._plugins = {};
25961
25962		/**
25963		 * Currently suppressed events to prevent them from being retriggered.
25964		 * @protected
25965		 */
25966		this._supress = {};
25967
25968		/**
25969		 * Absolute current position.
25970		 * @protected
25971		 */
25972		this._current = null;
25973
25974		/**
25975		 * Animation speed in milliseconds.
25976		 * @protected
25977		 */
25978		this._speed = null;
25979
25980		/**
25981		 * Coordinates of all items in pixel.
25982		 * @todo The name of this member is missleading.
25983		 * @protected
25984		 */
25985		this._coordinates = [];
25986
25987		/**
25988		 * Current breakpoint.
25989		 * @todo Real media queries would be nice.
25990		 * @protected
25991		 */
25992		this._breakpoint = null;
25993
25994		/**
25995		 * Current width of the plugin element.
25996		 */
25997		this._width = null;
25998
25999		/**
26000		 * All real items.
26001		 * @protected
26002		 */
26003		this._items = [];
26004
26005		/**
26006		 * All cloned items.
26007		 * @protected
26008		 */
26009		this._clones = [];
26010
26011		/**
26012		 * Merge values of all items.
26013		 * @todo Maybe this could be part of a plugin.
26014		 * @protected
26015		 */
26016		this._mergers = [];
26017
26018		/**
26019		 * Widths of all items.
26020		 */
26021		this._widths = [];
26022
26023		/**
26024		 * Invalidated parts within the update process.
26025		 * @protected
26026		 */
26027		this._invalidated = {};
26028
26029		/**
26030		 * Ordered list of workers for the update process.
26031		 * @protected
26032		 */
26033		this._pipe = [];
26034
26035		/**
26036		 * Current state information for the drag operation.
26037		 * @todo #261
26038		 * @protected
26039		 */
26040		this._drag = {
26041			time: null,
26042			target: null,
26043			pointer: null,
26044			stage: {
26045				start: null,
26046				current: null
26047			},
26048			direction: null
26049		};
26050
26051		/**
26052		 * Current state information and their tags.
26053		 * @type {Object}
26054		 * @protected
26055		 */
26056		this._states = {
26057			current: {},
26058			tags: {
26059				'initializing': [ 'busy' ],
26060				'animating': [ 'busy' ],
26061				'dragging': [ 'interacting' ]
26062			}
26063		};
26064
26065		$.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
26066			this._handlers[handler] = $.proxy(this[handler], this);
26067		}, this));
26068
26069		$.each(Owl.Plugins, $.proxy(function(key, plugin) {
26070			this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
26071				= new plugin(this);
26072		}, this));
26073
26074		$.each(Owl.Workers, $.proxy(function(priority, worker) {
26075			this._pipe.push({
26076				'filter': worker.filter,
26077				'run': $.proxy(worker.run, this)
26078			});
26079		}, this));
26080
26081		this.setup();
26082		this.initialize();
26083	}
26084
26085	/**
26086	 * Default options for the carousel.
26087	 * @public
26088	 */
26089	Owl.Defaults = {
26090		items: 3,
26091		loop: false,
26092		center: false,
26093		rewind: false,
26094		checkVisibility: true,
26095
26096		mouseDrag: true,
26097		touchDrag: true,
26098		pullDrag: true,
26099		freeDrag: false,
26100
26101		margin: 0,
26102		stagePadding: 0,
26103
26104		merge: false,
26105		mergeFit: true,
26106		autoWidth: false,
26107
26108		startPosition: 0,
26109		rtl: false,
26110
26111		smartSpeed: 250,
26112		fluidSpeed: false,
26113		dragEndSpeed: false,
26114
26115		responsive: {},
26116		responsiveRefreshRate: 200,
26117		responsiveBaseElement: window,
26118
26119		fallbackEasing: 'swing',
26120		slideTransition: '',
26121
26122		info: false,
26123
26124		nestedItemSelector: false,
26125		itemElement: 'div',
26126		stageElement: 'div',
26127
26128		refreshClass: 'owl-refresh',
26129		loadedClass: 'owl-loaded',
26130		loadingClass: 'owl-loading',
26131		rtlClass: 'owl-rtl',
26132		responsiveClass: 'owl-responsive',
26133		dragClass: 'owl-drag',
26134		itemClass: 'owl-item',
26135		stageClass: 'owl-stage',
26136		stageOuterClass: 'owl-stage-outer',
26137		grabClass: 'owl-grab'
26138	};
26139
26140	/**
26141	 * Enumeration for width.
26142	 * @public
26143	 * @readonly
26144	 * @enum {String}
26145	 */
26146	Owl.Width = {
26147		Default: 'default',
26148		Inner: 'inner',
26149		Outer: 'outer'
26150	};
26151
26152	/**
26153	 * Enumeration for types.
26154	 * @public
26155	 * @readonly
26156	 * @enum {String}
26157	 */
26158	Owl.Type = {
26159		Event: 'event',
26160		State: 'state'
26161	};
26162
26163	/**
26164	 * Contains all registered plugins.
26165	 * @public
26166	 */
26167	Owl.Plugins = {};
26168
26169	/**
26170	 * List of workers involved in the update process.
26171	 */
26172	Owl.Workers = [ {
26173		filter: [ 'width', 'settings' ],
26174		run: function() {
26175			this._width = this.$element.width();
26176		}
26177	}, {
26178		filter: [ 'width', 'items', 'settings' ],
26179		run: function(cache) {
26180			cache.current = this._items && this._items[this.relative(this._current)];
26181		}
26182	}, {
26183		filter: [ 'items', 'settings' ],
26184		run: function() {
26185			this.$stage.children('.cloned').remove();
26186		}
26187	}, {
26188		filter: [ 'width', 'items', 'settings' ],
26189		run: function(cache) {
26190			var margin = this.settings.margin || '',
26191				grid = !this.settings.autoWidth,
26192				rtl = this.settings.rtl,
26193				css = {
26194					'width': 'auto',
26195					'margin-left': rtl ? margin : '',
26196					'margin-right': rtl ? '' : margin
26197				};
26198
26199			!grid && this.$stage.children().css(css);
26200
26201			cache.css = css;
26202		}
26203	}, {
26204		filter: [ 'width', 'items', 'settings' ],
26205		run: function(cache) {
26206			var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin,
26207				merge = null,
26208				iterator = this._items.length,
26209				grid = !this.settings.autoWidth,
26210				widths = [];
26211
26212			cache.items = {
26213				merge: false,
26214				width: width
26215			};
26216
26217			while (iterator--) {
26218				merge = this._mergers[iterator];
26219				merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
26220
26221				cache.items.merge = merge > 1 || cache.items.merge;
26222
26223				widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
26224			}
26225
26226			this._widths = widths;
26227		}
26228	}, {
26229		filter: [ 'items', 'settings' ],
26230		run: function() {
26231			var clones = [],
26232				items = this._items,
26233				settings = this.settings,
26234				// TODO: Should be computed from number of min width items in stage
26235				view = Math.max(settings.items * 2, 4),
26236				size = Math.ceil(items.length / 2) * 2,
26237				repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
26238				append = '',
26239				prepend = '';
26240
26241			repeat /= 2;
26242
26243			while (repeat > 0) {
26244				// Switch to only using appended clones
26245				clones.push(this.normalize(clones.length / 2, true));
26246				append = append + items[clones[clones.length - 1]][0].outerHTML;
26247				clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
26248				prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
26249				repeat -= 1;
26250			}
26251
26252			this._clones = clones;
26253
26254			$(append).addClass('cloned').appendTo(this.$stage);
26255			$(prepend).addClass('cloned').prependTo(this.$stage);
26256		}
26257	}, {
26258		filter: [ 'width', 'items', 'settings' ],
26259		run: function() {
26260			var rtl = this.settings.rtl ? 1 : -1,
26261				size = this._clones.length + this._items.length,
26262				iterator = -1,
26263				previous = 0,
26264				current = 0,
26265				coordinates = [];
26266
26267			while (++iterator < size) {
26268				previous = coordinates[iterator - 1] || 0;
26269				current = this._widths[this.relative(iterator)] + this.settings.margin;
26270				coordinates.push(previous + current * rtl);
26271			}
26272
26273			this._coordinates = coordinates;
26274		}
26275	}, {
26276		filter: [ 'width', 'items', 'settings' ],
26277		run: function() {
26278			var padding = this.settings.stagePadding,
26279				coordinates = this._coordinates,
26280				css = {
26281					'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
26282					'padding-left': padding || '',
26283					'padding-right': padding || ''
26284				};
26285
26286			this.$stage.css(css);
26287		}
26288	}, {
26289		filter: [ 'width', 'items', 'settings' ],
26290		run: function(cache) {
26291			var iterator = this._coordinates.length,
26292				grid = !this.settings.autoWidth,
26293				items = this.$stage.children();
26294
26295			if (grid && cache.items.merge) {
26296				while (iterator--) {
26297					cache.css.width = this._widths[this.relative(iterator)];
26298					items.eq(iterator).css(cache.css);
26299				}
26300			} else if (grid) {
26301				cache.css.width = cache.items.width;
26302				items.css(cache.css);
26303			}
26304		}
26305	}, {
26306		filter: [ 'items' ],
26307		run: function() {
26308			this._coordinates.length < 1 && this.$stage.removeAttr('style');
26309		}
26310	}, {
26311		filter: [ 'width', 'items', 'settings' ],
26312		run: function(cache) {
26313			cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
26314			cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
26315			this.reset(cache.current);
26316		}
26317	}, {
26318		filter: [ 'position' ],
26319		run: function() {
26320			this.animate(this.coordinates(this._current));
26321		}
26322	}, {
26323		filter: [ 'width', 'position', 'items', 'settings' ],
26324		run: function() {
26325			var rtl = this.settings.rtl ? 1 : -1,
26326				padding = this.settings.stagePadding * 2,
26327				begin = this.coordinates(this.current()) + padding,
26328				end = begin + this.width() * rtl,
26329				inner, outer, matches = [], i, n;
26330
26331			for (i = 0, n = this._coordinates.length; i < n; i++) {
26332				inner = this._coordinates[i - 1] || 0;
26333				outer = Math.abs(this._coordinates[i]) + padding * rtl;
26334
26335				if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
26336					|| (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
26337					matches.push(i);
26338				}
26339			}
26340
26341			this.$stage.children('.active').removeClass('active');
26342			this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
26343
26344			this.$stage.children('.center').removeClass('center');
26345			if (this.settings.center) {
26346				this.$stage.children().eq(this.current()).addClass('center');
26347			}
26348		}
26349	} ];
26350
26351	/**
26352	 * Create the stage DOM element
26353	 */
26354	Owl.prototype.initializeStage = function() {
26355		this.$stage = this.$element.find('.' + this.settings.stageClass);
26356
26357		// if the stage is already in the DOM, grab it and skip stage initialization
26358		if (this.$stage.length) {
26359			return;
26360		}
26361
26362		this.$element.addClass(this.options.loadingClass);
26363
26364		// create stage
26365		this.$stage = $('<' + this.settings.stageElement + '>', {
26366			"class": this.settings.stageClass
26367		}).wrap( $( '<div/>', {
26368			"class": this.settings.stageOuterClass
26369		}));
26370
26371		// append stage
26372		this.$element.append(this.$stage.parent());
26373	};
26374
26375	/**
26376	 * Create item DOM elements
26377	 */
26378	Owl.prototype.initializeItems = function() {
26379		var $items = this.$element.find('.owl-item');
26380
26381		// if the items are already in the DOM, grab them and skip item initialization
26382		if ($items.length) {
26383			this._items = $items.get().map(function(item) {
26384				return $(item);
26385			});
26386
26387			this._mergers = this._items.map(function() {
26388				return 1;
26389			});
26390
26391			this.refresh();
26392
26393			return;
26394		}
26395
26396		// append content
26397		this.replace(this.$element.children().not(this.$stage.parent()));
26398
26399		// check visibility
26400		if (this.isVisible()) {
26401			// update view
26402			this.refresh();
26403		} else {
26404			// invalidate width
26405			this.invalidate('width');
26406		}
26407
26408		this.$element
26409			.removeClass(this.options.loadingClass)
26410			.addClass(this.options.loadedClass);
26411	};
26412
26413	/**
26414	 * Initializes the carousel.
26415	 * @protected
26416	 */
26417	Owl.prototype.initialize = function() {
26418		this.enter('initializing');
26419		this.trigger('initialize');
26420
26421		this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
26422
26423		if (this.settings.autoWidth && !this.is('pre-loading')) {
26424			var imgs, nestedSelector, width;
26425			imgs = this.$element.find('img');
26426			nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
26427			width = this.$element.children(nestedSelector).width();
26428
26429			if (imgs.length && width <= 0) {
26430				this.preloadAutoWidthImages(imgs);
26431			}
26432		}
26433
26434		this.initializeStage();
26435		this.initializeItems();
26436
26437		// register event handlers
26438		this.registerEventHandlers();
26439
26440		this.leave('initializing');
26441		this.trigger('initialized');
26442	};
26443
26444	/**
26445	 * @returns {Boolean} visibility of $element
26446	 *                    if you know the carousel will always be visible you can set `checkVisibility` to `false` to
26447	 *                    prevent the expensive browser layout forced reflow the $element.is(':visible') does
26448	 */
26449	Owl.prototype.isVisible = function() {
26450		return this.settings.checkVisibility
26451			? this.$element.is(':visible')
26452			: true;
26453	};
26454
26455	/**
26456	 * Setups the current settings.
26457	 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
26458	 * @todo Support for media queries by using `matchMedia` would be nice.
26459	 * @public
26460	 */
26461	Owl.prototype.setup = function() {
26462		var viewport = this.viewport(),
26463			overwrites = this.options.responsive,
26464			match = -1,
26465			settings = null;
26466
26467		if (!overwrites) {
26468			settings = $.extend({}, this.options);
26469		} else {
26470			$.each(overwrites, function(breakpoint) {
26471				if (breakpoint <= viewport && breakpoint > match) {
26472					match = Number(breakpoint);
26473				}
26474			});
26475
26476			settings = $.extend({}, this.options, overwrites[match]);
26477			if (typeof settings.stagePadding === 'function') {
26478				settings.stagePadding = settings.stagePadding();
26479			}
26480			delete settings.responsive;
26481
26482			// responsive class
26483			if (settings.responsiveClass) {
26484				this.$element.attr('class',
26485					this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
26486				);
26487			}
26488		}
26489
26490		this.trigger('change', { property: { name: 'settings', value: settings } });
26491		this._breakpoint = match;
26492		this.settings = settings;
26493		this.invalidate('settings');
26494		this.trigger('changed', { property: { name: 'settings', value: this.settings } });
26495	};
26496
26497	/**
26498	 * Updates option logic if necessery.
26499	 * @protected
26500	 */
26501	Owl.prototype.optionsLogic = function() {
26502		if (this.settings.autoWidth) {
26503			this.settings.stagePadding = false;
26504			this.settings.merge = false;
26505		}
26506	};
26507
26508	/**
26509	 * Prepares an item before add.
26510	 * @todo Rename event parameter `content` to `item`.
26511	 * @protected
26512	 * @returns {jQuery|HTMLElement} - The item container.
26513	 */
26514	Owl.prototype.prepare = function(item) {
26515		var event = this.trigger('prepare', { content: item });
26516
26517		if (!event.data) {
26518			event.data = $('<' + this.settings.itemElement + '/>')
26519				.addClass(this.options.itemClass).append(item)
26520		}
26521
26522		this.trigger('prepared', { content: event.data });
26523
26524		return event.data;
26525	};
26526
26527	/**
26528	 * Updates the view.
26529	 * @public
26530	 */
26531	Owl.prototype.update = function() {
26532		var i = 0,
26533			n = this._pipe.length,
26534			filter = $.proxy(function(p) { return this[p] }, this._invalidated),
26535			cache = {};
26536
26537		while (i < n) {
26538			if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
26539				this._pipe[i].run(cache);
26540			}
26541			i++;
26542		}
26543
26544		this._invalidated = {};
26545
26546		!this.is('valid') && this.enter('valid');
26547	};
26548
26549	/**
26550	 * Gets the width of the view.
26551	 * @public
26552	 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
26553	 * @returns {Number} - The width of the view in pixel.
26554	 */
26555	Owl.prototype.width = function(dimension) {
26556		dimension = dimension || Owl.Width.Default;
26557		switch (dimension) {
26558			case Owl.Width.Inner:
26559			case Owl.Width.Outer:
26560				return this._width;
26561			default:
26562				return this._width - this.settings.stagePadding * 2 + this.settings.margin;
26563		}
26564	};
26565
26566	/**
26567	 * Refreshes the carousel primarily for adaptive purposes.
26568	 * @public
26569	 */
26570	Owl.prototype.refresh = function() {
26571		this.enter('refreshing');
26572		this.trigger('refresh');
26573
26574		this.setup();
26575
26576		this.optionsLogic();
26577
26578		this.$element.addClass(this.options.refreshClass);
26579
26580		this.update();
26581
26582		this.$element.removeClass(this.options.refreshClass);
26583
26584		this.leave('refreshing');
26585		this.trigger('refreshed');
26586	};
26587
26588	/**
26589	 * Checks window `resize` event.
26590	 * @protected
26591	 */
26592	Owl.prototype.onThrottledResize = function() {
26593		window.clearTimeout(this.resizeTimer);
26594		this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
26595	};
26596
26597	/**
26598	 * Checks window `resize` event.
26599	 * @protected
26600	 */
26601	Owl.prototype.onResize = function() {
26602		if (!this._items.length) {
26603			return false;
26604		}
26605
26606		if (this._width === this.$element.width()) {
26607			return false;
26608		}
26609
26610		if (!this.isVisible()) {
26611			return false;
26612		}
26613
26614		this.enter('resizing');
26615
26616		if (this.trigger('resize').isDefaultPrevented()) {
26617			this.leave('resizing');
26618			return false;
26619		}
26620
26621		this.invalidate('width');
26622
26623		this.refresh();
26624
26625		this.leave('resizing');
26626		this.trigger('resized');
26627	};
26628
26629	/**
26630	 * Registers event handlers.
26631	 * @todo Check `msPointerEnabled`
26632	 * @todo #261
26633	 * @protected
26634	 */
26635	Owl.prototype.registerEventHandlers = function() {
26636		if ($.support.transition) {
26637			this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
26638		}
26639
26640		if (this.settings.responsive !== false) {
26641			this.on(window, 'resize', this._handlers.onThrottledResize);
26642		}
26643
26644		if (this.settings.mouseDrag) {
26645			this.$element.addClass(this.options.dragClass);
26646			this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
26647			this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
26648		}
26649
26650		if (this.settings.touchDrag){
26651			this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
26652			this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
26653		}
26654	};
26655
26656	/**
26657	 * Handles `touchstart` and `mousedown` events.
26658	 * @todo Horizontal swipe threshold as option
26659	 * @todo #261
26660	 * @protected
26661	 * @param {Event} event - The event arguments.
26662	 */
26663	Owl.prototype.onDragStart = function(event) {
26664		var stage = null;
26665
26666		if (event.which === 3) {
26667			return;
26668		}
26669
26670		if ($.support.transform) {
26671			stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
26672			stage = {
26673				x: stage[stage.length === 16 ? 12 : 4],
26674				y: stage[stage.length === 16 ? 13 : 5]
26675			};
26676		} else {
26677			stage = this.$stage.position();
26678			stage = {
26679				x: this.settings.rtl ?
26680					stage.left + this.$stage.width() - this.width() + this.settings.margin :
26681					stage.left,
26682				y: stage.top
26683			};
26684		}
26685
26686		if (this.is('animating')) {
26687			$.support.transform ? this.animate(stage.x) : this.$stage.stop()
26688			this.invalidate('position');
26689		}
26690
26691		this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
26692
26693		this.speed(0);
26694
26695		this._drag.time = new Date().getTime();
26696		this._drag.target = $(event.target);
26697		this._drag.stage.start = stage;
26698		this._drag.stage.current = stage;
26699		this._drag.pointer = this.pointer(event);
26700
26701		$(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
26702
26703		$(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
26704			var delta = this.difference(this._drag.pointer, this.pointer(event));
26705
26706			$(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
26707
26708			if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
26709				return;
26710			}
26711
26712			event.preventDefault();
26713
26714			this.enter('dragging');
26715			this.trigger('drag');
26716		}, this));
26717	};
26718
26719	/**
26720	 * Handles the `touchmove` and `mousemove` events.
26721	 * @todo #261
26722	 * @protected
26723	 * @param {Event} event - The event arguments.
26724	 */
26725	Owl.prototype.onDragMove = function(event) {
26726		var minimum = null,
26727			maximum = null,
26728			pull = null,
26729			delta = this.difference(this._drag.pointer, this.pointer(event)),
26730			stage = this.difference(this._drag.stage.start, delta);
26731
26732		if (!this.is('dragging')) {
26733			return;
26734		}
26735
26736		event.preventDefault();
26737
26738		if (this.settings.loop) {
26739			minimum = this.coordinates(this.minimum());
26740			maximum = this.coordinates(this.maximum() + 1) - minimum;
26741			stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
26742		} else {
26743			minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
26744			maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
26745			pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
26746			stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
26747		}
26748
26749		this._drag.stage.current = stage;
26750
26751		this.animate(stage.x);
26752	};
26753
26754	/**
26755	 * Handles the `touchend` and `mouseup` events.
26756	 * @todo #261
26757	 * @todo Threshold for click event
26758	 * @protected
26759	 * @param {Event} event - The event arguments.
26760	 */
26761	Owl.prototype.onDragEnd = function(event) {
26762		var delta = this.difference(this._drag.pointer, this.pointer(event)),
26763			stage = this._drag.stage.current,
26764			direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
26765
26766		$(document).off('.owl.core');
26767
26768		this.$element.removeClass(this.options.grabClass);
26769
26770		if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
26771			this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
26772			this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
26773			this.invalidate('position');
26774			this.update();
26775
26776			this._drag.direction = direction;
26777
26778			if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
26779				this._drag.target.one('click.owl.core', function() { return false; });
26780			}
26781		}
26782
26783		if (!this.is('dragging')) {
26784			return;
26785		}
26786
26787		this.leave('dragging');
26788		this.trigger('dragged');
26789	};
26790
26791	/**
26792	 * Gets absolute position of the closest item for a coordinate.
26793	 * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
26794	 * @protected
26795	 * @param {Number} coordinate - The coordinate in pixel.
26796	 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
26797	 * @return {Number} - The absolute position of the closest item.
26798	 */
26799	Owl.prototype.closest = function(coordinate, direction) {
26800		var position = -1,
26801			pull = 30,
26802			width = this.width(),
26803			coordinates = this.coordinates();
26804
26805		if (!this.settings.freeDrag) {
26806			// check closest item
26807			$.each(coordinates, $.proxy(function(index, value) {
26808				// on a left pull, check on current index
26809				if (direction === 'left' && coordinate > value - pull && coordinate < value + pull) {
26810					position = index;
26811				// on a right pull, check on previous index
26812				// to do so, subtract width from value and set position = index + 1
26813				} else if (direction === 'right' && coordinate > value - width - pull && coordinate < value - width + pull) {
26814					position = index + 1;
26815				} else if (this.op(coordinate, '<', value)
26816					&& this.op(coordinate, '>', coordinates[index + 1] !== undefined ? coordinates[index + 1] : value - width)) {
26817					position = direction === 'left' ? index + 1 : index;
26818				}
26819				return position === -1;
26820			}, this));
26821		}
26822
26823		if (!this.settings.loop) {
26824			// non loop boundries
26825			if (this.op(coordinate, '>', coordinates[this.minimum()])) {
26826				position = coordinate = this.minimum();
26827			} else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
26828				position = coordinate = this.maximum();
26829			}
26830		}
26831
26832		return position;
26833	};
26834
26835	/**
26836	 * Animates the stage.
26837	 * @todo #270
26838	 * @public
26839	 * @param {Number} coordinate - The coordinate in pixels.
26840	 */
26841	Owl.prototype.animate = function(coordinate) {
26842		var animate = this.speed() > 0;
26843
26844		this.is('animating') && this.onTransitionEnd();
26845
26846		if (animate) {
26847			this.enter('animating');
26848			this.trigger('translate');
26849		}
26850
vendor: 10,524 bytes, lines 26851-27218
26851		if ($.support.transform3d && $.support.transition) {
26852			this.$stage.css({
26853				transform: 'translate3d(' + coordinate + 'px,0px,0px)',
26854				transition: (this.speed() / 1000) + 's' + (
26855					this.settings.slideTransition ? ' ' + this.settings.slideTransition : ''
26856				)
26857			});
26858		} else if (animate) {
26859			this.$stage.animate({
26860				left: coordinate + 'px'
26861			}, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
26862		} else {
26863			this.$stage.css({
26864				left: coordinate + 'px'
26865			});
26866		}
26867	};
26868
26869	/**
26870	 * Checks whether the carousel is in a specific state or not.
26871	 * @param {String} state - The state to check.
26872	 * @returns {Boolean} - The flag which indicates if the carousel is busy.
26873	 */
26874	Owl.prototype.is = function(state) {
26875		return this._states.current[state] && this._states.current[state] > 0;
26876	};
26877
26878	/**
26879	 * Sets the absolute position of the current item.
26880	 * @public
26881	 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
26882	 * @returns {Number} - The absolute position of the current item.
26883	 */
26884	Owl.prototype.current = function(position) {
26885		if (position === undefined) {
26886			return this._current;
26887		}
26888
26889		if (this._items.length === 0) {
26890			return undefined;
26891		}
26892
26893		position = this.normalize(position);
26894
26895		if (this._current !== position) {
26896			var event = this.trigger('change', { property: { name: 'position', value: position } });
26897
26898			if (event.data !== undefined) {
26899				position = this.normalize(event.data);
26900			}
26901
26902			this._current = position;
26903
26904			this.invalidate('position');
26905
26906			this.trigger('changed', { property: { name: 'position', value: this._current } });
26907		}
26908
26909		return this._current;
26910	};
26911
26912	/**
26913	 * Invalidates the given part of the update routine.
26914	 * @param {String} [part] - The part to invalidate.
26915	 * @returns {Array.<String>} - The invalidated parts.
26916	 */
26917	Owl.prototype.invalidate = function(part) {
26918		if ($.type(part) === 'string') {
26919			this._invalidated[part] = true;
26920			this.is('valid') && this.leave('valid');
26921		}
26922		return $.map(this._invalidated, function(v, i) { return i });
26923	};
26924
26925	/**
26926	 * Resets the absolute position of the current item.
26927	 * @public
26928	 * @param {Number} position - The absolute position of the new item.
26929	 */
26930	Owl.prototype.reset = function(position) {
26931		position = this.normalize(position);
26932
26933		if (position === undefined) {
26934			return;
26935		}
26936
26937		this._speed = 0;
26938		this._current = position;
26939
26940		this.suppress([ 'translate', 'translated' ]);
26941
26942		this.animate(this.coordinates(position));
26943
26944		this.release([ 'translate', 'translated' ]);
26945	};
26946
26947	/**
26948	 * Normalizes an absolute or a relative position of an item.
26949	 * @public
26950	 * @param {Number} position - The absolute or relative position to normalize.
26951	 * @param {Boolean} [relative=false] - Whether the given position is relative or not.
26952	 * @returns {Number} - The normalized position.
26953	 */
26954	Owl.prototype.normalize = function(position, relative) {
26955		var n = this._items.length,
26956			m = relative ? 0 : this._clones.length;
26957
26958		if (!this.isNumeric(position) || n < 1) {
26959			position = undefined;
26960		} else if (position < 0 || position >= n + m) {
26961			position = ((position - m / 2) % n + n) % n + m / 2;
26962		}
26963
26964		return position;
26965	};
26966
26967	/**
26968	 * Converts an absolute position of an item into a relative one.
26969	 * @public
26970	 * @param {Number} position - The absolute position to convert.
26971	 * @returns {Number} - The converted position.
26972	 */
26973	Owl.prototype.relative = function(position) {
26974		position -= this._clones.length / 2;
26975		return this.normalize(position, true);
26976	};
26977
26978	/**
26979	 * Gets the maximum position for the current item.
26980	 * @public
26981	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
26982	 * @returns {Number}
26983	 */
26984	Owl.prototype.maximum = function(relative) {
26985		var settings = this.settings,
26986			maximum = this._coordinates.length,
26987			iterator,
26988			reciprocalItemsWidth,
26989			elementWidth;
26990
26991		if (settings.loop) {
26992			maximum = this._clones.length / 2 + this._items.length - 1;
26993		} else if (settings.autoWidth || settings.merge) {
26994			iterator = this._items.length;
26995			if (iterator) {
26996				reciprocalItemsWidth = this._items[--iterator].width();
26997				elementWidth = this.$element.width();
26998				while (iterator--) {
26999					reciprocalItemsWidth += this._items[iterator].width() + this.settings.margin;
27000					if (reciprocalItemsWidth > elementWidth) {
27001						break;
27002					}
27003				}
27004			}
27005			maximum = iterator + 1;
27006		} else if (settings.center) {
27007			maximum = this._items.length - 1;
27008		} else {
27009			maximum = this._items.length - settings.items;
27010		}
27011
27012		if (relative) {
27013			maximum -= this._clones.length / 2;
27014		}
27015
27016		return Math.max(maximum, 0);
27017	};
27018
27019	/**
27020	 * Gets the minimum position for the current item.
27021	 * @public
27022	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
27023	 * @returns {Number}
27024	 */
27025	Owl.prototype.minimum = function(relative) {
27026		return relative ? 0 : this._clones.length / 2;
27027	};
27028
27029	/**
27030	 * Gets an item at the specified relative position.
27031	 * @public
27032	 * @param {Number} [position] - The relative position of the item.
27033	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
27034	 */
27035	Owl.prototype.items = function(position) {
27036		if (position === undefined) {
27037			return this._items.slice();
27038		}
27039
27040		position = this.normalize(position, true);
27041		return this._items[position];
27042	};
27043
27044	/**
27045	 * Gets an item at the specified relative position.
27046	 * @public
27047	 * @param {Number} [position] - The relative position of the item.
27048	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
27049	 */
27050	Owl.prototype.mergers = function(position) {
27051		if (position === undefined) {
27052			return this._mergers.slice();
27053		}
27054
27055		position = this.normalize(position, true);
27056		return this._mergers[position];
27057	};
27058
27059	/**
27060	 * Gets the absolute positions of clones for an item.
27061	 * @public
27062	 * @param {Number} [position] - The relative position of the item.
27063	 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
27064	 */
27065	Owl.prototype.clones = function(position) {
27066		var odd = this._clones.length / 2,
27067			even = odd + this._items.length,
27068			map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
27069
27070		if (position === undefined) {
27071			return $.map(this._clones, function(v, i) { return map(i) });
27072		}
27073
27074		return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
27075	};
27076
27077	/**
27078	 * Sets the current animation speed.
27079	 * @public
27080	 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
27081	 * @returns {Number} - The current animation speed in milliseconds.
27082	 */
27083	Owl.prototype.speed = function(speed) {
27084		if (speed !== undefined) {
27085			this._speed = speed;
27086		}
27087
27088		return this._speed;
27089	};
27090
27091	/**
27092	 * Gets the coordinate of an item.
27093	 * @todo The name of this method is missleanding.
27094	 * @public
27095	 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
27096	 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
27097	 */
27098	Owl.prototype.coordinates = function(position) {
27099		var multiplier = 1,
27100			newPosition = position - 1,
27101			coordinate;
27102
27103		if (position === undefined) {
27104			return $.map(this._coordinates, $.proxy(function(coordinate, index) {
27105				return this.coordinates(index);
27106			}, this));
27107		}
27108
27109		if (this.settings.center) {
27110			if (this.settings.rtl) {
27111				multiplier = -1;
27112				newPosition = position + 1;
27113			}
27114
27115			coordinate = this._coordinates[position];
27116			coordinate += (this.width() - coordinate + (this._coordinates[newPosition] || 0)) / 2 * multiplier;
27117		} else {
27118			coordinate = this._coordinates[newPosition] || 0;
27119		}
27120
27121		coordinate = Math.ceil(coordinate);
27122
27123		return coordinate;
27124	};
27125
27126	/**
27127	 * Calculates the speed for a translation.
27128	 * @protected
27129	 * @param {Number} from - The absolute position of the start item.
27130	 * @param {Number} to - The absolute position of the target item.
27131	 * @param {Number} [factor=undefined] - The time factor in milliseconds.
27132	 * @returns {Number} - The time in milliseconds for the translation.
27133	 */
27134	Owl.prototype.duration = function(from, to, factor) {
27135		if (factor === 0) {
27136			return 0;
27137		}
27138
27139		return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
27140	};
27141
27142	/**
27143	 * Slides to the specified item.
27144	 * @public
27145	 * @param {Number} position - The position of the item.
27146	 * @param {Number} [speed] - The time in milliseconds for the transition.
27147	 */
27148	Owl.prototype.to = function(position, speed) {
27149		var current = this.current(),
27150			revert = null,
27151			distance = position - this.relative(current),
27152			direction = (distance > 0) - (distance < 0),
27153			items = this._items.length,
27154			minimum = this.minimum(),
27155			maximum = this.maximum();
27156
27157		if (this.settings.loop) {
27158			if (!this.settings.rewind && Math.abs(distance) > items / 2) {
27159				distance += direction * -1 * items;
27160			}
27161
27162			position = current + distance;
27163			revert = ((position - minimum) % items + items) % items + minimum;
27164
27165			if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
27166				current = revert - distance;
27167				position = revert;
27168				this.reset(current);
27169			}
27170		} else if (this.settings.rewind) {
27171			maximum += 1;
27172			position = (position % maximum + maximum) % maximum;
27173		} else {
27174			position = Math.max(minimum, Math.min(maximum, position));
27175		}
27176
27177		this.speed(this.duration(current, position, speed));
27178		this.current(position);
27179
27180		if (this.isVisible()) {
27181			this.update();
27182		}
27183	};
27184
27185	/**
27186	 * Slides to the next item.
27187	 * @public
27188	 * @param {Number} [speed] - The time in milliseconds for the transition.
27189	 */
27190	Owl.prototype.next = function(speed) {
27191		speed = speed || false;
27192		this.to(this.relative(this.current()) + 1, speed);
27193	};
27194
27195	/**
27196	 * Slides to the previous item.
27197	 * @public
27198	 * @param {Number} [speed] - The time in milliseconds for the transition.
27199	 */
27200	Owl.prototype.prev = function(speed) {
27201		speed = speed || false;
27202		this.to(this.relative(this.current()) - 1, speed);
27203	};
27204
27205	/**
27206	 * Handles the end of an animation.
27207	 * @protected
27208	 * @param {Event} event - The event arguments.
27209	 */
27210	Owl.prototype.onTransitionEnd = function(event) {
27211
27212		// if css2 animation then event object is undefined
27213		if (event !== undefined) {
27214			event.stopPropagation();
27215
27216			// Catch only owl-stage transitionEnd event
27217			if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
27218				return false;
vendor: 22,957 bytes, lines 27219-28067
27219			}
27220		}
27221
27222		this.leave('animating');
27223		this.trigger('translated');
27224	};
27225
27226	/**
27227	 * Gets viewport width.
27228	 * @protected
27229	 * @return {Number} - The width in pixel.
27230	 */
27231	Owl.prototype.viewport = function() {
27232		var width;
27233		if (this.options.responsiveBaseElement !== window) {
27234			width = $(this.options.responsiveBaseElement).width();
27235		} else if (window.innerWidth) {
27236			width = window.innerWidth;
27237		} else if (document.documentElement && document.documentElement.clientWidth) {
27238			width = document.documentElement.clientWidth;
27239		} else {
27240			console.warn('Can not detect viewport width.');
27241		}
27242		return width;
27243	};
27244
27245	/**
27246	 * Replaces the current content.
27247	 * @public
27248	 * @param {HTMLElement|jQuery|String} content - The new content.
27249	 */
27250	Owl.prototype.replace = function(content) {
27251		this.$stage.empty();
27252		this._items = [];
27253
27254		if (content) {
27255			content = (content instanceof jQuery) ? content : $(content);
27256		}
27257
27258		if (this.settings.nestedItemSelector) {
27259			content = content.find('.' + this.settings.nestedItemSelector);
27260		}
27261
27262		content.filter(function() {
27263			return this.nodeType === 1;
27264		}).each($.proxy(function(index, item) {
27265			item = this.prepare(item);
27266			this.$stage.append(item);
27267			this._items.push(item);
27268			this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
27269		}, this));
27270
27271		this.reset(this.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
27272
27273		this.invalidate('items');
27274	};
27275
27276	/**
27277	 * Adds an item.
27278	 * @todo Use `item` instead of `content` for the event arguments.
27279	 * @public
27280	 * @param {HTMLElement|jQuery|String} content - The item content to add.
27281	 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
27282	 */
27283	Owl.prototype.add = function(content, position) {
27284		var current = this.relative(this._current);
27285
27286		position = position === undefined ? this._items.length : this.normalize(position, true);
27287		content = content instanceof jQuery ? content : $(content);
27288
27289		this.trigger('add', { content: content, position: position });
27290
27291		content = this.prepare(content);
27292
27293		if (this._items.length === 0 || position === this._items.length) {
27294			this._items.length === 0 && this.$stage.append(content);
27295			this._items.length !== 0 && this._items[position - 1].after(content);
27296			this._items.push(content);
27297			this._mergers.push(content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
27298		} else {
27299			this._items[position].before(content);
27300			this._items.splice(position, 0, content);
27301			this._mergers.splice(position, 0, content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
27302		}
27303
27304		this._items[current] && this.reset(this._items[current].index());
27305
27306		this.invalidate('items');
27307
27308		this.trigger('added', { content: content, position: position });
27309	};
27310
27311	/**
27312	 * Removes an item by its position.
27313	 * @todo Use `item` instead of `content` for the event arguments.
27314	 * @public
27315	 * @param {Number} position - The relative position of the item to remove.
27316	 */
27317	Owl.prototype.remove = function(position) {
27318		position = this.normalize(position, true);
27319
27320		if (position === undefined) {
27321			return;
27322		}
27323
27324		this.trigger('remove', { content: this._items[position], position: position });
27325
27326		this._items[position].remove();
27327		this._items.splice(position, 1);
27328		this._mergers.splice(position, 1);
27329
27330		this.invalidate('items');
27331
27332		this.trigger('removed', { content: null, position: position });
27333	};
27334
27335	/**
27336	 * Preloads images with auto width.
27337	 * @todo Replace by a more generic approach
27338	 * @protected
27339	 */
27340	Owl.prototype.preloadAutoWidthImages = function(images) {
27341		images.each($.proxy(function(i, element) {
27342			this.enter('pre-loading');
27343			element = $(element);
27344			$(new Image()).one('load', $.proxy(function(e) {
27345				element.attr('src', e.target.src);
27346				element.css('opacity', 1);
27347				this.leave('pre-loading');
27348				!this.is('pre-loading') && !this.is('initializing') && this.refresh();
27349			}, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
27350		}, this));
27351	};
27352
27353	/**
27354	 * Destroys the carousel.
27355	 * @public
27356	 */
27357	Owl.prototype.destroy = function() {
27358
27359		this.$element.off('.owl.core');
27360		this.$stage.off('.owl.core');
27361		$(document).off('.owl.core');
27362
27363		if (this.settings.responsive !== false) {
27364			window.clearTimeout(this.resizeTimer);
27365			this.off(window, 'resize', this._handlers.onThrottledResize);
27366		}
27367
27368		for (var i in this._plugins) {
27369			this._plugins[i].destroy();
27370		}
27371
27372		this.$stage.children('.cloned').remove();
27373
27374		this.$stage.unwrap();
27375		this.$stage.children().contents().unwrap();
27376		this.$stage.children().unwrap();
27377		this.$stage.remove();
27378		this.$element
27379			.removeClass(this.options.refreshClass)
27380			.removeClass(this.options.loadingClass)
27381			.removeClass(this.options.loadedClass)
27382			.removeClass(this.options.rtlClass)
27383			.removeClass(this.options.dragClass)
27384			.removeClass(this.options.grabClass)
27385			.attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
27386			.removeData('owl.carousel');
27387	};
27388
27389	/**
27390	 * Operators to calculate right-to-left and left-to-right.
27391	 * @protected
27392	 * @param {Number} [a] - The left side operand.
27393	 * @param {String} [o] - The operator.
27394	 * @param {Number} [b] - The right side operand.
27395	 */
27396	Owl.prototype.op = function(a, o, b) {
27397		var rtl = this.settings.rtl;
27398		switch (o) {
27399			case '<':
27400				return rtl ? a > b : a < b;
27401			case '>':
27402				return rtl ? a < b : a > b;
27403			case '>=':
27404				return rtl ? a <= b : a >= b;
27405			case '<=':
27406				return rtl ? a >= b : a <= b;
27407			default:
27408				break;
27409		}
27410	};
27411
27412	/**
27413	 * Attaches to an internal event.
27414	 * @protected
27415	 * @param {HTMLElement} element - The event source.
27416	 * @param {String} event - The event name.
27417	 * @param {Function} listener - The event handler to attach.
27418	 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
27419	 */
27420	Owl.prototype.on = function(element, event, listener, capture) {
27421		if (element.addEventListener) {
27422			element.addEventListener(event, listener, capture);
27423		} else if (element.attachEvent) {
27424			element.attachEvent('on' + event, listener);
27425		}
27426	};
27427
27428	/**
27429	 * Detaches from an internal event.
27430	 * @protected
27431	 * @param {HTMLElement} element - The event source.
27432	 * @param {String} event - The event name.
27433	 * @param {Function} listener - The attached event handler to detach.
27434	 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
27435	 */
27436	Owl.prototype.off = function(element, event, listener, capture) {
27437		if (element.removeEventListener) {
27438			element.removeEventListener(event, listener, capture);
27439		} else if (element.detachEvent) {
27440			element.detachEvent('on' + event, listener);
27441		}
27442	};
27443
27444	/**
27445	 * Triggers a public event.
27446	 * @todo Remove `status`, `relatedTarget` should be used instead.
27447	 * @protected
27448	 * @param {String} name - The event name.
27449	 * @param {*} [data=null] - The event data.
27450	 * @param {String} [namespace=carousel] - The event namespace.
27451	 * @param {String} [state] - The state which is associated with the event.
27452	 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
27453	 * @returns {Event} - The event arguments.
27454	 */
27455	Owl.prototype.trigger = function(name, data, namespace, state, enter) {
27456		var status = {
27457			item: { count: this._items.length, index: this.current() }
27458		}, handler = $.camelCase(
27459			$.grep([ 'on', name, namespace ], function(v) { return v })
27460				.join('-').toLowerCase()
27461		), event = $.Event(
27462			[ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
27463			$.extend({ relatedTarget: this }, status, data)
27464		);
27465
27466		if (!this._supress[name]) {
27467			$.each(this._plugins, function(name, plugin) {
27468				if (plugin.onTrigger) {
27469					plugin.onTrigger(event);
27470				}
27471			});
27472
27473			this.register({ type: Owl.Type.Event, name: name });
27474			this.$element.trigger(event);
27475
27476			if (this.settings && typeof this.settings[handler] === 'function') {
27477				this.settings[handler].call(this, event);
27478			}
27479		}
27480
27481		return event;
27482	};
27483
27484	/**
27485	 * Enters a state.
27486	 * @param name - The state name.
27487	 */
27488	Owl.prototype.enter = function(name) {
27489		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
27490			if (this._states.current[name] === undefined) {
27491				this._states.current[name] = 0;
27492			}
27493
27494			this._states.current[name]++;
27495		}, this));
27496	};
27497
27498	/**
27499	 * Leaves a state.
27500	 * @param name - The state name.
27501	 */
27502	Owl.prototype.leave = function(name) {
27503		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
27504			this._states.current[name]--;
27505		}, this));
27506	};
27507
27508	/**
27509	 * Registers an event or state.
27510	 * @public
27511	 * @param {Object} object - The event or state to register.
27512	 */
27513	Owl.prototype.register = function(object) {
27514		if (object.type === Owl.Type.Event) {
27515			if (!$.event.special[object.name]) {
27516				$.event.special[object.name] = {};
27517			}
27518
27519			if (!$.event.special[object.name].owl) {
27520				var _default = $.event.special[object.name]._default;
27521				$.event.special[object.name]._default = function(e) {
27522					if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
27523						return _default.apply(this, arguments);
27524					}
27525					return e.namespace && e.namespace.indexOf('owl') > -1;
27526				};
27527				$.event.special[object.name].owl = true;
27528			}
27529		} else if (object.type === Owl.Type.State) {
27530			if (!this._states.tags[object.name]) {
27531				this._states.tags[object.name] = object.tags;
27532			} else {
27533				this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
27534			}
27535
27536			this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
27537				return $.inArray(tag, this._states.tags[object.name]) === i;
27538			}, this));
27539		}
27540	};
27541
27542	/**
27543	 * Suppresses events.
27544	 * @protected
27545	 * @param {Array.<String>} events - The events to suppress.
27546	 */
27547	Owl.prototype.suppress = function(events) {
27548		$.each(events, $.proxy(function(index, event) {
27549			this._supress[event] = true;
27550		}, this));
27551	};
27552
27553	/**
27554	 * Releases suppressed events.
27555	 * @protected
27556	 * @param {Array.<String>} events - The events to release.
27557	 */
27558	Owl.prototype.release = function(events) {
27559		$.each(events, $.proxy(function(index, event) {
27560			delete this._supress[event];
27561		}, this));
27562	};
27563
27564	/**
27565	 * Gets unified pointer coordinates from event.
27566	 * @todo #261
27567	 * @protected
27568	 * @param {Event} - The `mousedown` or `touchstart` event.
27569	 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
27570	 */
27571	Owl.prototype.pointer = function(event) {
27572		var result = { x: null, y: null };
27573
27574		event = event.originalEvent || event || window.event;
27575
27576		event = event.touches && event.touches.length ?
27577			event.touches[0] : event.changedTouches && event.changedTouches.length ?
27578				event.changedTouches[0] : event;
27579
27580		if (event.pageX) {
27581			result.x = event.pageX;
27582			result.y = event.pageY;
27583		} else {
27584			result.x = event.clientX;
27585			result.y = event.clientY;
27586		}
27587
27588		return result;
27589	};
27590
27591	/**
27592	 * Determines if the input is a Number or something that can be coerced to a Number
27593	 * @protected
27594	 * @param {Number|String|Object|Array|Boolean|RegExp|Function|Symbol} - The input to be tested
27595	 * @returns {Boolean} - An indication if the input is a Number or can be coerced to a Number
27596	 */
27597	Owl.prototype.isNumeric = function(number) {
27598		return !isNaN(parseFloat(number));
27599	};
27600
27601	/**
27602	 * Gets the difference of two vectors.
27603	 * @todo #261
27604	 * @protected
27605	 * @param {Object} - The first vector.
27606	 * @param {Object} - The second vector.
27607	 * @returns {Object} - The difference.
27608	 */
27609	Owl.prototype.difference = function(first, second) {
27610		return {
27611			x: first.x - second.x,
27612			y: first.y - second.y
27613		};
27614	};
27615
27616	/**
27617	 * The jQuery Plugin for the Owl Carousel
27618	 * @todo Navigation plugin `next` and `prev`
27619	 * @public
27620	 */
27621	$.fn.owlCarousel = function(option) {
27622		var args = Array.prototype.slice.call(arguments, 1);
27623
27624		return this.each(function() {
27625			var $this = $(this),
27626				data = $this.data('owl.carousel');
27627
27628			if (!data) {
27629				data = new Owl(this, typeof option == 'object' && option);
27630				$this.data('owl.carousel', data);
27631
27632				$.each([
27633					'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
27634				], function(i, event) {
27635					data.register({ type: Owl.Type.Event, name: event });
27636					data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
27637						if (e.namespace && e.relatedTarget !== this) {
27638							this.suppress([ event ]);
27639							data[event].apply(this, [].slice.call(arguments, 1));
27640							this.release([ event ]);
27641						}
27642					}, data));
27643				});
27644			}
27645
27646			if (typeof option == 'string' && option.charAt(0) !== '_') {
27647				data[option].apply(data, args);
27648			}
27649		});
27650	};
27651
27652	/**
27653	 * The constructor for the jQuery Plugin
27654	 * @public
27655	 */
27656	$.fn.owlCarousel.Constructor = Owl;
27657
27658})(window.Zepto || window.jQuery, window, document);
27659
27660/**
27661 * AutoRefresh Plugin
27662 * @version 2.3.4
27663 * @author Artus Kolanowski
27664 * @author David Deutsch
27665 * @license The MIT License (MIT)
27666 */
27667;(function($, window, document, undefined) {
27668
27669	/**
27670	 * Creates the auto refresh plugin.
27671	 * @class The Auto Refresh Plugin
27672	 * @param {Owl} carousel - The Owl Carousel
27673	 */
27674	var AutoRefresh = function(carousel) {
27675		/**
27676		 * Reference to the core.
27677		 * @protected
27678		 * @type {Owl}
27679		 */
27680		this._core = carousel;
27681
27682		/**
27683		 * Refresh interval.
27684		 * @protected
27685		 * @type {number}
27686		 */
27687		this._interval = null;
27688
27689		/**
27690		 * Whether the element is currently visible or not.
27691		 * @protected
27692		 * @type {Boolean}
27693		 */
27694		this._visible = null;
27695
27696		/**
27697		 * All event handlers.
27698		 * @protected
27699		 * @type {Object}
27700		 */
27701		this._handlers = {
27702			'initialized.owl.carousel': $.proxy(function(e) {
27703				if (e.namespace && this._core.settings.autoRefresh) {
27704					this.watch();
27705				}
27706			}, this)
27707		};
27708
27709		// set default options
27710		this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);
27711
27712		// register event handlers
27713		this._core.$element.on(this._handlers);
27714	};
27715
27716	/**
27717	 * Default options.
27718	 * @public
27719	 */
27720	AutoRefresh.Defaults = {
27721		autoRefresh: true,
27722		autoRefreshInterval: 500
27723	};
27724
27725	/**
27726	 * Watches the element.
27727	 */
27728	AutoRefresh.prototype.watch = function() {
27729		if (this._interval) {
27730			return;
27731		}
27732
27733		this._visible = this._core.isVisible();
27734		this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
27735	};
27736
27737	/**
27738	 * Refreshes the element.
27739	 */
27740	AutoRefresh.prototype.refresh = function() {
27741		if (this._core.isVisible() === this._visible) {
27742			return;
27743		}
27744
27745		this._visible = !this._visible;
27746
27747		this._core.$element.toggleClass('owl-hidden', !this._visible);
27748
27749		this._visible && (this._core.invalidate('width') && this._core.refresh());
27750	};
27751
27752	/**
27753	 * Destroys the plugin.
27754	 */
27755	AutoRefresh.prototype.destroy = function() {
27756		var handler, property;
27757
27758		window.clearInterval(this._interval);
27759
27760		for (handler in this._handlers) {
27761			this._core.$element.off(handler, this._handlers[handler]);
27762		}
27763		for (property in Object.getOwnPropertyNames(this)) {
27764			typeof this[property] != 'function' && (this[property] = null);
27765		}
27766	};
27767
27768	$.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;
27769
27770})(window.Zepto || window.jQuery, window, document);
27771
27772/**
27773 * Lazy Plugin
27774 * @version 2.3.4
27775 * @author Bartosz Wojciechowski
27776 * @author David Deutsch
27777 * @license The MIT License (MIT)
27778 */
27779;(function($, window, document, undefined) {
27780
27781	/**
27782	 * Creates the lazy plugin.
27783	 * @class The Lazy Plugin
27784	 * @param {Owl} carousel - The Owl Carousel
27785	 */
27786	var Lazy = function(carousel) {
27787
27788		/**
27789		 * Reference to the core.
27790		 * @protected
27791		 * @type {Owl}
27792		 */
27793		this._core = carousel;
27794
27795		/**
27796		 * Already loaded items.
27797		 * @protected
27798		 * @type {Array.<jQuery>}
27799		 */
27800		this._loaded = [];
27801
27802		/**
27803		 * Event handlers.
27804		 * @protected
27805		 * @type {Object}
27806		 */
27807		this._handlers = {
27808			'initialized.owl.carousel change.owl.carousel resized.owl.carousel': $.proxy(function(e) {
27809				if (!e.namespace) {
27810					return;
27811				}
27812
27813				if (!this._core.settings || !this._core.settings.lazyLoad) {
27814					return;
27815				}
27816
27817				if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
27818					var settings = this._core.settings,
27819						n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
27820						i = ((settings.center && n * -1) || 0),
27821						position = (e.property && e.property.value !== undefined ? e.property.value : this._core.current()) + i,
27822						clones = this._core.clones().length,
27823						load = $.proxy(function(i, v) { this.load(v) }, this);
27824					//TODO: Need documentation for this new option
27825					if (settings.lazyLoadEager > 0) {
27826						n += settings.lazyLoadEager;
27827						// If the carousel is looping also preload images that are to the "left"
27828						if (settings.loop) {
27829              position -= settings.lazyLoadEager;
27830              n++;
27831            }
27832					}
27833
27834					while (i++ < n) {
27835						this.load(clones / 2 + this._core.relative(position));
27836						clones && $.each(this._core.clones(this._core.relative(position)), load);
27837						position++;
27838					}
27839				}
27840			}, this)
27841		};
27842
27843		// set the default options
27844		this._core.options = $.extend({}, Lazy.Defaults, this._core.options);
27845
27846		// register event handler
27847		this._core.$element.on(this._handlers);
27848	};
27849
27850	/**
27851	 * Default options.
27852	 * @public
27853	 */
27854	Lazy.Defaults = {
27855		lazyLoad: false,
27856		lazyLoadEager: 0
27857	};
27858
27859	/**
27860	 * Loads all resources of an item at the specified position.
27861	 * @param {Number} position - The absolute position of the item.
27862	 * @protected
27863	 */
27864	Lazy.prototype.load = function(position) {
27865		var $item = this._core.$stage.children().eq(position),
27866			$elements = $item && $item.find('.owl-lazy');
27867
27868		if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
27869			return;
27870		}
27871
27872		$elements.each($.proxy(function(index, element) {
27873			var $element = $(element), image,
27874                url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src') || $element.attr('data-srcset');
27875
27876			this._core.trigger('load', { element: $element, url: url }, 'lazy');
27877
27878			if ($element.is('img')) {
27879				$element.one('load.owl.lazy', $.proxy(function() {
27880					$element.css('opacity', 1);
27881					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
27882				}, this)).attr('src', url);
27883            } else if ($element.is('source')) {
27884                $element.one('load.owl.lazy', $.proxy(function() {
27885                    this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
27886                }, this)).attr('srcset', url);
27887			} else {
27888				image = new Image();
27889				image.onload = $.proxy(function() {
27890					$element.css({
27891						'background-image': 'url("' + url + '")',
27892						'opacity': '1'
27893					});
27894					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
27895				}, this);
27896				image.src = url;
27897			}
27898		}, this));
27899
27900		this._loaded.push($item.get(0));
27901	};
27902
27903	/**
27904	 * Destroys the plugin.
27905	 * @public
27906	 */
27907	Lazy.prototype.destroy = function() {
27908		var handler, property;
27909
27910		for (handler in this.handlers) {
27911			this._core.$element.off(handler, this.handlers[handler]);
27912		}
27913		for (property in Object.getOwnPropertyNames(this)) {
27914			typeof this[property] != 'function' && (this[property] = null);
27915		}
27916	};
27917
27918	$.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;
27919
27920})(window.Zepto || window.jQuery, window, document);
27921
27922/**
27923 * AutoHeight Plugin
27924 * @version 2.3.4
27925 * @author Bartosz Wojciechowski
27926 * @author David Deutsch
27927 * @license The MIT License (MIT)
27928 */
27929;(function($, window, document, undefined) {
27930
27931	/**
27932	 * Creates the auto height plugin.
27933	 * @class The Auto Height Plugin
27934	 * @param {Owl} carousel - The Owl Carousel
27935	 */
27936	var AutoHeight = function(carousel) {
27937		/**
27938		 * Reference to the core.
27939		 * @protected
27940		 * @type {Owl}
27941		 */
27942		this._core = carousel;
27943
27944		this._previousHeight = null;
27945
27946		/**
27947		 * All event handlers.
27948		 * @protected
27949		 * @type {Object}
27950		 */
27951		this._handlers = {
27952			'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) {
27953				if (e.namespace && this._core.settings.autoHeight) {
27954					this.update();
27955				}
27956			}, this),
27957			'changed.owl.carousel': $.proxy(function(e) {
27958				if (e.namespace && this._core.settings.autoHeight && e.property.name === 'position'){
27959					this.update();
27960				}
27961			}, this),
27962			'loaded.owl.lazy': $.proxy(function(e) {
27963				if (e.namespace && this._core.settings.autoHeight
27964					&& e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) {
27965					this.update();
27966				}
27967			}, this)
27968		};
27969
27970		// set default options
27971		this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);
27972
27973		// register event handlers
27974		this._core.$element.on(this._handlers);
27975		this._intervalId = null;
27976		var refThis = this;
27977
27978		// These changes have been taken from a PR by gavrochelegnou proposed in #1575
27979		// and have been made compatible with the latest jQuery version
27980		$(window).on('load', function() {
27981			if (refThis._core.settings.autoHeight) {
27982				refThis.update();
27983			}
27984		});
27985
27986		// Autoresize the height of the carousel when window is resized
27987		// When carousel has images, the height is dependent on the width
27988		// and should also change on resize
27989		$(window).resize(function() {
27990			if (refThis._core.settings.autoHeight) {
27991				if (refThis._intervalId != null) {
27992					clearTimeout(refThis._intervalId);
27993				}
27994
27995				refThis._intervalId = setTimeout(function() {
27996					refThis.update();
27997				}, 250);
27998			}
27999		});
28000
28001	};
28002
28003	/**
28004	 * Default options.
28005	 * @public
28006	 */
28007	AutoHeight.Defaults = {
28008		autoHeight: false,
28009		autoHeightClass: 'owl-height'
28010	};
28011
28012	/**
28013	 * Updates the view.
28014	 */
28015	AutoHeight.prototype.update = function() {
28016		var start = this._core._current,
28017			end = start + this._core.settings.items,
28018			lazyLoadEnabled = this._core.settings.lazyLoad,
28019			visible = this._core.$stage.children().toArray().slice(start, end),
28020			heights = [],
28021			maxheight = 0;
28022
28023		$.each(visible, function(index, item) {
28024			heights.push($(item).height());
28025		});
28026
28027		maxheight = Math.max.apply(null, heights);
28028
28029		if (maxheight <= 1 && lazyLoadEnabled && this._previousHeight) {
28030			maxheight = this._previousHeight;
28031		}
28032
28033		this._previousHeight = maxheight;
28034
28035		this._core.$stage.parent()
28036			.height(maxheight)
28037			.addClass(this._core.settings.autoHeightClass);
28038	};
28039
28040	AutoHeight.prototype.destroy = function() {
28041		var handler, property;
28042
28043		for (handler in this._handlers) {
28044			this._core.$element.off(handler, this._handlers[handler]);
28045		}
28046		for (property in Object.getOwnPropertyNames(this)) {
28047			typeof this[property] !== 'function' && (this[property] = null);
28048		}
28049	};
28050
28051	$.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;
28052
28053})(window.Zepto || window.jQuery, window, document);
28054
28055/**
28056 * Video Plugin
28057 * @version 2.3.4
28058 * @author Bartosz Wojciechowski
28059 * @author David Deutsch
28060 * @license The MIT License (MIT)
28061 */
28062;(function($, window, document, undefined) {
28063
28064	/**
28065	 * Creates the video plugin.
28066	 * @class The Video Plugin
28067	 * @param {Owl} carousel - The Owl Carousel
vendor: 5,347 bytes, lines 28068-28265
28068	 */
28069	var Video = function(carousel) {
28070		/**
28071		 * Reference to the core.
28072		 * @protected
28073		 * @type {Owl}
28074		 */
28075		this._core = carousel;
28076
28077		/**
28078		 * Cache all video URLs.
28079		 * @protected
28080		 * @type {Object}
28081		 */
28082		this._videos = {};
28083
28084		/**
28085		 * Current playing item.
28086		 * @protected
28087		 * @type {jQuery}
28088		 */
28089		this._playing = null;
28090
28091		/**
28092		 * All event handlers.
28093		 * @todo The cloned content removale is too late
28094		 * @protected
28095		 * @type {Object}
28096		 */
28097		this._handlers = {
28098			'initialized.owl.carousel': $.proxy(function(e) {
28099				if (e.namespace) {
28100					this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] });
28101				}
28102			}, this),
28103			'resize.owl.carousel': $.proxy(function(e) {
28104				if (e.namespace && this._core.settings.video && this.isInFullScreen()) {
28105					e.preventDefault();
28106				}
28107			}, this),
28108			'refreshed.owl.carousel': $.proxy(function(e) {
28109				if (e.namespace && this._core.is('resizing')) {
28110					this._core.$stage.find('.cloned .owl-video-frame').remove();
28111				}
28112			}, this),
28113			'changed.owl.carousel': $.proxy(function(e) {
28114				if (e.namespace && e.property.name === 'position' && this._playing) {
28115					this.stop();
28116				}
28117			}, this),
28118			'prepared.owl.carousel': $.proxy(function(e) {
28119				if (!e.namespace) {
28120					return;
28121				}
28122
28123				var $element = $(e.content).find('.owl-video');
28124
28125				if ($element.length) {
28126					$element.css('display', 'none');
28127					this.fetch($element, $(e.content));
28128				}
28129			}, this)
28130		};
28131
28132		// set default options
28133		this._core.options = $.extend({}, Video.Defaults, this._core.options);
28134
28135		// register event handlers
28136		this._core.$element.on(this._handlers);
28137
28138		this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
28139			this.play(e);
28140		}, this));
28141	};
28142
28143	/**
28144	 * Default options.
28145	 * @public
28146	 */
28147	Video.Defaults = {
28148		video: false,
28149		videoHeight: false,
28150		videoWidth: false
28151	};
28152
28153	/**
28154	 * Gets the video ID and the type (YouTube/Vimeo/vzaar only).
28155	 * @protected
28156	 * @param {jQuery} target - The target containing the video data.
28157	 * @param {jQuery} item - The item containing the video.
28158	 */
28159	Video.prototype.fetch = function(target, item) {
28160			var type = (function() {
28161					if (target.attr('data-vimeo-id')) {
28162						return 'vimeo';
28163					} else if (target.attr('data-vzaar-id')) {
28164						return 'vzaar'
28165					} else {
28166						return 'youtube';
28167					}
28168				})(),
28169				id = target.attr('data-vimeo-id') || target.attr('data-youtube-id') || target.attr('data-vzaar-id'),
28170				width = target.attr('data-width') || this._core.settings.videoWidth,
28171				height = target.attr('data-height') || this._core.settings.videoHeight,
28172				url = target.attr('href');
28173
28174		if (url) {
28175
28176			/*
28177					Parses the id's out of the following urls (and probably more):
28178					https://www.youtube.com/watch?v=:id
28179					https://youtu.be/:id
28180					https://vimeo.com/:id
28181					https://vimeo.com/channels/:channel/:id
28182					https://vimeo.com/groups/:group/videos/:id
28183					https://app.vzaar.com/videos/:id
28184
28185					Visual example: https://regexper.com/#(http%3A%7Chttps%3A%7C)%5C%2F%5C%2F(player.%7Cwww.%7Capp.)%3F(vimeo%5C.com%7Cyoutu(be%5C.com%7C%5C.be%7Cbe%5C.googleapis%5C.com)%7Cvzaar%5C.com)%5C%2F(video%5C%2F%7Cvideos%5C%2F%7Cembed%5C%2F%7Cchannels%5C%2F.%2B%5C%2F%7Cgroups%5C%2F.%2B%5C%2F%7Cwatch%5C%3Fv%3D%7Cv%5C%2F)%3F(%5BA-Za-z0-9._%25-%5D*)(%5C%26%5CS%2B)%3F
28186			*/
28187
28188			id = url.match(/(http:|https:|)\/\/(player.|www.|app.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com|be\-nocookie\.com)|vzaar\.com)\/(video\/|videos\/|embed\/|channels\/.+\/|groups\/.+\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/);
28189
28190			if (id[3].indexOf('youtu') > -1) {
28191				type = 'youtube';
28192			} else if (id[3].indexOf('vimeo') > -1) {
28193				type = 'vimeo';
28194			} else if (id[3].indexOf('vzaar') > -1) {
28195				type = 'vzaar';
28196			} else {
28197				throw new Error('Video URL not supported.');
28198			}
28199			id = id[6];
28200		} else {
28201			throw new Error('Missing video URL.');
28202		}
28203
28204		this._videos[url] = {
28205			type: type,
28206			id: id,
28207			width: width,
28208			height: height
28209		};
28210
28211		item.attr('data-video', url);
28212
28213		this.thumbnail(target, this._videos[url]);
28214	};
28215
28216	/**
28217	 * Creates video thumbnail.
28218	 * @protected
28219	 * @param {jQuery} target - The target containing the video data.
28220	 * @param {Object} info - The video info object.
28221	 * @see `fetch`
28222	 */
28223	Video.prototype.thumbnail = function(target, video) {
28224		var tnLink,
28225			icon,
28226			path,
28227			dimensions = video.width && video.height ? 'width:' + video.width + 'px;height:' + video.height + 'px;' : '',
28228			customTn = target.find('img'),
28229			srcType = 'src',
28230			lazyClass = '',
28231			settings = this._core.settings,
28232			create = function(path) {
28233				icon = '<div class="owl-video-play-icon"></div>';
28234
28235				if (settings.lazyLoad) {
28236					tnLink = $('<div/>',{
28237						"class": 'owl-video-tn ' + lazyClass,
28238						"srcType": path
28239					});
28240				} else {
28241					tnLink = $( '<div/>', {
28242						"class": "owl-video-tn",
28243						"style": 'opacity:1;background-image:url(' + path + ')'
28244					});
28245				}
28246				target.after(tnLink);
28247				target.after(icon);
28248			};
28249
28250		// wrap video content into owl-video-wrapper div
28251		target.wrap( $( '<div/>', {
28252			"class": "owl-video-wrapper",
28253			"style": dimensions
28254		}));
28255
28256		if (this._core.settings.lazyLoad) {
28257			srcType = 'data-src';
28258			lazyClass = 'owl-lazy';
28259		}
28260
28261		// custom thumbnail
28262		if (customTn.length) {
28263			create(customTn.attr(srcType));
28264			customTn.remove();
28265			return false;
vendor: 15,908 bytes, lines 28266-28903
28266		}
28267
28268		if (video.type === 'youtube') {
28269			path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
28270			create(path);
28271		} else if (video.type === 'vimeo') {
28272			$.ajax({
28273				type: 'GET',
28274				url: '//vimeo.com/api/v2/video/' + video.id + '.json',
28275				jsonp: 'callback',
28276				dataType: 'jsonp',
28277				success: function(data) {
28278					path = data[0].thumbnail_large;
28279					create(path);
28280				}
28281			});
28282		} else if (video.type === 'vzaar') {
28283			$.ajax({
28284				type: 'GET',
28285				url: '//vzaar.com/api/videos/' + video.id + '.json',
28286				jsonp: 'callback',
28287				dataType: 'jsonp',
28288				success: function(data) {
28289					path = data.framegrab_url;
28290					create(path);
28291				}
28292			});
28293		}
28294	};
28295
28296	/**
28297	 * Stops the current video.
28298	 * @public
28299	 */
28300	Video.prototype.stop = function() {
28301		this._core.trigger('stop', null, 'video');
28302		this._playing.find('.owl-video-frame').remove();
28303		this._playing.removeClass('owl-video-playing');
28304		this._playing = null;
28305		this._core.leave('playing');
28306		this._core.trigger('stopped', null, 'video');
28307	};
28308
28309	/**
28310	 * Starts the current video.
28311	 * @public
28312	 * @param {Event} event - The event arguments.
28313	 */
28314	Video.prototype.play = function(event) {
28315		var target = $(event.target),
28316			item = target.closest('.' + this._core.settings.itemClass),
28317			video = this._videos[item.attr('data-video')],
28318			width = video.width || '100%',
28319			height = video.height || this._core.$stage.height(),
28320			html,
28321			iframe;
28322
28323		if (this._playing) {
28324			return;
28325		}
28326
28327		this._core.enter('playing');
28328		this._core.trigger('play', null, 'video');
28329
28330		item = this._core.items(this._core.relative(item.index()));
28331
28332		this._core.reset(item.index());
28333
28334		html = $( '<iframe frameborder="0" allowfullscreen mozallowfullscreen webkitAllowFullScreen ></iframe>' );
28335		html.attr( 'height', height );
28336		html.attr( 'width', width );
28337		if (video.type === 'youtube') {
28338			html.attr( 'src', '//www.youtube.com/embed/' + video.id + '?autoplay=1&rel=0&v=' + video.id );
28339		} else if (video.type === 'vimeo') {
28340			html.attr( 'src', '//player.vimeo.com/video/' + video.id + '?autoplay=1' );
28341		} else if (video.type === 'vzaar') {
28342			html.attr( 'src', '//view.vzaar.com/' + video.id + '/player?autoplay=true' );
28343		}
28344
28345		iframe = $(html).wrap( '<div class="owl-video-frame" />' ).insertAfter(item.find('.owl-video'));
28346
28347		this._playing = item.addClass('owl-video-playing');
28348	};
28349
28350	/**
28351	 * Checks whether an video is currently in full screen mode or not.
28352	 * @todo Bad style because looks like a readonly method but changes members.
28353	 * @protected
28354	 * @returns {Boolean}
28355	 */
28356	Video.prototype.isInFullScreen = function() {
28357		var element = document.fullscreenElement || document.mozFullScreenElement ||
28358				document.webkitFullscreenElement;
28359
28360		return element && $(element).parent().hasClass('owl-video-frame');
28361	};
28362
28363	/**
28364	 * Destroys the plugin.
28365	 */
28366	Video.prototype.destroy = function() {
28367		var handler, property;
28368
28369		this._core.$element.off('click.owl.video');
28370
28371		for (handler in this._handlers) {
28372			this._core.$element.off(handler, this._handlers[handler]);
28373		}
28374		for (property in Object.getOwnPropertyNames(this)) {
28375			typeof this[property] != 'function' && (this[property] = null);
28376		}
28377	};
28378
28379	$.fn.owlCarousel.Constructor.Plugins.Video = Video;
28380
28381})(window.Zepto || window.jQuery, window, document);
28382
28383/**
28384 * Animate Plugin
28385 * @version 2.3.4
28386 * @author Bartosz Wojciechowski
28387 * @author David Deutsch
28388 * @license The MIT License (MIT)
28389 */
28390;(function($, window, document, undefined) {
28391
28392	/**
28393	 * Creates the animate plugin.
28394	 * @class The Navigation Plugin
28395	 * @param {Owl} scope - The Owl Carousel
28396	 */
28397	var Animate = function(scope) {
28398		this.core = scope;
28399		this.core.options = $.extend({}, Animate.Defaults, this.core.options);
28400		this.swapping = true;
28401		this.previous = undefined;
28402		this.next = undefined;
28403
28404		this.handlers = {
28405			'change.owl.carousel': $.proxy(function(e) {
28406				if (e.namespace && e.property.name == 'position') {
28407					this.previous = this.core.current();
28408					this.next = e.property.value;
28409				}
28410			}, this),
28411			'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
28412				if (e.namespace) {
28413					this.swapping = e.type == 'translated';
28414				}
28415			}, this),
28416			'translate.owl.carousel': $.proxy(function(e) {
28417				if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
28418					this.swap();
28419				}
28420			}, this)
28421		};
28422
28423		this.core.$element.on(this.handlers);
28424	};
28425
28426	/**
28427	 * Default options.
28428	 * @public
28429	 */
28430	Animate.Defaults = {
28431		animateOut: false,
28432		animateIn: false
28433	};
28434
28435	/**
28436	 * Toggles the animation classes whenever an translations starts.
28437	 * @protected
28438	 * @returns {Boolean|undefined}
28439	 */
28440	Animate.prototype.swap = function() {
28441
28442		if (this.core.settings.items !== 1) {
28443			return;
28444		}
28445
28446		if (!$.support.animation || !$.support.transition) {
28447			return;
28448		}
28449
28450		this.core.speed(0);
28451
28452		var left,
28453			clear = $.proxy(this.clear, this),
28454			previous = this.core.$stage.children().eq(this.previous),
28455			next = this.core.$stage.children().eq(this.next),
28456			incoming = this.core.settings.animateIn,
28457			outgoing = this.core.settings.animateOut;
28458
28459		if (this.core.current() === this.previous) {
28460			return;
28461		}
28462
28463		if (outgoing) {
28464			left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
28465			previous.one($.support.animation.end, clear)
28466				.css( { 'left': left + 'px' } )
28467				.addClass('animated owl-animated-out')
28468				.addClass(outgoing);
28469		}
28470
28471		if (incoming) {
28472			next.one($.support.animation.end, clear)
28473				.addClass('animated owl-animated-in')
28474				.addClass(incoming);
28475		}
28476	};
28477
28478	Animate.prototype.clear = function(e) {
28479		$(e.target).css( { 'left': '' } )
28480			.removeClass('animated owl-animated-out owl-animated-in')
28481			.removeClass(this.core.settings.animateIn)
28482			.removeClass(this.core.settings.animateOut);
28483		this.core.onTransitionEnd();
28484	};
28485
28486	/**
28487	 * Destroys the plugin.
28488	 * @public
28489	 */
28490	Animate.prototype.destroy = function() {
28491		var handler, property;
28492
28493		for (handler in this.handlers) {
28494			this.core.$element.off(handler, this.handlers[handler]);
28495		}
28496		for (property in Object.getOwnPropertyNames(this)) {
28497			typeof this[property] != 'function' && (this[property] = null);
28498		}
28499	};
28500
28501	$.fn.owlCarousel.Constructor.Plugins.Animate = Animate;
28502
28503})(window.Zepto || window.jQuery, window, document);
28504
28505/**
28506 * Autoplay Plugin
28507 * @version 2.3.4
28508 * @author Bartosz Wojciechowski
28509 * @author Artus Kolanowski
28510 * @author David Deutsch
28511 * @author Tom De Caluwé
28512 * @license The MIT License (MIT)
28513 */
28514;(function($, window, document, undefined) {
28515
28516	/**
28517	 * Creates the autoplay plugin.
28518	 * @class The Autoplay Plugin
28519	 * @param {Owl} scope - The Owl Carousel
28520	 */
28521	var Autoplay = function(carousel) {
28522		/**
28523		 * Reference to the core.
28524		 * @protected
28525		 * @type {Owl}
28526		 */
28527		this._core = carousel;
28528
28529		/**
28530		 * The autoplay timeout id.
28531		 * @type {Number}
28532		 */
28533		this._call = null;
28534
28535		/**
28536		 * Depending on the state of the plugin, this variable contains either
28537		 * the start time of the timer or the current timer value if it's
28538		 * paused. Since we start in a paused state we initialize the timer
28539		 * value.
28540		 * @type {Number}
28541		 */
28542		this._time = 0;
28543
28544		/**
28545		 * Stores the timeout currently used.
28546		 * @type {Number}
28547		 */
28548		this._timeout = 0;
28549
28550		/**
28551		 * Indicates whenever the autoplay is paused.
28552		 * @type {Boolean}
28553		 */
28554		this._paused = true;
28555
28556		/**
28557		 * All event handlers.
28558		 * @protected
28559		 * @type {Object}
28560		 */
28561		this._handlers = {
28562			'changed.owl.carousel': $.proxy(function(e) {
28563				if (e.namespace && e.property.name === 'settings') {
28564					if (this._core.settings.autoplay) {
28565						this.play();
28566					} else {
28567						this.stop();
28568					}
28569				} else if (e.namespace && e.property.name === 'position' && this._paused) {
28570					// Reset the timer. This code is triggered when the position
28571					// of the carousel was changed through user interaction.
28572					this._time = 0;
28573				}
28574			}, this),
28575			'initialized.owl.carousel': $.proxy(function(e) {
28576				if (e.namespace && this._core.settings.autoplay) {
28577					this.play();
28578				}
28579			}, this),
28580			'play.owl.autoplay': $.proxy(function(e, t, s) {
28581				if (e.namespace) {
28582					this.play(t, s);
28583				}
28584			}, this),
28585			'stop.owl.autoplay': $.proxy(function(e) {
28586				if (e.namespace) {
28587					this.stop();
28588				}
28589			}, this),
28590			'mouseover.owl.autoplay': $.proxy(function() {
28591				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
28592					this.pause();
28593				}
28594			}, this),
28595			'mouseleave.owl.autoplay': $.proxy(function() {
28596				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
28597					this.play();
28598				}
28599			}, this),
28600			'touchstart.owl.core': $.proxy(function() {
28601				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
28602					this.pause();
28603				}
28604			}, this),
28605			'touchend.owl.core': $.proxy(function() {
28606				if (this._core.settings.autoplayHoverPause) {
28607					this.play();
28608				}
28609			}, this)
28610		};
28611
28612		// register event handlers
28613		this._core.$element.on(this._handlers);
28614
28615		// set default options
28616		this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
28617	};
28618
28619	/**
28620	 * Default options.
28621	 * @public
28622	 */
28623	Autoplay.Defaults = {
28624		autoplay: false,
28625		autoplayTimeout: 5000,
28626		autoplayHoverPause: false,
28627		autoplaySpeed: false
28628	};
28629
28630	/**
28631	 * Transition to the next slide and set a timeout for the next transition.
28632	 * @private
28633	 * @param {Number} [speed] - The animation speed for the animations.
28634	 */
28635	Autoplay.prototype._next = function(speed) {
28636		this._call = window.setTimeout(
28637			$.proxy(this._next, this, speed),
28638			this._timeout * (Math.round(this.read() / this._timeout) + 1) - this.read()
28639		);
28640
28641		if (this._core.is('interacting') || document.hidden) {
28642			return;
28643		}
28644		this._core.next(speed || this._core.settings.autoplaySpeed);
28645	}
28646
28647	/**
28648	 * Reads the current timer value when the timer is playing.
28649	 * @public
28650	 */
28651	Autoplay.prototype.read = function() {
28652		return new Date().getTime() - this._time;
28653	};
28654
28655	/**
28656	 * Starts the autoplay.
28657	 * @public
28658	 * @param {Number} [timeout] - The interval before the next animation starts.
28659	 * @param {Number} [speed] - The animation speed for the animations.
28660	 */
28661	Autoplay.prototype.play = function(timeout, speed) {
28662		var elapsed;
28663
28664		if (!this._core.is('rotating')) {
28665			this._core.enter('rotating');
28666		}
28667
28668		timeout = timeout || this._core.settings.autoplayTimeout;
28669
28670		// Calculate the elapsed time since the last transition. If the carousel
28671		// wasn't playing this calculation will yield zero.
28672		elapsed = Math.min(this._time % (this._timeout || timeout), timeout);
28673
28674		if (this._paused) {
28675			// Start the clock.
28676			this._time = this.read();
28677			this._paused = false;
28678		} else {
28679			// Clear the active timeout to allow replacement.
28680			window.clearTimeout(this._call);
28681		}
28682
28683		// Adjust the origin of the timer to match the new timeout value.
28684		this._time += this.read() % timeout - elapsed;
28685
28686		this._timeout = timeout;
28687		this._call = window.setTimeout($.proxy(this._next, this, speed), timeout - elapsed);
28688	};
28689
28690	/**
28691	 * Stops the autoplay.
28692	 * @public
28693	 */
28694	Autoplay.prototype.stop = function() {
28695		if (this._core.is('rotating')) {
28696			// Reset the clock.
28697			this._time = 0;
28698			this._paused = true;
28699
28700			window.clearTimeout(this._call);
28701			this._core.leave('rotating');
28702		}
28703	};
28704
28705	/**
28706	 * Pauses the autoplay.
28707	 * @public
28708	 */
28709	Autoplay.prototype.pause = function() {
28710		if (this._core.is('rotating') && !this._paused) {
28711			// Pause the clock.
28712			this._time = this.read();
28713			this._paused = true;
28714
28715			window.clearTimeout(this._call);
28716		}
28717	};
28718
28719	/**
28720	 * Destroys the plugin.
28721	 */
28722	Autoplay.prototype.destroy = function() {
28723		var handler, property;
28724
28725		this.stop();
28726
28727		for (handler in this._handlers) {
28728			this._core.$element.off(handler, this._handlers[handler]);
28729		}
28730		for (property in Object.getOwnPropertyNames(this)) {
28731			typeof this[property] != 'function' && (this[property] = null);
28732		}
28733	};
28734
28735	$.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;
28736
28737})(window.Zepto || window.jQuery, window, document);
28738
28739/**
28740 * Navigation Plugin
28741 * @version 2.3.4
28742 * @author Artus Kolanowski
28743 * @author David Deutsch
28744 * @license The MIT License (MIT)
28745 */
28746;(function($, window, document, undefined) {
28747	'use strict';
28748
28749	/**
28750	 * Creates the navigation plugin.
28751	 * @class The Navigation Plugin
28752	 * @param {Owl} carousel - The Owl Carousel.
28753	 */
28754	var Navigation = function(carousel) {
28755		/**
28756		 * Reference to the core.
28757		 * @protected
28758		 * @type {Owl}
28759		 */
28760		this._core = carousel;
28761
28762		/**
28763		 * Indicates whether the plugin is initialized or not.
28764		 * @protected
28765		 * @type {Boolean}
28766		 */
28767		this._initialized = false;
28768
28769		/**
28770		 * The current paging indexes.
28771		 * @protected
28772		 * @type {Array}
28773		 */
28774		this._pages = [];
28775
28776		/**
28777		 * All DOM elements of the user interface.
28778		 * @protected
28779		 * @type {Object}
28780		 */
28781		this._controls = {};
28782
28783		/**
28784		 * Markup for an indicator.
28785		 * @protected
28786		 * @type {Array.<String>}
28787		 */
28788		this._templates = [];
28789
28790		/**
28791		 * The carousel element.
28792		 * @type {jQuery}
28793		 */
28794		this.$element = this._core.$element;
28795
28796		/**
28797		 * Overridden methods of the carousel.
28798		 * @protected
28799		 * @type {Object}
28800		 */
28801		this._overrides = {
28802			next: this._core.next,
28803			prev: this._core.prev,
28804			to: this._core.to
28805		};
28806
28807		/**
28808		 * All event handlers.
28809		 * @protected
28810		 * @type {Object}
28811		 */
28812		this._handlers = {
28813			'prepared.owl.carousel': $.proxy(function(e) {
28814				if (e.namespace && this._core.settings.dotsData) {
28815					this._templates.push('<div class="' + this._core.settings.dotClass + '">' +
28816						$(e.content).find('[data-dot]').addBack('[data-dot]').attr('data-dot') + '</div>');
28817				}
28818			}, this),
28819			'added.owl.carousel': $.proxy(function(e) {
28820				if (e.namespace && this._core.settings.dotsData) {
28821					this._templates.splice(e.position, 0, this._templates.pop());
28822				}
28823			}, this),
28824			'remove.owl.carousel': $.proxy(function(e) {
28825				if (e.namespace && this._core.settings.dotsData) {
28826					this._templates.splice(e.position, 1);
28827				}
28828			}, this),
28829			'changed.owl.carousel': $.proxy(function(e) {
28830				if (e.namespace && e.property.name == 'position') {
28831					this.draw();
28832				}
28833			}, this),
28834			'initialized.owl.carousel': $.proxy(function(e) {
28835				if (e.namespace && !this._initialized) {
28836					this._core.trigger('initialize', null, 'navigation');
28837					this.initialize();
28838					this.update();
28839					this.draw();
28840					this._initialized = true;
28841					this._core.trigger('initialized', null, 'navigation');
28842				}
28843			}, this),
28844			'refreshed.owl.carousel': $.proxy(function(e) {
28845				if (e.namespace && this._initialized) {
28846					this._core.trigger('refresh', null, 'navigation');
28847					this.update();
28848					this.draw();
28849					this._core.trigger('refreshed', null, 'navigation');
28850				}
28851			}, this)
28852		};
28853
28854		// set default options
28855		this._core.options = $.extend({}, Navigation.Defaults, this._core.options);
28856
28857		// register event handlers
28858		this.$element.on(this._handlers);
28859	};
28860
28861	/**
28862	 * Default options.
28863	 * @public
28864	 * @todo Rename `slideBy` to `navBy`
28865	 */
28866	Navigation.Defaults = {
28867		nav: false,
28868		navText: [
28869			'<span aria-label="' + 'Previous' + '">&#x2039;</span>',
28870			'<span aria-label="' + 'Next' + '">&#x203a;</span>'
28871		],
28872		navSpeed: false,
28873		navElement: 'button type="button" role="presentation"',
28874		navContainer: false,
28875		navContainerClass: 'owl-nav',
28876		navClass: [
28877			'owl-prev',
28878			'owl-next'
28879		],
28880		slideBy: 1,
28881		dotClass: 'owl-dot',
28882		dotsClass: 'owl-dots',
28883		dots: true,
28884		dotsEach: false,
28885		dotsData: false,
28886		dotsSpeed: false,
28887		dotsContainer: false
28888	};
28889
28890	/**
28891	 * Initializes the layout of the plugin and extends the carousel.
28892	 * @protected
28893	 */
28894	Navigation.prototype.initialize = function() {
28895		var override,
28896			settings = this._core.settings;
28897
28898		// create DOM structure for relative navigation
28899		this._controls.$relative = (settings.navContainer ? $(settings.navContainer)
28900			: $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled');
28901
28902		this._controls.$previous = $('<' + settings.navElement + '>')
28903			.addClass(settings.navClass[0])
vendor: 4,756 bytes, lines 28904-29065
28904			.html(settings.navText[0])
28905			.prependTo(this._controls.$relative)
28906			.on('click', $.proxy(function(e) {
28907				this.prev(settings.navSpeed);
28908			}, this));
28909		this._controls.$next = $('<' + settings.navElement + '>')
28910			.addClass(settings.navClass[1])
28911			.html(settings.navText[1])
28912			.appendTo(this._controls.$relative)
28913			.on('click', $.proxy(function(e) {
28914				this.next(settings.navSpeed);
28915			}, this));
28916
28917		// create DOM structure for absolute navigation
28918		if (!settings.dotsData) {
28919			this._templates = [ $('<button role="button">')
28920				.addClass(settings.dotClass)
28921				.append($('<span>'))
28922				.prop('outerHTML') ];
28923		}
28924
28925		this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer)
28926			: $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled');
28927
28928		this._controls.$absolute.on('click', 'button', $.proxy(function(e) {
28929			var index = $(e.target).parent().is(this._controls.$absolute)
28930				? $(e.target).index() : $(e.target).parent().index();
28931
28932			e.preventDefault();
28933
28934			this.to(index, settings.dotsSpeed);
28935		}, this));
28936
28937		/*$el.on('focusin', function() {
28938			$(document).off(".carousel");
28939
28940			$(document).on('keydown.carousel', function(e) {
28941				if(e.keyCode == 37) {
28942					$el.trigger('prev.owl')
28943				}
28944				if(e.keyCode == 39) {
28945					$el.trigger('next.owl')
28946				}
28947			});
28948		});*/
28949
28950		// override public methods of the carousel
28951		for (override in this._overrides) {
28952			this._core[override] = $.proxy(this[override], this);
28953		}
28954	};
28955
28956	/**
28957	 * Destroys the plugin.
28958	 * @protected
28959	 */
28960	Navigation.prototype.destroy = function() {
28961		var handler, control, property, override, settings;
28962		settings = this._core.settings;
28963
28964		for (handler in this._handlers) {
28965			this.$element.off(handler, this._handlers[handler]);
28966		}
28967		for (control in this._controls) {
28968			if (control === '$relative' && settings.navContainer) {
28969				this._controls[control].html('');
28970			} else {
28971				this._controls[control].remove();
28972			}
28973		}
28974		for (override in this.overides) {
28975			this._core[override] = this._overrides[override];
28976		}
28977		for (property in Object.getOwnPropertyNames(this)) {
28978			typeof this[property] != 'function' && (this[property] = null);
28979		}
28980	};
28981
28982	/**
28983	 * Updates the internal state.
28984	 * @protected
28985	 */
28986	Navigation.prototype.update = function() {
28987		var i, j, k,
28988			lower = this._core.clones().length / 2,
28989			upper = lower + this._core.items().length,
28990			maximum = this._core.maximum(true),
28991			settings = this._core.settings,
28992			size = settings.center || settings.autoWidth || settings.dotsData
28993				? 1 : settings.dotsEach || settings.items;
28994
28995		if (settings.slideBy !== 'page') {
28996			settings.slideBy = Math.min(settings.slideBy, settings.items);
28997		}
28998
28999		if (settings.dots || settings.slideBy == 'page') {
29000			this._pages = [];
29001
29002			for (i = lower, j = 0, k = 0; i < upper; i++) {
29003				if (j >= size || j === 0) {
29004					this._pages.push({
29005						start: Math.min(maximum, i - lower),
29006						end: i - lower + size - 1
29007					});
29008					if (Math.min(maximum, i - lower) === maximum) {
29009						break;
29010					}
29011					j = 0, ++k;
29012				}
29013				j += this._core.mergers(this._core.relative(i));
29014			}
29015		}
29016	};
29017
29018	/**
29019	 * Draws the user interface.
29020	 * @todo The option `dotsData` wont work.
29021	 * @protected
29022	 */
29023	Navigation.prototype.draw = function() {
29024		var difference,
29025			settings = this._core.settings,
29026			disabled = this._core.items().length <= settings.items,
29027			index = this._core.relative(this._core.current()),
29028			loop = settings.loop || settings.rewind;
29029
29030		this._controls.$relative.toggleClass('disabled', !settings.nav || disabled);
29031
29032		if (settings.nav) {
29033			this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true));
29034			this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true));
29035		}
29036
29037		this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled);
29038
29039		if (settings.dots) {
29040			difference = this._pages.length - this._controls.$absolute.children().length;
29041
29042			if (settings.dotsData && difference !== 0) {
29043				this._controls.$absolute.html(this._templates.join(''));
29044			} else if (difference > 0) {
29045				this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0]));
29046			} else if (difference < 0) {
29047				this._controls.$absolute.children().slice(difference).remove();
29048			}
29049
29050			this._controls.$absolute.find('.active').removeClass('active');
29051			this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active');
29052		}
29053	};
29054
29055	/**
29056	 * Extends event data.
29057	 * @protected
29058	 * @param {Event} event - The event object which gets thrown.
29059	 */
29060	Navigation.prototype.onTrigger = function(event) {
29061		var settings = this._core.settings;
29062
29063		event.page = {
29064			index: $.inArray(this.current(), this._pages),
29065			count: this._pages.length,
vendor: 7,284 bytes, lines 29066-29351
29066			size: settings && (settings.center || settings.autoWidth || settings.dotsData
29067				? 1 : settings.dotsEach || settings.items)
29068		};
29069	};
29070
29071	/**
29072	 * Gets the current page position of the carousel.
29073	 * @protected
29074	 * @returns {Number}
29075	 */
29076	Navigation.prototype.current = function() {
29077		var current = this._core.relative(this._core.current());
29078		return $.grep(this._pages, $.proxy(function(page, index) {
29079			return page.start <= current && page.end >= current;
29080		}, this)).pop();
29081	};
29082
29083	/**
29084	 * Gets the current succesor/predecessor position.
29085	 * @protected
29086	 * @returns {Number}
29087	 */
29088	Navigation.prototype.getPosition = function(successor) {
29089		var position, length,
29090			settings = this._core.settings;
29091
29092		if (settings.slideBy == 'page') {
29093			position = $.inArray(this.current(), this._pages);
29094			length = this._pages.length;
29095			successor ? ++position : --position;
29096			position = this._pages[((position % length) + length) % length].start;
29097		} else {
29098			position = this._core.relative(this._core.current());
29099			length = this._core.items().length;
29100			successor ? position += settings.slideBy : position -= settings.slideBy;
29101		}
29102
29103		return position;
29104	};
29105
29106	/**
29107	 * Slides to the next item or page.
29108	 * @public
29109	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
29110	 */
29111	Navigation.prototype.next = function(speed) {
29112		$.proxy(this._overrides.to, this._core)(this.getPosition(true), speed);
29113	};
29114
29115	/**
29116	 * Slides to the previous item or page.
29117	 * @public
29118	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
29119	 */
29120	Navigation.prototype.prev = function(speed) {
29121		$.proxy(this._overrides.to, this._core)(this.getPosition(false), speed);
29122	};
29123
29124	/**
29125	 * Slides to the specified item or page.
29126	 * @public
29127	 * @param {Number} position - The position of the item or page.
29128	 * @param {Number} [speed] - The time in milliseconds for the transition.
29129	 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not.
29130	 */
29131	Navigation.prototype.to = function(position, speed, standard) {
29132		var length;
29133
29134		if (!standard && this._pages.length) {
29135			length = this._pages.length;
29136			$.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed);
29137		} else {
29138			$.proxy(this._overrides.to, this._core)(position, speed);
29139		}
29140	};
29141
29142	$.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation;
29143
29144})(window.Zepto || window.jQuery, window, document);
29145
29146/**
29147 * Hash Plugin
29148 * @version 2.3.4
29149 * @author Artus Kolanowski
29150 * @author David Deutsch
29151 * @license The MIT License (MIT)
29152 */
29153;(function($, window, document, undefined) {
29154	'use strict';
29155
29156	/**
29157	 * Creates the hash plugin.
29158	 * @class The Hash Plugin
29159	 * @param {Owl} carousel - The Owl Carousel
29160	 */
29161	var Hash = function(carousel) {
29162		/**
29163		 * Reference to the core.
29164		 * @protected
29165		 * @type {Owl}
29166		 */
29167		this._core = carousel;
29168
29169		/**
29170		 * Hash index for the items.
29171		 * @protected
29172		 * @type {Object}
29173		 */
29174		this._hashes = {};
29175
29176		/**
29177		 * The carousel element.
29178		 * @type {jQuery}
29179		 */
29180		this.$element = this._core.$element;
29181
29182		/**
29183		 * All event handlers.
29184		 * @protected
29185		 * @type {Object}
29186		 */
29187		this._handlers = {
29188			'initialized.owl.carousel': $.proxy(function(e) {
29189				if (e.namespace && this._core.settings.startPosition === 'URLHash') {
29190					$(window).trigger('hashchange.owl.navigation');
29191				}
29192			}, this),
29193			'prepared.owl.carousel': $.proxy(function(e) {
29194				if (e.namespace) {
29195					var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash');
29196
29197					if (!hash) {
29198						return;
29199					}
29200
29201					this._hashes[hash] = e.content;
29202				}
29203			}, this),
29204			'changed.owl.carousel': $.proxy(function(e) {
29205				if (e.namespace && e.property.name === 'position') {
29206					var current = this._core.items(this._core.relative(this._core.current())),
29207						hash = $.map(this._hashes, function(item, hash) {
29208							return item === current ? hash : null;
29209						}).join();
29210
29211					if (!hash || window.location.hash.slice(1) === hash) {
29212						return;
29213					}
29214
29215					window.location.hash = hash;
29216				}
29217			}, this)
29218		};
29219
29220		// set default options
29221		this._core.options = $.extend({}, Hash.Defaults, this._core.options);
29222
29223		// register the event handlers
29224		this.$element.on(this._handlers);
29225
29226		// register event listener for hash navigation
29227		$(window).on('hashchange.owl.navigation', $.proxy(function(e) {
29228			var hash = window.location.hash.substring(1),
29229				items = this._core.$stage.children(),
29230				position = this._hashes[hash] && items.index(this._hashes[hash]);
29231
29232			if (position === undefined || position === this._core.current()) {
29233				return;
29234			}
29235
29236			this._core.to(this._core.relative(position), false, true);
29237		}, this));
29238	};
29239
29240	/**
29241	 * Default options.
29242	 * @public
29243	 */
29244	Hash.Defaults = {
29245		URLhashListener: false
29246	};
29247
29248	/**
29249	 * Destroys the plugin.
29250	 * @public
29251	 */
29252	Hash.prototype.destroy = function() {
29253		var handler, property;
29254
29255		$(window).off('hashchange.owl.navigation');
29256
29257		for (handler in this._handlers) {
29258			this._core.$element.off(handler, this._handlers[handler]);
29259		}
29260		for (property in Object.getOwnPropertyNames(this)) {
29261			typeof this[property] != 'function' && (this[property] = null);
29262		}
29263	};
29264
29265	$.fn.owlCarousel.Constructor.Plugins.Hash = Hash;
29266
29267})(window.Zepto || window.jQuery, window, document);
29268
29269/**
29270 * Support Plugin
29271 *
29272 * @version 2.3.4
29273 * @author Vivid Planet Software GmbH
29274 * @author Artus Kolanowski
29275 * @author David Deutsch
29276 * @license The MIT License (MIT)
29277 */
29278;(function($, window, document, undefined) {
29279
29280	var style = $('<support>').get(0).style,
29281		prefixes = 'Webkit Moz O ms'.split(' '),
29282		events = {
29283			transition: {
29284				end: {
29285					WebkitTransition: 'webkitTransitionEnd',
29286					MozTransition: 'transitionend',
29287					OTransition: 'oTransitionEnd',
29288					transition: 'transitionend'
29289				}
29290			},
29291			animation: {
29292				end: {
29293					WebkitAnimation: 'webkitAnimationEnd',
29294					MozAnimation: 'animationend',
29295					OAnimation: 'oAnimationEnd',
29296					animation: 'animationend'
29297				}
29298			}
29299		},
29300		tests = {
29301			csstransforms: function() {
29302				return !!test('transform');
29303			},
29304			csstransforms3d: function() {
29305				return !!test('perspective');
29306			},
29307			csstransitions: function() {
29308				return !!test('transition');
29309			},
29310			cssanimations: function() {
29311				return !!test('animation');
29312			}
29313		};
29314
29315	function test(property, prefixed) {
29316		var result = false,
29317			upper = property.charAt(0).toUpperCase() + property.slice(1);
29318
29319		$.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) {
29320			if (style[property] !== undefined) {
29321				result = prefixed ? property : true;
29322				return false;
29323			}
29324		});
29325
29326		return result;
29327	}
29328
29329	function prefixed(property) {
29330		return test(property, true);
29331	}
29332
29333	if (tests.csstransitions()) {
29334		/* jshint -W053 */
29335		$.support.transition = new String(prefixed('transition'))
29336		$.support.transition.end = events.transition.end[ $.support.transition ];
29337	}
29338
29339	if (tests.cssanimations()) {
29340		/* jshint -W053 */
29341		$.support.animation = new String(prefixed('animation'))
29342		$.support.animation.end = events.animation.end[ $.support.animation ];
29343	}
29344
29345	if (tests.csstransforms()) {
29346		/* jshint -W053 */
29347		$.support.transform = new String(prefixed('transform'));
29348		$.support.transform3d = tests.csstransforms3d();
29349	}
29350
29351})(window.Zepto || window.jQuery, window, document);
vendor: 3,669 bytes, lines 29352-29500
29352
29353/*!
29354	autosize 4.0.2
29355	license: MIT
29356	http://www.jacklmoore.com/autosize
29357*/
29358(function (global, factory) {
29359	if (typeof define === "function" && define.amd) {
29360		define(['module', 'exports'], factory);
29361	} else if (typeof exports !== "undefined") {
29362		factory(module, exports);
29363	} else {
29364		var mod = {
29365			exports: {}
29366		};
29367		factory(mod, mod.exports);
29368		global.autosize = mod.exports;
29369	}
29370})(this, function (module, exports) {
29371	'use strict';
29372
29373	var map = typeof Map === "function" ? new Map() : function () {
29374		var keys = [];
29375		var values = [];
29376
29377		return {
29378			has: function has(key) {
29379				return keys.indexOf(key) > -1;
29380			},
29381			get: function get(key) {
29382				return values[keys.indexOf(key)];
29383			},
29384			set: function set(key, value) {
29385				if (keys.indexOf(key) === -1) {
29386					keys.push(key);
29387					values.push(value);
29388				}
29389			},
29390			delete: function _delete(key) {
29391				var index = keys.indexOf(key);
29392				if (index > -1) {
29393					keys.splice(index, 1);
29394					values.splice(index, 1);
29395				}
29396			}
29397		};
29398	}();
29399
29400	var createEvent = function createEvent(name) {
29401		return new Event(name, { bubbles: true });
29402	};
29403	try {
29404		new Event('test');
29405	} catch (e) {
29406		// IE does not support `new Event()`
29407		createEvent = function createEvent(name) {
29408			var evt = document.createEvent('Event');
29409			evt.initEvent(name, true, false);
29410			return evt;
29411		};
29412	}
29413
29414	function assign(ta) {
29415		if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || map.has(ta)) return;
29416
29417		var heightOffset = null;
29418		var clientWidth = null;
29419		var cachedHeight = null;
29420
29421		function init() {
29422			var style = window.getComputedStyle(ta, null);
29423
29424			if (style.resize === 'vertical') {
29425				ta.style.resize = 'none';
29426			} else if (style.resize === 'both') {
29427				ta.style.resize = 'horizontal';
29428			}
29429
29430			if (style.boxSizing === 'content-box') {
29431				heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));
29432			} else {
29433				heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
29434			}
29435			// Fix when a textarea is not on document body and heightOffset is Not a Number
29436			if (isNaN(heightOffset)) {
29437				heightOffset = 0;
29438			}
29439
29440			update();
29441		}
29442
29443		function changeOverflow(value) {
29444			{
29445				// Chrome/Safari-specific fix:
29446				// When the textarea y-overflow is hidden, Chrome/Safari do not reflow the text to account for the space
29447				// made available by removing the scrollbar. The following forces the necessary text reflow.
29448				var width = ta.style.width;
29449				ta.style.width = '0px';
29450				// Force reflow:
29451				/* jshint ignore:start */
29452				ta.offsetWidth;
29453				/* jshint ignore:end */
29454				ta.style.width = width;
29455			}
29456
29457			ta.style.overflowY = value;
29458		}
29459
29460		function getParentOverflows(el) {
29461			var arr = [];
29462
29463			while (el && el.parentNode && el.parentNode instanceof Element) {
29464				if (el.parentNode.scrollTop) {
29465					arr.push({
29466						node: el.parentNode,
29467						scrollTop: el.parentNode.scrollTop
29468					});
29469				}
29470				el = el.parentNode;
29471			}
29472
29473			return arr;
29474		}
29475
29476		function resize() {
29477			if (ta.scrollHeight === 0) {
29478				// If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM.
29479				return;
29480			}
29481
29482			var overflows = getParentOverflows(ta);
29483			var docTop = document.documentElement && document.documentElement.scrollTop; // Needed for Mobile IE (ticket #240)
29484
29485			ta.style.height = '';
29486			ta.style.height = ta.scrollHeight + heightOffset + 'px';
29487
29488			// used to check if an update is actually necessary on window.resize
29489			clientWidth = ta.clientWidth;
29490
29491			// prevents scroll-position jumping
29492			overflows.forEach(function (el) {
29493				el.node.scrollTop = el.scrollTop;
29494			});
29495
29496			if (docTop) {
29497				document.documentElement.scrollTop = docTop;
29498			}
29499		}
29500
29501		function update() {
29502			resize();
29503
29504			var styleHeight = Math.round(parseFloat(ta.style.height));
29505			var computed = window.getComputedStyle(ta, null);
29506
29507			// Using offsetHeight as a replacement for computed.height in IE, because IE does not account use of border-box
29508			var actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(computed.height)) : ta.offsetHeight;
29509
29510			// The actual height not matching the style height (set via the resize method) indicates that 
29511			// the max-height has been exceeded, in which case the overflow should be allowed.
29512			if (actualHeight < styleHeight) {
29513				if (computed.overflowY === 'hidden') {
29514					changeOverflow('scroll');
29515					resize();
29516					actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(window.getComputedStyle(ta, null).height)) : ta.offsetHeight;
29517				}
29518			} else {
29519				// Normally keep overflow set to hidden, to avoid flash of scrollbar as the textarea expands.
29520				if (computed.overflowY !== 'hidden') {
29521					changeOverflow('hidden');
29522					resize();
29523					actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(window.getComputedStyle(ta, null).height)) : ta.offsetHeight;
29524				}
29525			}
29526
29527			if (cachedHeight !== actualHeight) {
29528				cachedHeight = actualHeight;
29529				var evt = createEvent('autosize:resized');
29530				try {
29531					ta.dispatchEvent(evt);
29532				} catch (err) {
29533					// Firefox will throw an error on dispatchEvent for a detached element
29534					// https://bugzilla.mozilla.org/show_bug.cgi?id=889376
29535				}
29536			}
29537		}
29538
29539		var pageResize = function pageResize() {
29540			if (ta.clientWidth !== clientWidth) {
29541				update();
29542			}
29543		};
29544
29545		var destroy = function (style) {
29546			window.removeEventListener('resize', pageResize, false);
29547			ta.removeEventListener('input', update, false);
29548			ta.removeEventListener('keyup', update, false);
29549			ta.removeEventListener('autosize:destroy', destroy, false);
29550			ta.removeEventListener('autosize:update', update, false);
29551
29552			Object.keys(style).forEach(function (key) {
29553				ta.style[key] = style[key];
29554			});
29555
29556			map.delete(ta);
29557		}.bind(ta, {
29558			height: ta.style.height,
29559			resize: ta.style.resize,
29560			overflowY: ta.style.overflowY,
29561			overflowX: ta.style.overflowX,
29562			wordWrap: ta.style.wordWrap
29563		});
29564
29565		ta.addEventListener('autosize:destroy', destroy, false);
29566
29567		// IE9 does not fire onpropertychange or oninput for deletions,
29568		// so binding to onkeyup to catch most of those events.
29569		// There is no way that I know of to detect something like 'cut' in IE9.
29570		if ('onpropertychange' in ta && 'oninput' in ta) {
29571			ta.addEventListener('keyup', update, false);
29572		}
29573
29574		window.addEventListener('resize', pageResize, false);
29575		ta.addEventListener('input', update, false);
29576		ta.addEventListener('autosize:update', update, false);
29577		ta.style.overflowX = 'hidden';
29578		ta.style.wordWrap = 'break-word';
29579
29580		map.set(ta, {
29581			destroy: destroy,
29582			update: update
29583		});
29584
29585		init();
29586	}
29587
29588	function destroy(ta) {
29589		var methods = map.get(ta);
29590		if (methods) {
29591			methods.destroy();
29592		}
29593	}
29594
29595	function update(ta) {
29596		var methods = map.get(ta);
29597		if (methods) {
29598			methods.update();
29599		}
29600	}
29601
29602	var autosize = null;
29603
29604	// Do nothing in Node.js environment and IE8 (or lower)
29605	if (typeof window === 'undefined' || typeof window.getComputedStyle !== 'function') {
29606		autosize = function autosize(el) {
29607			return el;
29608		};
29609		autosize.destroy = function (el) {
29610			return el;
29611		};
29612		autosize.update = function (el) {
29613			return el;
29614		};
29615	} else {
29616		autosize = function autosize(el, options) {
29617			if (el) {
29618				Array.prototype.forEach.call(el.length ? el : [el], function (x) {
29619					return assign(x, options);
29620				});
29621			}
29622			return el;
29623		};
29624		autosize.destroy = function (el) {
29625			if (el) {
29626				Array.prototype.forEach.call(el.length ? el : [el], destroy);
29627			}
29628			return el;
29629		};
29630		autosize.update = function (el) {
29631			if (el) {
29632				Array.prototype.forEach.call(el.length ? el : [el], update);
29633			}
29634			return el;
29635		};
29636	}
29637
29638	exports.default = autosize;
29639	module.exports = exports['default'];
29640});
29641/*!
29642 * clipboard.js v1.7.1
29643 * https://zenorocha.github.io/clipboard.js
29644 *
29645 * Licensed MIT © Zeno Rocha
29646 */
29647!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Clipboard=t()}}(function(){var t,e,n;return function t(e,n,o){function i(a,c){if(!n[a]){if(!e[a]){var l="function"==typeof require&&require;if(!c&&l)return l(a,!0);if(r)return r(a,!0);var s=new Error("Cannot find module '"+a+"'");throw s.code="MODULE_NOT_FOUND",s}var u=n[a]={exports:{}};e[a][0].call(u.exports,function(t){var n=e[a][1][t];return i(n||t)},u,u.exports,t,e,n,o)}return n[a].exports}for(var r="function"==typeof require&&require,a=0;a<o.length;a++)i(o[a]);return i}({1:[function(t,e,n){function o(t,e){for(;t&&t.nodeType!==i;){if("function"==typeof t.matches&&t.matches(e))return t;t=t.parentNode}}var i=9;if("undefined"!=typeof Element&&!Element.prototype.matches){var r=Element.prototype;r.matches=r.matchesSelector||r.mozMatchesSelector||r.msMatchesSelector||r.oMatchesSelector||r.webkitMatchesSelector}e.exports=o},{}],2:[function(t,e,n){function o(t,e,n,o,r){var a=i.apply(this,arguments);return t.addEventListener(n,a,r),{destroy:function(){t.removeEventListener(n,a,r)}}}function i(t,e,n,o){return function(n){n.delegateTarget=r(n.target,e),n.delegateTarget&&o.call(t,n)}}
vendor: 9,269 bytes, line 29647
29647var r=t("./closest");e.exports=o},{"./closest":1}],3:[function(t,e,n){n.node=function(t){return void 0!==t&&t instanceof HTMLElement&&1===t.nodeType},n.nodeList=function(t){var e=Object.prototype.toString.call(t);return void 0!==t&&("[object NodeList]"===e||"[object HTMLCollection]"===e)&&"length"in t&&(0===t.length||n.node(t[0]))},n.string=function(t){return"string"==typeof t||t instanceof String},n.fn=function(t){return"[object Function]"===Object.prototype.toString.call(t)}},{}],4:[function(t,e,n){function o(t,e,n){if(!t&&!e&&!n)throw new Error("Missing required arguments");if(!c.string(e))throw new TypeError("Second argument must be a String");if(!c.fn(n))throw new TypeError("Third argument must be a Function");if(c.node(t))return i(t,e,n);if(c.nodeList(t))return r(t,e,n);if(c.string(t))return a(t,e,n);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function i(t,e,n){return t.addEventListener(e,n),{destroy:function(){t.removeEventListener(e,n)}}}function r(t,e,n){return Array.prototype.forEach.call(t,function(t){t.addEventListener(e,n)}),{destroy:function(){Array.prototype.forEach.call(t,function(t){t.removeEventListener(e,n)})}}}function a(t,e,n){return l(document.body,t,e,n)}var c=t("./is"),l=t("delegate");e.exports=o},{"./is":3,delegate:2}],5:[function(t,e,n){function o(t){var e;if("SELECT"===t.nodeName)t.focus(),e=t.value;else if("INPUT"===t.nodeName||"TEXTAREA"===t.nodeName){var n=t.hasAttribute("readonly");n||t.setAttribute("readonly",""),t.select(),t.setSelectionRange(0,t.value.length),n||t.removeAttribute("readonly"),e=t.value}else{t.hasAttribute("contenteditable")&&t.focus();var o=window.getSelection(),i=document.createRange();i.selectNodeContents(t),o.removeAllRanges(),o.addRange(i),e=o.toString()}return e}e.exports=o},{}],6:[function(t,e,n){function o(){}o.prototype={on:function(t,e,n){var o=this.e||(this.e={});return(o[t]||(o[t]=[])).push({fn:e,ctx:n}),this},once:function(t,e,n){function o(){i.off(t,o),e.apply(n,arguments)}var i=this;return o._=e,this.on(t,o,n)},emit:function(t){var e=[].slice.call(arguments,1),n=((this.e||(this.e={}))[t]||[]).slice(),o=0,i=n.length;for(o;o<i;o++)n[o].fn.apply(n[o].ctx,e);return this},off:function(t,e){var n=this.e||(this.e={}),o=n[t],i=[];if(o&&e)for(var r=0,a=o.length;r<a;r++)o[r].fn!==e&&o[r].fn._!==e&&i.push(o[r]);return i.length?n[t]=i:delete n[t],this}},e.exports=o},{}],7:[function(e,n,o){!function(i,r){if("function"==typeof t&&t.amd)t(["module","select"],r);else if(void 0!==o)r(n,e("select"));else{var a={exports:{}};r(a,i.select),i.clipboardAction=a.exports}}(this,function(t,e){"use strict";function n(t){return t&&t.__esModule?t:{default:t}}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var i=n(e),r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},a=function(){function t(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(e,n,o){return n&&t(e.prototype,n),o&&t(e,o),e}}(),c=function(){function t(e){o(this,t),this.resolveOptions(e),this.initSelection()}return a(t,[{key:"resolveOptions",value:function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.action=e.action,this.container=e.container,this.emitter=e.emitter,this.target=e.target,this.text=e.text,this.trigger=e.trigger,this.selectedText=""}},{key:"initSelection",value:function t(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function t(){var e=this,n="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return e.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[n?"right":"left"]="-9999px";var o=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=o+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=(0,i.default)(this.fakeElem),this.copyText()}},{key:"removeFake",value:function t(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function t(){this.selectedText=(0,i.default)(this.target),this.copyText()}},{key:"copyText",value:function t(){var e=void 0;try{e=document.execCommand(this.action)}catch(t){e=!1}this.handleResult(e)}},{key:"handleResult",value:function t(e){this.emitter.emit(e?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function t(){this.trigger&&this.trigger.focus(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function t(){this.removeFake()}},{key:"action",set:function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=e,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function t(){return this._action}},{key:"target",set:function t(e){if(void 0!==e){if(!e||"object"!==(void 0===e?"undefined":r(e))||1!==e.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(e.hasAttribute("readonly")||e.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=e}},get:function t(){return this._target}}]),t}();t.exports=c})},{select:5}],8:[function(e,n,o){!function(i,r){if("function"==typeof t&&t.amd)t(["module","./clipboard-action","tiny-emitter","good-listener"],r);else if(void 0!==o)r(n,e("./clipboard-action"),e("tiny-emitter"),e("good-listener"));else{var a={exports:{}};r(a,i.clipboardAction,i.tinyEmitter,i.goodListener),i.clipboard=a.exports}}(this,function(t,e,n,o){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function c(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function l(t,e){var n="data-clipboard-"+t;if(e.hasAttribute(n))return e.getAttribute(n)}var s=i(e),u=i(n),f=i(o),d="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},h=function(){function t(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(e,n,o){return n&&t(e.prototype,n),o&&t(e,o),e}}(),p=function(t){function e(t,n){r(this,e);var o=a(this,(e.__proto__||Object.getPrototypeOf(e)).call(this));return o.resolveOptions(n),o.listenClick(t),o}return c(e,t),h(e,[{key:"resolveOptions",value:function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof e.action?e.action:this.defaultAction,this.target="function"==typeof e.target?e.target:this.defaultTarget,this.text="function"==typeof e.text?e.text:this.defaultText,this.container="object"===d(e.container)?e.container:document.body}},{key:"listenClick",value:function t(e){var n=this;this.listener=(0,f.default)(e,"click",function(t){return n.onClick(t)})}},{key:"onClick",value:function t(e){var n=e.delegateTarget||e.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new s.default({action:this.action(n),target:this.target(n),text:this.text(n),container:this.container,trigger:n,emitter:this})}},{key:"defaultAction",value:function t(e){return l("action",e)}},{key:"defaultTarget",value:function t(e){var n=l("target",e);if(n)return document.querySelector(n)}},{key:"defaultText",value:function t(e){return l("text",e)}},{key:"destroy",value:function t(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],n="string"==typeof e?[e]:e,o=!!document.queryCommandSupported;
29647return n.forEach(function(t){o=o&&!!document.queryCommandSupported(t)}),o}}]),e}(u.default);t.exports=p})},{"./clipboard-action":7,"good-listener":4,"tiny-emitter":6}]},{},[8])(8)});
29648// Ion.RangeSlider
29649// version 2.3.0 Build: 381
29650// © Denis Ineshin, 2018
29651// https://github.com/IonDen
29652//
29653// Project page:    http://ionden.com/a/plugins/ion.rangeSlider/en.html
29654// GitHub page:     https://github.com/IonDen/ion.rangeSlider
29655//
29656// Released under MIT licence:
29657// http://ionden.com/a/plugins/licence-en.html
29658// =====================================================================================================================
29659
29660;(function(factory) {
29661    if (!jQuery && typeof define === "function" && define.amd) {
29662        define(["jquery"], function (jQuery) {
29663            return factory(jQuery, document, window, navigator);
29664        });
29665    } else if (!jQuery && typeof exports === "object") {
29666        factory(require("jquery"), document, window, navigator);
29667    } else {
29668        factory(jQuery, document, window, navigator);
29669    }
29670} (function ($, document, window, navigator, undefined) {
29671    "use strict";
29672
29673    // =================================================================================================================
29674    // Service
29675
29676    var plugin_count = 0;
29677
29678    // IE8 fix
29679    var is_old_ie = (function () {
29680        var n = navigator.userAgent,
29681            r = /msie\s\d+/i,
29682            v;
29683        if (n.search(r) > 0) {
29684            v = r.exec(n).toString();
29685            v = v.split(" ")[1];
29686            if (v < 9) {
29687                $("html").addClass("lt-ie9");
29688                return true;
29689            }
29690        }
29691        return false;
29692    } ());
29693    if (!Function.prototype.bind) {
29694        Function.prototype.bind = function bind(that) {
29695
29696            var target = this;
29697            var slice = [].slice;
29698
29699            if (typeof target != "function") {
29700                throw new TypeError();
29701            }
29702
29703            var args = slice.call(arguments, 1),
29704                bound = function () {
29705
29706                    if (this instanceof bound) {
29707
29708                        var F = function(){};
29709                        F.prototype = target.prototype;
29710                        var self = new F();
29711
29712                        var result = target.apply(
29713                            self,
29714                            args.concat(slice.call(arguments))
29715                        );
29716                        if (Object(result) === result) {
29717                            return result;
29718                        }
29719                        return self;
29720
29721                    } else {
29722
29723                        return target.apply(
29724                            that,
29725                            args.concat(slice.call(arguments))
29726                        );
29727
29728                    }
29729
29730                };
29731
29732            return bound;
29733        };
29734    }
29735    if (!Array.prototype.indexOf) {
29736        Array.prototype.indexOf = function(searchElement, fromIndex) {
29737            var k;
29738            if (this == null) {
29739                throw new TypeError('"this" is null or not defined');
29740            }
29741            var O = Object(this);
29742            var len = O.length >>> 0;
29743            if (len === 0) {
29744                return -1;
29745            }
29746            var n = +fromIndex || 0;
29747            if (Math.abs(n) === Infinity) {
29748                n = 0;
29749            }
29750            if (n >= len) {
29751                return -1;
29752            }
29753            k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
29754            while (k < len) {
29755                if (k in O && O[k] === searchElement) {
29756                    return k;
29757                }
29758                k++;
29759            }
29760            return -1;
29761        };
29762    }
29763
29764
29765
29766    // =================================================================================================================
29767    // Template
29768
29769    var base_html =
29770        '<span class="irs">' +
29771        '<span class="irs-line" tabindex="0"></span>' +
29772        '<span class="irs-min">0</span><span class="irs-max">1</span>' +
29773        '<span class="irs-from">0</span><span class="irs-to">0</span><span class="irs-single">0</span>' +
29774        '</span>' +
29775        '<span class="irs-grid"></span>';
29776
29777    var single_html =
29778        '<span class="irs-bar irs-bar--single"></span>' +
29779        '<span class="irs-shadow shadow-single"></span>' +
29780        '<span class="irs-handle single"><i></i><i></i><i></i></span>';
29781
29782    var double_html =
29783        '<span class="irs-bar"></span>' +
29784        '<span class="irs-shadow shadow-from"></span>' +
29785        '<span class="irs-shadow shadow-to"></span>' +
29786        '<span class="irs-handle from"><i></i><i></i><i></i></span>' +
29787        '<span class="irs-handle to"><i></i><i></i><i></i></span>';
29788
29789    var disable_html =
29790        '<span class="irs-disable-mask"></span>';
29791
29792
29793
29794    // =================================================================================================================
29795    // Core
29796
29797    /**
29798     * Main plugin constructor
29799     *
29800     * @param input {Object} link to base input element
29801     * @param options {Object} slider config
29802     * @param plugin_count {Number}
29803     * @constructor
29804     */
29805    var IonRangeSlider = function (input, options, plugin_count) {
29806        this.VERSION = "2.3.0";
29807        this.input = input;
29808        this.plugin_count = plugin_count;
29809        this.current_plugin = 0;
29810        this.calc_count = 0;
29811        this.update_tm = 0;
29812        this.old_from = 0;
29813        this.old_to = 0;
29814        this.old_min_interval = null;
29815        this.raf_id = null;
29816        this.dragging = false;
29817        this.force_redraw = false;
29818        this.no_diapason = false;
29819        this.has_tab_index = true;
29820        this.is_key = false;
29821        this.is_update = false;
29822        this.is_start = true;
29823        this.is_finish = false;
29824        this.is_active = false;
29825        this.is_resize = false;
29826        this.is_click = false;
29827
29828        options = options || {};
29829
29830        // cache for links to all DOM elements
29831        this.$cache = {
29832            win: $(window),
29833            body: $(document.body),
29834            input: $(input),
29835            cont: null,
29836            rs: null,
29837            min: null,
29838            max: null,
29839            from: null,
29840            to: null,
29841            single: null,
29842            bar: null,
29843            line: null,
29844            s_single: null,
29845            s_from: null,
29846            s_to: null,
29847            shad_single: null,
29848            shad_from: null,
29849            shad_to: null,
29850            edge: null,
29851            grid: null,
29852            grid_labels: []
29853        };
29854
29855        // storage for measure variables
29856        this.coords = {
29857            // left
29858            x_gap: 0,
29859            x_pointer: 0,
29860
29861            // width
29862            w_rs: 0,
29863            w_rs_old: 0,
29864            w_handle: 0,
29865
29866            // percents
29867            p_gap: 0,
29868            p_gap_left: 0,
29869            p_gap_right: 0,
29870            p_step: 0,
29871            p_pointer: 0,
29872            p_handle: 0,
29873            p_single_fake: 0,
29874            p_single_real: 0,
29875            p_from_fake: 0,
29876            p_from_real: 0,
29877            p_to_fake: 0,
29878            p_to_real: 0,
29879            p_bar_x: 0,
29880            p_bar_w: 0,
29881
29882            // grid
29883            grid_gap: 0,
29884            big_num: 0,
29885            big: [],
29886            big_w: [],
29887            big_p: [],
29888            big_x: []
29889        };
29890
29891        // storage for labels measure variables
29892        this.labels = {
29893            // width
29894            w_min: 0,
29895            w_max: 0,
29896            w_from: 0,
29897            w_to: 0,
29898            w_single: 0,
29899
29900            // percents
29901            p_min: 0,
29902            p_max: 0,
29903            p_from_fake: 0,
29904            p_from_left: 0,
29905            p_to_fake: 0,
29906            p_to_left: 0,
29907            p_single_fake: 0,
29908            p_single_left: 0
29909        };
29910
29911
29912
29913        /**
29914         * get and validate config
29915         */
29916        var $inp = this.$cache.input,
29917            val = $inp.prop("value"),
29918            config, config_from_data, prop;
29919
29920        // default config
29921        config = {
29922            skin: "flat",
29923            type: "single",
29924
29925            min: 10,
29926            max: 100,
29927            from: null,
29928            to: null,
29929            step: 1,
29930
29931            min_interval: 0,
29932            max_interval: 0,
29933            drag_interval: false,
29934
29935            values: [],
29936            p_values: [],
29937
29938            from_fixed: false,
29939            from_min: null,
29940            from_max: null,
29941            from_shadow: false,
29942
29943            to_fixed: false,
29944            to_min: null,
29945            to_max: null,
29946            to_shadow: false,
29947
29948            prettify_enabled: true,
29949            prettify_separator: " ",
29950            prettify: null,
29951
29952            force_edges: false,
29953
29954            keyboard: true,
29955
29956            grid: false,
29957            grid_margin: true,
29958            grid_num: 4,
29959            grid_snap: false,
29960
29961            hide_min_max: false,
29962            hide_from_to: false,
29963
29964            prefix: "",
29965            postfix: "",
29966            max_postfix: "",
29967            decorate_both: true,
29968            values_separator: " — ",
29969
29970            input_values_separator: ";",
29971
29972            disable: false,
29973            block: false,
29974
29975            extra_classes: "",
29976
29977            scope: null,
29978            onStart: null,
29979            onChange: null,
29980            onFinish: null,
29981            onUpdate: null
29982        };
29983
29984
29985        // check if base element is input
29986        if ($inp[0].nodeName !== "INPUT") {
29987            console && console.warn && console.warn("Base element should be <input>!", $inp[0]);
29988        }
29989
29990
29991        // config from data-attributes extends js config
29992        config_from_data = {
29993            skin: $inp.data("skin"),
29994            type: $inp.data("type"),
29995
29996            min: $inp.data("min"),
29997            max: $inp.data("max"),
29998            from: $inp.data("from"),
29999            to: $inp.data("to"),
30000            step: $inp.data("step"),
30001
30002            min_interval: $inp.data("minInterval"),
30003            max_interval: $inp.data("maxInterval"),
30004            drag_interval: $inp.data("dragInterval"),
30005
30006            values: $inp.data("values"),
30007
30008            from_fixed: $inp.data("fromFixed"),
30009            from_min: $inp.data("fromMin"),
30010            from_max: $inp.data("fromMax"),
30011            from_shadow: $inp.data("fromShadow"),
30012
30013            to_fixed: $inp.data("toFixed"),
30014            to_min: $inp.data("toMin"),
30015            to_max: $inp.data("toMax"),
30016            to_shadow: $inp.data("toShadow"),
30017
30018            prettify_enabled: $inp.data("prettifyEnabled"),
30019            prettify_separator: $inp.data("prettifySeparator"),
30020
30021            force_edges: $inp.data("forceEdges"),
30022
30023            keyboard: $inp.data("keyboard"),
30024
30025            grid: $inp.data("grid"),
30026            grid_margin: $inp.data("gridMargin"),
30027            grid_num: $inp.data("gridNum"),
30028            grid_snap: $inp.data("gridSnap"),
30029
30030            hide_min_max: $inp.data("hideMinMax"),
30031            hide_from_to: $inp.data("hideFromTo"),
30032
30033            prefix: $inp.data("prefix"),
30034            postfix: $inp.data("postfix"),
30035            max_postfix: $inp.data("maxPostfix"),
30036            decorate_both: $inp.data("decorateBoth"),
30037            values_separator: $inp.data("valuesSeparator"),
30038
30039            input_values_separator: $inp.data("inputValuesSeparator"),
30040
30041            disable: $inp.data("disable"),
30042            block: $inp.data("block"),
30043
30044            extra_classes: $inp.data("extraClasses"),
30045        };
30046        config_from_data.values = config_from_data.values && config_from_data.values.split(",");
30047
30048        for (prop in config_from_data) {
30049            if (config_from_data.hasOwnProperty(prop)) {
30050                if (config_from_data[prop] === undefined || config_from_data[prop] === "") {
30051                    delete config_from_data[prop];
30052                }
30053            }
30054        }
30055
30056
30057        // input value extends default config
30058        if (val !== undefined && val !== "") {
30059            val = val.split(config_from_data.input_values_separator || options.input_values_separator || ";");
30060
30061            if (val[0] && val[0] == +val[0]) {
30062                val[0] = +val[0];
30063            }
30064            if (val[1] && val[1] == +val[1]) {
30065                val[1] = +val[1];
30066            }
30067
30068            if (options && options.values && options.values.length) {
30069                config.from = val[0] && options.values.indexOf(val[0]);
30070                config.to = val[1] && options.values.indexOf(val[1]);
30071            } else {
30072                config.from = val[0] && +val[0];
30073                config.to = val[1] && +val[1];
30074            }
30075        }
30076
30077
30078
30079        // js config extends default config
30080        $.extend(config, options);
30081
30082
30083        // data config extends config
30084        $.extend(config, config_from_data);
30085        this.options = config;
30086
30087
30088
30089        // validate config, to be sure that all data types are correct
30090        this.update_check = {};
30091        this.validate();
30092
30093
30094
30095        // default result object, returned to callbacks
30096        this.result = {
30097            input: this.$cache.input,
30098            slider: null,
30099
30100            min: this.options.min,
30101            max: this.options.max,
30102
30103            from: this.options.from,
30104            from_percent: 0,
30105            from_value: null,
30106
30107            to: this.options.to,
30108            to_percent: 0,
30109            to_value: null
30110        };
30111
30112
30113
30114        this.init();
30115    };
30116
30117    IonRangeSlider.prototype = {
30118
30119        /**
30120         * Starts or updates the plugin instance
30121         *
30122         * @param [is_update] {boolean}
30123         */
30124        init: function (is_update) {
30125            this.no_diapason = false;
30126            this.coords.p_step = this.convertToPercent(this.options.step, true);
30127
30128            this.target = "base";
30129
30130            this.toggleInput();
30131            this.append();
30132            this.setMinMax();
30133
30134            if (is_update) {
30135                this.force_redraw = true;
30136                this.calc(true);
30137
30138                // callbacks called
30139                this.callOnUpdate();
30140            } else {
30141                this.force_redraw = true;
30142                this.calc(true);
30143
30144                // callbacks called
30145                this.callOnStart();
30146            }
30147
30148            this.updateScene();
30149        },
30150
30151        /**
30152         * Appends slider template to a DOM
30153         */
30154        append: function () {
30155            var container_html = '<span class="irs irs--' + this.options.skin + ' js-irs-' 
30155+ this.plugin_count + ' ' + this.options.extra_classes + '"></span>';
30156            this.$cache.input.before(container_html);
30157            this.$cache.input.prop("readonly", true);
30158            this.$cache.cont = this.$cache.input.prev();
30159            this.result.slider = this.$cache.cont;
30160
30161            this.$cache.cont.html(base_html);
30162            this.$cache.rs = this.$cache.cont.find(".irs");
30163            this.$cache.min = this.$cache.cont.find(".irs-min");
30164            this.$cache.max = this.$cache.cont.find(".irs-max");
30165            this.$cache.from = this.$cache.cont.find(".irs-from");
30166            this.$cache.to = this.$cache.cont.find(".irs-to");
30167            this.$cache.single = this.$cache.cont.find(".irs-single");
30168            this.$cache.line = this.$cache.cont.find(".irs-line");
30169            this.$cache.grid = this.$cache.cont.find(".irs-grid");
30170
30171            if (this.options.type === "single") {
30172                this.$cache.cont.append(single_html);
30173                this.$cache.bar = this.$cache.cont.find(".irs-bar");
30174                this.$cache.edge = this.$cache.cont.find(".irs-bar-edge");
30175                this.$cache.s_single = this.$cache.cont.find(".single");
30176                this.$cache.from[0].style.visibility = "hidden";
30177                this.$cache.to[0].style.visibility = "hidden";
30178                this.$cache.shad_single = this.$cache.cont.find(".shadow-single");
30179            } else {
30180                this.$cache.cont.append(double_html);
30181                this.$cache.bar = this.$cache.cont.find(".irs-bar");
30182                this.$cache.s_from = this.$cache.cont.find(".from");
30183                this.$cache.s_to = this.$cache.cont.find(".to");
30184                this.$cache.shad_from = this.$cache.cont.find(".shadow-from");
30185                this.$cache.shad_to = this.$cache.cont.find(".shadow-to");
30186
30187                this.setTopHandler();
30188            }
30189
30190            if (this.options.hide_from_to) {
30191                this.$cache.from[0].style.display = "none";
30192                this.$cache.to[0].style.display = "none";
30193                this.$cache.single[0].style.display = "none";
30194            }
30195
30196            this.appendGrid();
30197
30198            if (this.options.disable) {
30199                this.appendDisableMask();
30200                this.$cache.input[0].disabled = true;
30201            } else {
30202                this.$cache.input[0].disabled = false;
30203                this.removeDisableMask();
30204                this.bindEvents();
30205            }
30206
30207            // block only if not disabled
30208            if (!this.options.disable) {
30209                if (this.options.block) {
30210                    this.appendDisableMask();
30211                } else {
30212                    this.removeDisableMask();
30213                }
30214            }
30215
30216            if (this.options.drag_interval) {
30217                this.$cache.bar[0].style.cursor = "ew-resize";
30218            }
30219        },
30220
30221        /**
30222         * Determine which handler has a priority
30223         * works only for double slider type
30224         */
30225        setTopHandler: function () {
30226            var min = this.options.min,
30227                max = this.options.max,
30228                from = this.options.from,
30229                to = this.options.to;
30230
30231            if (from > min && to === max) {
30232                this.$cache.s_from.addClass("type_last");
30233            } else if (to < max) {
30234                this.$cache.s_to.addClass("type_last");
30235            }
30236        },
30237
30238        /**
30239         * Determine which handles was clicked last
30240         * and which handler should have hover effect
30241         *
30242         * @param target {String}
30243         */
30244        changeLevel: function (target) {
30245            switch (target) {
30246                case "single":
30247                    this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_single_fake);
30248                    this.$cache.s_single.addClass("state_hover");
30249                    break;
30250                case "from":
30251                    this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_from_fake);
30252                    this.$cache.s_from.addClass("state_hover");
30253                    this.$cache.s_from.addClass("type_last");
30254                    this.$cache.s_to.removeClass("type_last");
30255                    break;
30256                case "to":
30257                    this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_to_fake);
30258                    this.$cache.s_to.addClass("state_hover");
30259                    this.$cache.s_to.addClass("type_last");
30260                    this.$cache.s_from.removeClass("type_last");
30261                    break;
30262                case "both":
30263                    this.coords.p_gap_left = this.toFixed(this.coords.p_pointer - this.coords.p_from_fake);
30264                    this.coords.p_gap_right = this.toFixed(this.coords.p_to_fake - this.coords.p_pointer);
30265                    this.$cache.s_to.removeClass("type_last");
30266                    this.$cache.s_from.removeClass("type_last");
30267                    break;
30268            }
30269        },
30270
30271        /**
30272         * Then slider is disabled
30273         * appends extra layer with opacity
30274         */
30275        appendDisableMask: function () {
30276            this.$cache.cont.append(disable_html);
30277            this.$cache.cont.addClass("irs-disabled");
30278        },
30279
30280        /**
30281         * Then slider is not disabled
30282         * remove disable mask
30283         */
30284        removeDisableMask: function () {
30285            this.$cache.cont.remove(".irs-disable-mask");
30286            this.$cache.cont.removeClass("irs-disabled");
30287        },
30288
30289        /**
30290         * Remove slider instance
30291         * and unbind all events
30292         */
30293        remove: function () {
30294            this.$cache.cont.remove();
30295            this.$cache.cont = null;
30296
30297            this.$cache.line.off("keydown.irs_" + this.plugin_count);
30298
30299            this.$cache.body.off("touchmove.irs_" + this.plugin_count);
30300            this.$cache.body.off("mousemove.irs_" + this.plugin_count);
30301
30302            this.$cache.win.off("touchend.irs_" + this.plugin_count);
30303            this.$cache.win.off("mouseup.irs_" + this.plugin_count);
30304
30305            if (is_old_ie) {
30306                this.$cache.body.off("mouseup.irs_" + this.plugin_count);
30307                this.$cache.body.off("mouseleave.irs_" + this.plugin_count);
30308            }
30309
30310            this.$cache.grid_labels = [];
30311            this.coords.big = [];
30312            this.coords.big_w = [];
30313            this.coords.big_p = [];
30314            this.coords.big_x = [];
30315
30316            cancelAnimationFrame(this.raf_id);
30317        },
30318
30319        /**
30320         * bind all slider events
30321         */
30322        bindEvents: function () {
30323            if (this.no_diapason) {
30324                return;
30325            }
30326
30327            this.$cache.body.on("touchmove.irs_" + this.plugin_count, this.pointerMove.bind(this));
30328            this.$cache.body.on("mousemove.irs_" + this.plugin_count, this.pointerMove.bind(this));
30329
30330            this.$cache.win.on("touchend.irs_" + this.plugin_count, this.pointerUp.bind(this));
30331            this.$cache.win.on("mouseup.irs_" + this.plugin_count, this.pointerUp.bind(this));
30332
30333            this.$cache.line.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
30334            this.$cache.line.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
30335
30336            this.$cache.line.on("focus.irs_" + this.plugin_count, this.pointerFocus.bind(this));
30337
30338            if (this.options.drag_interval && this.options.type === "double") {
30339                this.$cache.bar.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "both"));
30340                this.$cache.bar.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "both"));
30341            } else {
30342                this.$cache.bar.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
30343                this.$cache.bar.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
30344            }
30345
30346            if (this.options.type === "single") {
30347                this.$cache.single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
30348                this.$cache.s_single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
30349                this.$cache.shad_single.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
30350
30351                this.$cache.single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
30352                this.$cache.s_single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
30353                this.$cache.edge.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
30354                this.$cache.shad_single.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
30355            } else {
30356                this.$cache.single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, null));
30357                this.$cache.single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, null));
30358
30359                this.$cache.from.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
30360                this.$cache.s_from.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
30361                this.$cache.to.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
30362                this.$cache.s_to.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
30363                this.$cache.shad_from.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
30364                this.$cache.shad_to.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
30365
30366                this.$cache.from.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
30367                this.$cache.s_from.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
30368                this.$cache.to.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
30369                this.$cache.s_to.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
30370                this.$cache.shad_from.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
30371                this.$cache.shad_to.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
30372            }
30373
30374            if (this.options.keyboard) {
30375                this.$cache.line.on("keydown.irs_" + this.plugin_count, this.key.bind(this, "keyboard"));
30376            }
30377
30378            if (is_old_ie) {
30379                this.$cache.body.on("mouseup.irs_" + this.plugin_count, this.pointerUp.bind(this));
30380                this.$cache.body.on("mouseleave.irs_" + this.plugin_count, this.pointerUp.bind(this));
30381            }
30382        },
30383
30384        /**
30385         * Focus with tabIndex
30386         *
30387         * @param e {Object} event object
30388         */
30389        pointerFocus: function (e) {
30390            if (!this.target) {
30391                var x;
30392                var $handle;
30393
30394                if (this.options.type === "single") {
30395                    $handle = this.$cache.single;
30396                } else {
30397                    $handle = this.$cache.from;
30398                }
30399
30400                x = $handle.offset().left;
30401                x += ($handle.width() / 2) - 1;
30402
30403                this.pointerClick("single", {preventDefault: function () {}, pageX: x});
30404            }
30405        },
30406
30407        /**
30408         * Mousemove or touchmove
30409         * only for handlers
30410         *
30411         * @param e {Object} event object
30412         */
30413        pointerMove: function (e) {
30414            if (!this.dragging) {
30415                return;
30416            }
30417
30418            var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
30419            this.coords.x_pointer = x - this.coords.x_gap;
30420
30421            this.calc();
30422        },
30423
30424        /**
30425         * Mouseup or touchend
30426         * only for handlers
30427         *
30428         * @param e {Object} event object
30429         */
30430        pointerUp: function (e) {
30431            if (this.current_plugin !== this.plugin_count) {
30432                return;
30433            }
30434
30435            if (this.is_active) {
30436                this.is_active = false;
30437            } else {
30438                return;
30439            }
30440
30441            this.$cache.cont.find(".state_hover").removeClass("state_hover");
30442
30443            this.force_redraw = true;
30444
30445            if (is_old_ie) {
30446                $("*").prop("unselectable", false);
30447            }
30448
30449            this.updateScene();
30450            this.restoreOriginalMinInterval();
30451
30452            // callbacks call
30453            if ($.contains(this.$cache.cont[0], e.target) || this.dragging) {
30454                this.callOnFinish();
30455            }
30456            
30457            this.dragging = false;
30458        },
30459
30460        /**
30461         * Mousedown or touchstart
30462         * only for handlers
30463         *
30464         * @param target {String|null}
30465         * @param e {Object} event object
30466         */
30467        pointerDown: function (target, e) {
30468            e.preventDefault();
30469            var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
30470            if (e.button === 2) {
30471                return;
30472            }
30473
30474            if (target === "both") {
30475                this.setTempMinInterval();
30476            }
30477
30478            if (!target) {
30479                target = this.target || "from";
30480            }
30481
30482            this.current_plugin = this.plugin_count;
30483            this.target = target;
30484
30485            this.is_active = true;
30486            this.dragging = true;
30487
30488            this.coords.x_gap = this.$cache.rs.offset().left;
30489            this.coords.x_pointer = x - this.coords.x_gap;
30490
30491            this.calcPointerPercent();
30492            this.changeLevel(target);
30493
30494            if (is_old_ie) {
30495                $("*").prop("unselectable", true);
30496            }
30497
30498            this.$cache.line.trigger("focus");
30499
30500            this.updateScene();
30501        },
30502
30503        /**
30504         * Mousedown or touchstart
30505         * for other slider elements, like diapason line
30506         *
30507         * @param target {String}
30508         * @param e {Object} event object
30509         */
30510        pointerClick: function (target, e) {
30511            e.preventDefault();
30512            var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
30513            if (e.button === 2) {
30514                return;
30515            }
30516
30517            this.current_plugin = this.plugin_count;
30518            this.target = target;
30519
30520            this.is_click = true;
30521            this.coords.x_gap = this.$cache.rs.offset().left;
30522            this.coords.x_pointer = +(x - this.coords.x_gap).toFixed();
30523
30524            this.force_redraw = true;
30525            this.calc();
30526
30527            this.$cache.line.trigger("focus");
30528        },
30529
30530        /**
30531         * Keyborard controls for focused slider
30532         *
30533         * @param target {String}
30534         * @param e {Object} event object
30535         * @returns {boolean|undefined}
30536         */
30537        key: function (target, e) {
30538            if (this.current_plugin !== this.plugin_count || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
30539                return;
30540            }
30541
30542            switch (e.which) {
30543                case 83: // W
30544                case 65: // A
30545                case 40: // DOWN
30546                case 37: // LEFT
30547                    e.preventDefault();
30548                    this.moveByKey(false);
30549                    break;
30550
30551                case 87: // S
30552                case 68: // D
30553                case 38: // UP
30554                case 39: // RIGHT
30555                    e.preventDefault();
30556                    this.moveByKey(true);
30557                    break;
30558            }
30559
30560            return true;
30561        },
30562
30563        /**
30564         * Move by key
30565         *
30566         * @param right {boolean} direction to move
30567         */
30568        moveByKey: function (right) {
30569            var p = this.coords.p_pointer;
30570            var p_step = (this.options.max - this.options.min) / 100;
30571            p_step = this.options.step / p_step;
30572
30573            if (right) {
30574                p += p_step;
30575            } else {
30576                p -= p_step;
30577            }
30578
30579            this.coords.x_pointer = this.toFixed(this.coords.w_rs / 100 * p);
30580            this.is_key = true;
30581            this.calc();
30582        },
30583
30584        /**
30585         * Set visibility and content
30586         * of Min and Max labels
30587         */
30588        setMinMax: function () {
30589            if (!this.options) {
30590                return;
30591            }
30592
30593            if (this.options.hide_min_max) {
30594                this.$cache.min[0].style.display = "none";
30595                this.$cache.max[0].style.display = "none";
30596                return;
30597            }
30598
30599            if (this.options.values.length) {
30600                this.$cache.min.html(this.decorate(this.options.p_values[this.options.min]));
30601                this.$cache.max.html(this.decorate(this.options.p_values[this.options.max]));
30602            } else {
30603                var min_pretty = this._prettify(this.options.min);
30604                var max_pretty = this._prettify(this.options.max);
30605
30606                this.result.min_pretty = min_pretty;
30607                this.result.max_pretty = max_pretty;
30608
30609                this.$cache.min.html(this.decorate(min_pretty, this.options.min));
30610                this.$cache.max.html(this.decorate(max_pretty, this.options.max));
30611            }
30612
30613            this.labels.w_min = this.$cache.min.outerWidth(false);
30614            this.labels.w_max = this.$cache.max.outerWidth(false);
30615        },
30616
30617        /**
30618         * Then dragging interval, prevent interval collapsing
30619         * using min_interval option
30620         */
30621        setTempMinInterval: function () {
30622            var interval = this.result.to - this.result.from;
30623
30624            if (this.old_min_interval === null) {
30625                this.old_min_interval = this.options.min_interval;
30626            }
30627
30628            this.options.min_interval = interval;
30629        },
30630
30631        /**
30632         * Restore min_interval option to original
30633         */
30634        restoreOriginalMinInterval: function () {
30635            if (this.old_min_interval !== null) {
30636                this.options.min_interval = this.old_min_interval;
30637                this.old_min_interval = null;
30638            }
30639        },
30640
30641
30642
30643        // =============================================================================================================
30644        // Calculations
30645
30646        /**
30647         * All calculations and measures start here
30648         *
30649         * @param update {boolean=}
30650         */
30651        calc: function (update) {
30652            if (!this.options) {
30653                return;
30654            }
30655
30656            this.calc_count++;
30657
30658            if (this.calc_count === 10 || update) {
30659                this.calc_count = 0;
30660                this.coords.w_rs = this.$cache.rs.outerWidth(false);
30661
30662                this.calcHandlePercent();
30663            }
30664
30665            if (!this.coords.w_rs) {
30666                return;
30667            }
30668
30669            this.calcPointerPercent();
30670            var handle_x = this.getHandleX();
30671
30672
30673            if (this.target === "both") {
30674                this.coords.p_gap = 0;
30675                handle_x = this.getHandleX();
30676            }
30677
30678            if (this.target === "click") {
30679                this.coords.p_gap = this.coords.p_handle / 2;
30680                handle_x = this.getHandleX();
30681
30682                if (this.options.drag_interval) {
30683                    this.target = "both_one";
30684                } else {
30685                    this.target = this.chooseHandle(handle_x);
30686                }
30687            }
30688
30689            switch (this.target) {
30690                case "base":
30691                    var w = (this.options.max - this.options.min) / 100,
30692                        f = (this.result.from - this.options.min) / w,
30693                        t = (this.result.to - this.options.min) / w;
30694
30695                    this.coords.p_single_real = this.toFixed(f);
30696                    this.coords.p_from_real = this.toFixed(f);
30697                    this.coords.p_to_real = this.toFixed(t);
30698
30699                    this.coords.p_single_real = this.checkDiapason(this.coords.p_single_real, this.options.from_min, this.options.from_max);
30700                    this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
30701                    this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
30702
30703                    this.coords.p_single_fake = this.convertToFakePercent(this.coords.p_single_real);
30704                    this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);
30705                    this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);
30706
30707                    this.target = null;
30708
30709                    break;
30710
30711                case "single":
30712                    if (this.options.from_fixed) {
30713                        break;
30714                    }
30715
30716                    this.coords.p_single_real = this.convertToRealPercent(handle_x);
30717                    this.coords.p_single_real = this.calcWithStep(this.coords.p_single_real);
30718                    this.coords.p_single_real = this.checkDiapason(this.coords.p_single_real, this.options.from_min, this.options.from_max);
30719
30720                    this.coords.p_single_fake = this.convertToFakePercent(this.coords.p_single_real);
30721
30722                    break;
30723
30724                case "from":
30725                    if (this.options.from_fixed) {
30726                        break;
30727                    }
30728
30729                    this.coords.p_from_real = this.convertToRealPercent(handle_x);
30730                    this.coords.p_from_real = this.calcWithStep(this.coords.p_from_real);
30731                    if (this.coords.p_from_real > this.coords.p_to_real) {
30732                        this.coords.p_from_real = this.coords.p_to_real;
30733                    }
30734                    this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
30735                    this.coords.p_from_real = this.checkMinInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
30736                    this.coords.p_from_real = this.checkMaxInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
30737
30738                    this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);
30739
30740                    break;
30741
30742                case "to":
30743                    if (this.options.to_fixed) {
30744                        break;
30745                    }
30746
30747                    this.coords.p_to_real = this.convertToRealPercent(handle_x);
30748                    this.coords.p_to_real = this.calcWithStep(this.coords.p_to_real);
30749                    if (this.coords.p_to_real < this.coords.p_from_real) {
30750                        this.coords.p_to_real = this.coords.p_from_real;
30751                    }
30752                    this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
30753                    this.coords.p_to_real = this.checkMinInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
30754                    this.coords.p_to_real = this.checkMaxInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
30755
30756                    this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);
30757
30758                    break;
30759
30760                case "both":
30761                    if (this.options.from_fixed || this.options.to_fixed) {
30762                        break;
30763                    }
30764
30765                    handle_x = this.toFixed(handle_x + (this.coords.p_handle * 0.001));
30766
30767                    this.coords.p_from_real = this.convertToRealPercent(handle_x) - this.coords.p_gap_left;
30768                    this.coords.p_from_real = this.calcWithStep(this.coords.p_from_real);
30769                    this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
30770                    this.coords.p_from_real = this.checkMinInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
30771                    this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);
30772
30773                    this.coords.p_to_real = this.convertToRealPercent(handle_x) + this.coords.p_gap_right;
30774                    this.coords.p_to_real = this.calcWithStep(this.coords.p_to_real);
30775                    this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
30776                    this.coords.p_to_real = this.checkMinInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
30777                    this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);
30778
30779                    break;
30780
30781                case "both_one":
30782                    if (this.options.from_fixed || this.options.to_fixed) {
30783                        break;
30784                    }
30785
30786                    var real_x = this.convertToRealPercent(handle_x),
30787                        from = this.result.from_percent,
30788                        to = this.result.to_percent,
30789                        full = to - from,
30790                        half = full / 2,
30791                        new_from = real_x - half,
30792                        new_to = real_x + half;
30793
30794                    if (new_from < 0) {
30795                        new_from = 0;
30796                        new_to = new_from + full;
30797                    }
30798
30799                    if (new_to > 100) {
30800                        new_to = 100;
30801                        new_from = new_to - full;
30802                    }
30803
30804                    this.coords.p_from_real = this.calcWithStep(new_from);
30805                    this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
30806                    this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);
30807
30808                    this.coords.p_to_real = this.calcWithStep(new_to);
30809                    this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
30810                    this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);
30811
30812                    break;
30813            }
30814
30815            if (this.options.type === "single") {
30816                this.coords.p_bar_x = (this.coords.p_handle / 2);
30817                this.coords.p_bar_w = this.coords.p_single_fake;
30818
30819                this.result.from_percent = this.coords.p_single_real;
30820                this.result.from = this.convertToValue(this.coords.p_single_real);
30821                this.result.from_pretty = this._prettify(this.result.from);
30822
30823                if (this.options.values.length) {
30824                    this.result.from_value = this.options.values[this.result.from];
30825                }
30826            } else {
30827                this.coords.p_bar_x = this.toFixed(this.coords.p_from_fake + (this.coords.p_handle / 2));
30828                this.coords.p_bar_w = this.toFixed(this.coords.p_to_fake - this.coords.p_from_fake);
30829
30830                this.result.from_percent = this.coords.p_from_real;
30831                this.result.from = this.convertToValue(this.coords.p_from_real);
30832                this.result.from_pretty = this._prettify(this.result.from);
30833                this.result.to_percent = this.coords.p_to_real;
30834                this.result.to = this.convertToValue(this.coords.p_to_real);
30835                this.result.to_pretty = this._prettify(this.result.to);
30836
30837                if (this.options.values.length) {
30838                    this.result.from_value = this.options.values[this.result.from];
30839                    this.result.to_value = this.options.values[this.result.to];
30840                }
30841            }
30842
30843            this.calcMinMax();
30844            this.calcLabels();
30845        },
30846
30847
30848        /**
30849         * calculates pointer X in percent
30850         */
30851        calcPointerPercent: function () {
30852            if (!this.coords.w_rs) {
30853                this.coords.p_pointer = 0;
30854                return;
30855            }
30856
30857            if (this.coords.x_pointer < 0 || isNaN(this.coords.x_pointer)  ) {
30858                this.coords.x_pointer = 0;
30859            } else if (this.coords.x_pointer > this.coords.w_rs) {
30860                this.coords.x_pointer = this.coords.w_rs;
30861            }
30862
30863            this.coords.p_pointer = this.toFixed(this.coords.x_pointer / this.coords.w_rs * 100);
30864        },
30865
30866        convertToRealPercent: function (fake) {
30867            var full = 100 - this.coords.p_handle;
30868            return fake / full * 100;
30869        },
30870
30871        convertToFakePercent: function (real) {
30872            var full = 100 - this.coords.p_handle;
30873            return real / 100 * full;
30874        },
30875
30876        getHandleX: function () {
30877            var max = 100 - this.coords.p_handle,
30878                x = this.toFixed(this.coords.p_pointer - this.coords.p_gap);
30879
30880            if (x < 0) {
30881                x = 0;
30882            } else if (x > max) {
30883                x = max;
30884            }
30885
30886            return x;
30887        },
30888
30889        calcHandlePercent: function () {
30890            if (this.options.type === "single") {
30891                this.coords.w_handle = this.$cache.s_single.outerWidth(false);
30892            } else {
30893                this.coords.w_handle = this.$cache.s_from.outerWidth(false);
30894            }
30895
30896            this.coords.p_handle = this.toFixed(this.coords.w_handle / this.coords.w_rs * 100);
30897        },
30898
30899        /**
30900         * Find closest handle to pointer click
30901         *
30902         * @param real_x {Number}
30903         * @returns {String}
30904         */
30905        chooseHandle: function (real_x) {
30906            if (this.options.type === "single") {
30907                return "single";
30908            } else {
30909                var m_point = this.coords.p_from_real + ((this.coords.p_to_real - this.coords.p_from_real) / 2);
30910                if (real_x >= m_point) {
30911                    return this.options.to_fixed ? "from" : "to";
30912                } else {
30913                    return this.options.from_fixed ? "to" : "from";
30914                }
30915            }
30916        },
30917
30918        /**
30919         * Measure Min and Max labels width in percent
30920         */
30921        calcMinMax: function () {
30922            if (!this.coords.w_rs) {
30923                return;
30924            }
30925
30926            this.labels.p_min = this.labels.w_min / this.coords.w_rs * 100;
30927            this.labels.p_max = this.labels.w_max / this.coords.w_rs * 100;
30928        },
30929
30930        /**
30931         * Measure labels width and X in percent
30932         */
30933        calcLabels: function () {
30934            if (!this.coords.w_rs || this.options.hide_from_to) {
30935                return;
30936            }
30937
30938            if (this.options.type === "single") {
30939
30940                this.labels.w_single = this.$cache.single.outerWidth(false);
30941                this.labels.p_single_fake = this.labels.w_single / this.coords.w_rs * 100;
30942                this.labels.p_single_left = this.coords.p_single_fake + (this.coords.p_handle / 2) - (this.labels.p_single_fake / 2);
30943                this.labels.p_single_left = this.checkEdges(this.labels.p_single_left, this.labels.p_single_fake);
30944
30945            } else {
30946
30947                this.labels.w_from = this.$cache.from.outerWidth(false);
30948                this.labels.p_from_fake = this.labels.w_from / this.coords.w_rs * 100;
30949                this.labels.p_from_left = this.coords.p_from_fake + (this.coords.p_handle / 2) - (this.labels.p_from_fake / 2);
30950                this.labels.p_from_left = this.toFixed(this.labels.p_from_left);
30951                this.labels.p_from_left = this.checkEdges(this.labels.p_from_left, this.labels.p_from_fake);
30952
30953                this.labels.w_to = this.$cache.to.outerWidth(false);
30954                this.labels.p_to_fake = this.labels.w_to / this.coords.w_rs * 100;
30955                this.labels.p_to_left = this.coords.p_to_fake + (this.coords.p_handle / 2) - (this.labels.p_to_fake / 2);
30956                this.labels.p_to_left = this.toFixed(this.labels.p_to_left);
30957                this.labels.p_to_left = this.checkEdges(this.labels.p_to_left, this.labels.p_to_fake);
30958
30959                this.labels.w_single = this.$cache.single.outerWidth(false);
30960                this.labels.p_single_fake = this.labels.w_single / this.coords.w_rs * 100;
30961                this.labels.p_single_left = ((this.labels.p_from_left + this.labels.p_to_left + this.labels.p_to_fake) / 2) - (this.labels.p_single_fake / 2);
30962                this.labels.p_single_left = this.toFixed(this.labels.p_single_left);
30963                this.labels.p_single_left = this.checkEdges(this.labels.p_single_left, this.labels.p_single_fake);
30964
30965            }
30966        },
30967
30968
30969
30970        // =============================================================================================================
30971        // Drawings
30972
30973        /**
30974         * Main function called in request animation frame
30975         * to update everything
30976         */
30977        updateScene: function () {
30978            if (this.raf_id) {
30979                cancelAnimationFrame(this.raf_id);
30980                this.raf_id = null;
30981            }
30982
30983            clearTimeout(this.update_tm);
30984            this.update_tm = null;
30985
30986            if (!this.options) {
30987                return;
30988            }
30989
30990            this.drawHandles();
30991
30992            if (this.is_active) {
30993                this.raf_id = requestAnimationFrame(this.updateScene.bind(this));
30994            } else {
30995                this.update_tm = setTimeout(this.updateScene.bind(this), 300);
30996            }
30997        },
30998
30999        /**
31000         * Draw handles
31001         */
31002        drawHandles: function () {
31003            this.coords.w_rs = this.$cache.rs.outerWidth(false);
31004
31005            if (!this.coords.w_rs) {
31006                return;
31007            }
31008
31009            if (this.coords.w_rs !== this.coords.w_rs_old) {
31010                this.target = "base";
31011                this.is_resize = true;
31012            }
31013
31014            if (this.coords.w_rs !== this.coords.w_rs_old || this.force_redraw) {
31015                this.setMinMax();
31016                this.calc(true);
31017                this.drawLabels();
31018                if (this.options.grid) {
31019                    this.calcGridMargin();
31020                    this.calcGridLabels();
31021                }
31022                this.force_redraw = true;
31023                this.coords.w_rs_old = this.coords.w_rs;
31024                this.drawShadow();
31025            }
31026
31027            if (!this.coords.w_rs) {
31028                return;
31029            }
31030
31031            if (!this.dragging && !this.force_redraw && !this.is_key) {
31032                return;
31033            }
31034
31035            if (this.old_from !== this.result.from || this.old_to !== this.result.to || this.force_redraw || this.is_key) {
31036
31037                this.drawLabels();
31038
31039                this.$cache.bar[0].style.left = this.coords.p_bar_x + "%";
31040                this.$cache.bar[0].style.width = this.coords.p_bar_w + "%";
31041
31042                if (this.options.type === "single") {
31043                    this.$cache.bar[0].style.left = 0;
31044                    this.$cache.bar[0].style.width = this.coords.p_bar_w + this.coords.p_bar_x + "%";
31045
31046                    this.$cache.s_single[0].style.left = this.coords.p_single_fake + "%";
31047
31048                    this.$cache.single[0].style.left = this.labels.p_single_left + "%";
31049                } else {
31050                    this.$cache.s_from[0].style.left = this.coords.p_from_fake + "%";
31051                    this.$cache.s_to[0].style.left = this.coords.p_to_fake + "%";
31052
31053                    if (this.old_from !== this.result.from || this.force_redraw) {
31054                        this.$cache.from[0].style.left = this.labels.p_from_left + "%";
31055                    }
31056                    if (this.old_to !== this.result.to || this.force_redraw) {
31057                        this.$cache.to[0].style.left = this.labels.p_to_left + "%";
31058                    }
31059
31060                    this.$cache.single[0].style.left = this.labels.p_single_left + "%";
31061                }
31062
31063                this.writeToInput();
31064
31065                if ((this.old_from !== this.result.from || this.old_to !== this.result.to) && !this.is_start) {
31066                    this.$cache.input.trigger("change");
31067                    this.$cache.input.trigger("input");
31068                }
31069
31070                this.old_from = this.result.from;
31071                this.old_to = this.result.to;
31072
31073                // callbacks call
31074                if (!this.is_resize && !this.is_update && !this.is_start && !this.is_finish) {
31075                    this.callOnChange();
31076                }
31077                if (this.is_key || this.is_click) {
31078                    this.is_key = false;
31079                    this.is_click = false;
31080                    this.callOnFinish();
31081                }
31082
31083                this.is_update = false;
31084                this.is_resize = false;
31085                this.is_finish = false;
31086            }
31087
31088            this.is_start = false;
31089            this.is_key = false;
31090            this.is_click = false;
31091            this.force_redraw = false;
31092        },
31093
31094        /**
31095         * Draw labels
31096         * measure labels collisions
31097         * collapse close labels
31098         */
31099        drawLabels: function () {
31100            if (!this.options) {
31101                return;
31102            }
31103
31104            var values_num = this.options.values.length;
31105            var p_values = this.options.p_values;
31106            var text_single;
31107            var text_from;
31108            var text_to;
31109            var from_pretty;
31110            var to_pretty;
31111
31112            if (this.options.hide_from_to) {
31113                return;
31114            }
31115
31116            if (this.options.type === "single") {
31117
31118                if (values_num) {
31119                    text_single = this.decorate(p_values[this.result.from]);
31120                    this.$cache.single.html(text_single);
31121                } else {
31122                    from_pretty = this._prettify(this.result.from);
31123
31124                    text_single = this.decorate(from_pretty, this.result.from);
31125                    this.$cache.single.html(text_single);
31126                }
31127
31128                this.calcLabels();
31129
31130                if (this.labels.p_single_left < this.labels.p_min + 1) {
31131                    this.$cache.min[0].style.visibility = "hidden";
31132                } else {
31133                    this.$cache.min[0].style.visibility = "visible";
31134                }
31135
31136                if (this.labels.p_single_left + this.labels.p_single_fake > 100 - this.labels.p_max - 1) {
31137                    this.$cache.max[0].style.visibility = "hidden";
31138                } else {
31139                    this.$cache.max[0].style.visibility = "visible";
31140                }
31141
31142            } else {
31143
31144                if (values_num) {
31145
31146                    if (this.options.decorate_both) {
31147                        text_single = this.decorate(p_values[this.result.from]);
31148                        text_single += this.options.values_separator;
31149                        text_single += this.decorate(p_values[this.result.to]);
31150                    } else {
31151                        text_single = this.decorate(p_values[this.result.from] + this.options.values_separator + p_values[this.result.to]);
31152                    }
31153                    text_from = this.decorate(p_values[this.result.from]);
31154                    text_to = this.decorate(p_values[this.result.to]);
31155
31156                    this.$cache.single.html(text_single);
31157                    this.$cache.from.html(text_from);
31158                    this.$cache.to.html(text_to);
31159
31160                } else {
31161                    from_pretty = this._prettify(this.result.from);
31162                    to_pretty = this._prettify(this.result.to);
31163
31164                    if (this.options.decorate_both) {
31165                        text_single = this.decorate(from_pretty, this.result.from);
31166                        text_single += this.options.values_separator;
31167                        text_single += this.decorate(to_pretty, this.result.to);
31168                    } else {
31169                        text_single = this.decorate(from_pretty + this.options.values_separator + to_pretty, this.result.to);
31170                    }
31171                    text_from = this.decorate(from_pretty, this.result.from);
31172                    text_to = this.decorate(to_pretty, this.result.to);
31173
31174                    this.$cache.single.html(text_single);
31175                    this.$cache.from.html(text_from);
31176                    this.$cache.to.html(text_to);
31177
31178                }
31179
31180                this.calcLabels();
31181
31182                var min = Math.min(this.labels.p_single_left, this.labels.p_from_left),
31183                    single_left = this.labels.p_single_left + this.labels.p_single_fake,
31184                    to_left = this.labels.p_to_left + this.labels.p_to_fake,
31185                    max = Math.max(single_left, to_left);
31186
31187                if (this.labels.p_from_left + this.labels.p_from_fake >= this.labels.p_to_left) {
31188                    this.$cache.from[0].style.visibility = "hidden";
31189                    this.$cache.to[0].style.visibility = "hidden";
31190                    this.$cache.single[0].style.visibility = "visible";
31191
31192                    if (this.result.from === this.result.to) {
31193                        if (this.target === "from") {
31194                            this.$cache.from[0].style.visibility = "visible";
31195                        } else if (this.target === "to") {
31196                            this.$cache.to[0].style.visibility = "visible";
31197                        } else if (!this.target) {
31198                            this.$cache.from[0].style.visibility = "visible";
31199                        }
31200                        this.$cache.single[0].style.visibility = "hidden";
31201                        max = to_left;
31202                    } else {
31203                        this.$cache.from[0].style.visibility = "hidden";
31204                        this.$cache.to[0].style.visibility = "hidden";
31205                        this.$cache.single[0].style.visibility = "visible";
31206                        max = Math.max(single_left, to_left);
31207                    }
31208                } else {
31209                    this.$cache.from[0].style.visibility = "visible";
31210                    this.$cache.to[0].style.visibility = "visible";
31211                    this.$cache.single[0].style.visibility = "hidden";
31212                }
31213
31214                if (min < this.labels.p_min + 1) {
31215                    this.$cache.min[0].style.visibility = "hidden";
31216                } else {
31217                    this.$cache.min[0].style.visibility = "visible";
31218                }
31219
31220                if (max > 100 - this.labels.p_max - 1) {
31221                    this.$cache.max[0].style.visibility = "hidden";
31222                } else {
31223                    this.$cache.max[0].style.visibility = "visible";
31224                }
31225
31226            }
31227        },
31228
31229        /**
31230         * Draw shadow intervals
31231         */
31232        drawShadow: function () {
31233            var o = this.options,
31234                c = this.$cache,
31235
31236                is_from_min = typeof o.from_min === "number" && !isNaN(o.from_min),
31237                is_from_max = typeof o.from_max === "number" && !isNaN(o.from_max),
31238                is_to_min = typeof o.to_min === "number" && !isNaN(o.to_min),
31239                is_to_max = typeof o.to_max === "number" && !isNaN(o.to_max),
31240
31241                from_min,
31242                from_max,
31243                to_min,
31244                to_max;
31245
31246            if (o.type === "single") {
31247                if (o.from_shadow && (is_from_min || is_from_max)) {
31248                    from_min = this.convertToPercent(is_from_min ? o.from_min : o.min);
31249                    from_max = this.convertToPercent(is_from_max ? o.from_max : o.max) - from_min;
31250                    from_min = this.toFixed(from_min - (this.coords.p_handle / 100 * from_min));
31251                    from_max = this.toFixed(from_max - (this.coords.p_handle / 100 * from_max));
31252                    from_min = from_min + (this.coords.p_handle / 2);
31253
31254                    c.shad_single[0].style.display = "block";
31255                    c.shad_single[0].style.left = from_min + "%";
31256                    c.shad_single[0].style.width = from_max + "%";
31257                } else {
31258                    c.shad_single[0].style.display = "none";
31259                }
31260            } else {
31261                if (o.from_shadow && (is_from_min || is_from_max)) {
31262                    from_min = this.convertToPercent(is_from_min ? o.from_min : o.min);
31263                    from_max = this.convertToPercent(is_from_max ? o.from_max : o.max) - from_min;
31264                    from_min = this.toFixed(from_min - (this.coords.p_handle / 100 * from_min));
31265                    from_max = this.toFixed(from_max - (this.coords.p_handle / 100 * from_max));
31266                    from_min = from_min + (this.coords.p_handle / 2);
31267
31268                    c.shad_from[0].style.display = "block";
31269                    c.shad_from[0].style.left = from_min + "%";
31270                    c.shad_from[0].style.width = from_max + "%";
31271                } else {
31272                    c.shad_from[0].style.display = "none";
31273                }
31274
31275                if (o.to_shadow && (is_to_min || is_to_max)) {
31276                    to_min = this.convertToPercent(is_to_min ? o.to_min : o.min);
31277                    to_max = this.convertToPercent(is_to_max ? o.to_max : o.max) - to_min;
31278                    to_min = this.toFixed(to_min - (this.coords.p_handle / 100 * to_min));
31279                    to_max = this.toFixed(to_max - (this.coords.p_handle / 100 * to_max));
31280                    to_min = to_min + (this.coords.p_handle / 2);
31281
31282                    c.shad_to[0].style.display = "block";
31283                    c.shad_to[0].style.left = to_min + "%";
31284                    c.shad_to[0].style.width = to_max + "%";
31285                } else {
31286                    c.shad_to[0].style.display = "none";
31287                }
31288            }
31289        },
31290
31291
31292
31293        /**
31294         * Write values to input element
31295         */
31296        writeToInput: function () {
31297            if (this.options.type === "single") {
31298                if (this.options.values.length) {
31299                    this.$cache.input.prop("value", this.result.from_value);
31300                } else {
31301                    this.$cache.input.prop("value", this.result.from);
31302                }
31303                this.$cache.input.data("from", this.result.from);
31304            } else {
31305                if (this.options.values.length) {
31306                    this.$cache.input.prop("value", this.result.from_value + this.options.input_values_separator + this.result.to_value);
31307                } else {
31308                    this.$cache.input.prop("value", this.result.from + this.options.input_values_separator + this.result.to);
31309                }
31310                this.$cache.input.data("from", this.result.from);
31311                this.$cache.input.data("to", this.result.to);
31312            }
31313        },
31314
31315
31316
31317        // =============================================================================================================
31318        // Callbacks
31319
31320        callOnStart: function () {
31321            this.writeToInput();
31322
31323            if (this.options.onStart && typeof this.options.onStart === "function") {
31324                if (this.options.scope) {
31325                    this.options.onStart.call(this.options.scope, this.result);
31326                } else {
31327                    this.options.onStart(this.result);
31328                }
31329            }
31330        },
31331        callOnChange: function () {
31332            this.writeToInput();
31333
31334            if (this.options.onChange && typeof this.options.onChange === "function") {
31335                if (this.options.scope) {
31336                    this.options.onChange.call(this.options.scope, this.result);
31337                } else {
31338                    this.options.onChange(this.result);
31339                }
31340            }
31341        },
31342        callOnFinish: function () {
31343            this.writeToInput();
31344
31345            if (this.options.onFinish && typeof this.options.onFinish === "function") {
31346                if (this.options.scope) {
31347                    this.options.onFinish.call(this.options.scope, this.result);
31348                } else {
31349                    this.options.onFinish(this.result);
31350                }
31351            }
31352        },
31353        callOnUpdate: function () {
31354            this.writeToInput();
31355
31356            if (this.options.onUpdate && typeof this.options.onUpdate === "function") {
31357                if (this.options.scope) {
31358                    this.options.onUpdate.call(this.options.scope, this.result);
31359                } else {
31360                    this.options.onUpdate(this.result);
31361                }
31362            }
31363        },
31364
31365
31366
31367
31368        // =============================================================================================================
31369        // Service methods
31370
31371        toggleInput: function () {
31372            this.$cache.input.toggleClass("irs-hidden-input");
31373
31374            if (this.has_tab_index) {
31375                this.$cache.input.prop("tabindex", -1);
31376            } else {
31377                this.$cache.input.removeProp("tabindex");
31378            }
31379
31380            this.has_tab_index = !this.has_tab_index;
31381        },
31382
31383        /**
31384         * Convert real value to percent
31385         *
31386         * @param value {Number} X in real
31387         * @param no_min {boolean=} don't use min value
31388         * @returns {Number} X in percent
31389         */
31390        convertToPercent: function (value, no_min) {
31391            var diapason = this.options.max - this.options.min,
31392                one_percent = diapason / 100,
31393                val, percent;
31394
31395            if (!diapason) {
31396                this.no_diapason = true;
31397                return 0;
31398            }
31399
31400            if (no_min) {
31401                val = value;
31402            } else {
31403                val = value - this.options.min;
31404            }
31405
31406            percent = val / one_percent;
31407
31408            return this.toFixed(percent);
31409        },
31410
31411        /**
31412         * Convert percent to real values
31413         *
31414         * @param percent {Number} X in percent
31415         * @returns {Number} X in real
31416         */
31417        convertToValue: function (percent) {
31418            var min = this.options.min,
31419                max = this.options.max,
31420                min_decimals = min.toString().split(".")[1],
31421                max_decimals = max.toString().split(".")[1],
31422                min_length, max_length,
31423                avg_decimals = 0,
31424                abs = 0;
31425
31426            if (percent === 0) {
31427                return this.options.min;
31428            }
31429            if (percent === 100) {
31430                return this.options.max;
31431            }
31432
31433
31434            if (min_decimals) {
31435                min_length = min_decimals.length;
31436                avg_decimals = min_length;
31437            }
31438            if (max_decimals) {
31439                max_length = max_decimals.length;
31440                avg_decimals = max_length;
31441            }
31442            if (min_length && max_length) {
31443                avg_decimals = (min_length >= max_length) ? min_length : max_length;
31444            }
31445
31446            if (min < 0) {
31447                abs = Math.abs(min);
31448                min = +(min + abs).toFixed(avg_decimals);
31449                max = +(max + abs).toFixed(avg_decimals);
31450            }
31451
31452            var number = ((max - min) / 100 * percent) + min,
31453                string = this.options.step.toString().split(".")[1],
31454                result;
31455
31456            if (string) {
31457                number = +number.toFixed(string.length);
31458            } else {
31459                number = number / this.options.step;
31460                number = number * this.options.step;
31461
31462                number = +number.toFixed(0);
31463            }
31464
31465            if (abs) {
31466                number -= abs;
31467            }
31468
31469            if (string) {
31470                result = +number.toFixed(string.length);
31471            } else {
31472                result = this.toFixed(number);
31473            }
31474
31475            if (result < this.options.min) {
31476                result = this.options.min;
31477            } else if (result > this.options.max) {
31478                result = this.options.max;
31479            }
31480
31481            return result;
31482        },
31483
31484        /**
31485         * Round percent value with step
31486         *
31487         * @param percent {Number}
31488         * @returns percent {Number} rounded
31489         */
31490        calcWithStep: function (percent) {
31491            var rounded = Math.round(percent / this.coords.p_step) * this.coords.p_step;
31492
31493            if (rounded > 100) {
31494                rounded = 100;
31495            }
31496            if (percent === 100) {
31497                rounded = 100;
31498            }
31499
31500            return this.toFixed(rounded);
31501        },
31502
31503        checkMinInterval: function (p_current, p_next, type) {
31504            var o = this.options,
31505                current,
31506                next;
31507
31508            if (!o.min_interval) {
31509                return p_current;
31510            }
31511
31512            current = this.convertToValue(p_current);
31513            next = this.convertToValue(p_next);
31514
31515            if (type === "from") {
31516
31517                if (next - current < o.min_interval) {
31518                    current = next - o.min_interval;
31519                }
31520
31521            } else {
31522
31523                if (current - next < o.min_interval) {
31524                    current = next + o.min_interval;
31525                }
31526
31527            }
31528
31529            return this.convertToPercent(current);
31530        },
31531
31532        checkMaxInterval: function (p_current, p_next, type) {
31533            var o = this.options,
31534                current,
31535                next;
31536
31537            if (!o.max_interval) {
31538                return p_current;
31539            }
31540
31541            current = this.convertToValue(p_current);
31542            next = this.convertToValue(p_next);
31543
31544            if (type === "from") {
31545
31546                if (next - current > o.max_interval) {
31547                    current = next - o.max_interval;
31548                }
31549
31550            } else {
31551
31552                if (current - next > o.max_interval) {
31553                    current = next + o.max_interval;
31554                }
31555
31556            }
31557
31558            return this.convertToPercent(current);
31559        },
31560
31561        checkDiapason: function (p_num, min, max) {
31562            var num = this.convertToValue(p_num),
31563                o = this.options;
31564
31565            if (typeof min !== "number") {
31566                min = o.min;
31567            }
31568
31569            if (typeof max !== "number") {
31570                max = o.max;
31571            }
31572
31573            if (num < min) {
31574                num = min;
31575            }
31576
31577            if (num > max) {
31578                num = max;
31579            }
31580
31581            return this.convertToPercent(num);
31582        },
31583
31584        toFixed: function (num) {
31585            num = num.toFixed(20);
31586            return +num;
31587        },
31588
31589        _prettify: function (num) {
31590            if (!this.options.prettify_enabled) {
31591                return num;
31592            }
31593
31594            if (this.options.prettify && typeof this.options.prettify === "function") {
31595                return this.options.prettify(num);
31596            } else {
31597                return this.prettify(num);
31598            }
31599        },
31600
31601        prettify: function (num) {
31602            var n = num.toString();
31603            return n.replace(/(\d{1,3}(?=(?:\d\d\d)+(?!\d)))/g, "$1" + this.options.prettify_separator);
31604        },
31605
31606        checkEdges: function (left, width) {
31607            if (!this.options.force_edges) {
31608                return this.toFixed(left);
31609            }
31610
31611            if (left < 0) {
31612                left = 0;
31613            } else if (left > 100 - width) {
31614                left = 100 - width;
31615            }
31616
31617            return this.toFixed(left);
31618        },
31619
31620        validate: function () {
31621            var o = this.options,
31622                r = this.result,
31623                v = o.values,
31624                vl = v.length,
31625                value,
31626                i;
31627
31628            if (typeof o.min === "string") o.min = +o.min;
31629            if (typeof o.max === "string") o.max = +o.max;
31630            if (typeof o.from === "string") o.from = +o.from;
31631            if (typeof o.to === "string") o.to = +o.to;
31632            if (typeof o.step === "string") o.step = +o.step;
31633
31634            if (typeof o.from_min === "string") o.from_min = +o.from_min;
31635            if (typeof o.from_max === "string") o.from_max = +o.from_max;
31636            if (typeof o.to_min === "string") o.to_min = +o.to_min;
31637            if (typeof o.to_max === "string") o.to_max = +o.to_max;
31638
31639            if (typeof o.grid_num === "string") o.grid_num = +o.grid_num;
31640
31641            if (o.max < o.min) {
31642                o.max = o.min;
31643            }
31644
31645            if (vl) {
31646                o.p_values = [];
31647                o.min = 0;
31648                o.max = vl - 1;
31649                o.step = 1;
31650                o.grid_num = o.max;
31651                o.grid_snap = true;
31652
31653                for (i = 0; i < vl; i++) {
31654                    value = +v[i];
31655
31656                    if (!isNaN(value)) {
31657                        v[i] = value;
31658                        value = this._prettify(value);
31659                    } else {
31660                        value = v[i];
31661                    }
31662
31663                    o.p_values.push(value);
31664                }
31665            }
31666
31667            if (typeof o.from !== "number" || isNaN(o.from)) {
31668                o.from = o.min;
31669            }
31670
31671            if (typeof o.to !== "number" || isNaN(o.to)) {
31672                o.to = o.max;
31673            }
31674
31675            if (o.type === "single") {
31676
31677                if (o.from < o.min) o.from = o.min;
31678                if (o.from > o.max) o.from = o.max;
31679
31680            } else {
31681
31682                if (o.from < o.min) o.from = o.min;
31683                if (o.from > o.max) o.from = o.max;
31684
31685                if (o.to < o.min) o.to = o.min;
31686                if (o.to > o.max) o.to = o.max;
31687
31688                if (this.update_check.from) {
31689
31690                    if (this.update_check.from !== o.from) {
31691                        if (o.from > o.to) o.from = o.to;
31692                    }
31693                    if (this.update_check.to !== o.to) {
31694                        if (o.to < o.from) o.to = o.from;
31695                    }
31696
31697                }
31698
31699                if (o.from > o.to) o.from = o.to;
31700                if (o.to < o.from) o.to = o.from;
31701
31702            }
31703
31704            if (typeof o.step !== "number" || isNaN(o.step) || !o.step || o.step < 0) {
31705                o.step = 1;
31706            }
31707
31708            if (typeof o.from_min === "number" && o.from < o.from_min) {
31709                o.from = o.from_min;
31710            }
31711
31712            if (typeof o.from_max === "number" && o.from > o.from_max) {
31713                o.from = o.from_max;
31714            }
31715
31716            if (typeof o.to_min === "number" && o.to < o.to_min) {
31717                o.to = o.to_min;
31718            }
31719
31720            if (typeof o.to_max === "number" && o.from > o.to_max) {
31721                o.to = o.to_max;
31722            }
31723
31724            if (r) {
31725                if (r.min !== o.min) {
31726                    r.min = o.min;
31727                }
31728
31729                if (r.max !== o.max) {
31730                    r.max = o.max;
31731                }
31732
31733                if (r.from < r.min || r.from > r.max) {
31734                    r.from = o.from;
31735                }
31736
31737                if (r.to < r.min || r.to > r.max) {
31738                    r.to = o.to;
31739                }
31740            }
31741
31742            if (typeof o.min_interval !== "number" || isNaN(o.min_interval) || !o.min_interval || o.min_interval < 0) {
31743                o.min_interval = 0;
31744            }
31745
31746            if (typeof o.max_interval !== "number" || isNaN(o.max_interval) || !o.max_interval || o.max_interval < 0) {
31747                o.max_interval = 0;
31748            }
31749
31750            if (o.min_interval && o.min_interval > o.max - o.min) {
31751                o.min_interval = o.max - o.min;
31752            }
31753
31754            if (o.max_interval && o.max_interval > o.max - o.min) {
31755                o.max_interval = o.max - o.min;
31756            }
31757        },
31758
31759        decorate: function (num, original) {
31760            var decorated = "",
31761                o = this.options;
31762
31763            if (o.prefix) {
31764                decorated += o.prefix;
31765            }
31766
31767            decorated += num;
31768
31769            if (o.max_postfix) {
31770                if (o.values.length && num === o.p_values[o.max]) {
31771                    decorated += o.max_postfix;
31772                    if (o.postfix) {
31773                        decorated += " ";
31774                    }
31775                } else if (original === o.max) {
31776                    decorated += o.max_postfix;
31777                    if (o.postfix) {
31778                        decorated += " ";
31779                    }
31780                }
31781            }
31782
31783            if (o.postfix) {
31784                decorated += o.postfix;
31785            }
31786
31787            return decorated;
31788        },
31789
31790        updateFrom: function () {
31791            this.result.from = this.options.from;
31792            this.result.from_percent = this.convertToPercent(this.result.from);
31793            this.result.from_pretty = this._prettify(this.result.from);
31794            if (this.options.values) {
31795                this.result.from_value = this.options.values[this.result.from];
31796            }
31797        },
31798
31799        updateTo: function () {
31800            this.result.to = this.options.to;
31801            this.result.to_percent = this.convertToPercent(this.result.to);
31802            this.result.to_pretty = this._prettify(this.result.to);
31803            if (this.options.values) {
31804                this.result.to_value = this.options.values[this.result.to];
31805            }
31806        },
31807
31808        updateResult: function () {
31809            this.result.min = this.options.min;
31810            this.result.max = this.options.max;
31811            this.updateFrom();
31812            this.updateTo();
31813        },
31814
31815
31816        // =============================================================================================================
31817        // Grid
31818
31819        appendGrid: function () {
31820            if (!this.options.grid) {
31821                return;
31822            }
31823
31824            var o = this.options,
31825                i, z,
31826
31827                total = o.max - o.min,
31828                big_num = o.grid_num,
31829                big_p = 0,
31830                big_w = 0,
31831
31832                small_max = 4,
31833                local_small_max,
31834                small_p,
31835                small_w = 0,
31836
31837                result,
31838                html = '';
31839
31840
31841
31842            this.calcGridMargin();
31843
31844            if (o.grid_snap) {
31845                big_num = total / o.step;
31846            }
31847
31848            if (big_num > 50) big_num = 50;
31849            big_p = this.toFixed(100 / big_num);
31850
31851            if (big_num > 4) {
31852                small_max = 3;
31853            }
31854            if (big_num > 7) {
31855                small_max = 2;
31856            }
31857            if (big_num > 14) {
31858                small_max = 1;
31859            }
31860            if (big_num > 28) {
31861                small_max = 0;
31862            }
31863
31864            for (i = 0; i < big_num + 1; i++) {
31865                local_small_max = small_max;
31866
31867                big_w = this.toFixed(big_p * i);
31868
31869                if (big_w > 100) {
31870                    big_w = 100;
31871                }
31872                this.coords.big[i] = big_w;
31873
31874                small_p = (big_w - (big_p * (i - 1))) / (local_small_max + 1);
31875
31876                for (z = 1; z <= local_small_max; z++) {
31877                    if (big_w === 0) {
31878                        break;
31879                    }
31880
31881                    small_w = this.toFixed(big_w - (small_p * z));
31882
31883                    html += '<span class="irs-grid-pol small" style="left: ' + small_w + '%"></span>';
31884                }
31885
31886                html += '<span class="irs-grid-pol" style="left: ' + big_w + '%"></span>';
31887
31888                result = this.convertToValue(big_w);
31889                if (o.values.length) {
31890                    result = o.p_values[result];
31891                } else {
31892                    result = this._prettify(result);
31893                }
31894
31895                html += '<span class="irs-grid-text js-grid-text-' + i + '" style="left: ' + big_w + '%">' + result + '</span>';
31896            }
31897            this.coords.big_num = Math.ceil(big_num + 1);
31898
31899
31900
31901            this.$cache.cont.addClass("irs-with-grid");
31902            this.$cache.grid.html(html);
31903            this.cacheGridLabels();
31904        },
31905
31906        cacheGridLabels: function () {
31907            var $label, i,
31908                num = this.coords.big_num;
31909
31910            for (i = 0; i < num; i++) {
31911                $label = this.$cache.grid.find(".js-grid-text-" + i);
31912                this.$cache.grid_labels.push($label);
31913            }
31914
31915            this.calcGridLabels();
31916        },
31917
31918        calcGridLabels: function () {
31919            var i, label, start = [], finish = [],
31920                num = this.coords.big_num;
31921
31922            for (i = 0; i < num; i++) {
31923                this.coords.big_w[i] = this.$cache.grid_labels[i].outerWidth(false);
31924                this.coords.big_p[i] = this.toFixed(this.coords.big_w[i] / this.coords.w_rs * 100);
31925                this.coords.big_x[i] = this.toFixed(this.coords.big_p[i] / 2);
31926
31927                start[i] = this.toFixed(this.coords.big[i] - this.coords.big_x[i]);
31928                finish[i] = this.toFixed(start[i] + this.coords.big_p[i]);
31929            }
31930
31931            if (this.options.force_edges) {
31932                if (start[0] < -this.coords.grid_gap) {
31933                    start[0] = -this.coords.grid_gap;
31934                    finish[0] = this.toFixed(start[0] + this.coords.big_p[0]);
31935
31936                    this.coords.big_x[0] = this.coords.grid_gap;
31937                }
31938
31939                if (finish[num - 1] > 100 + this.coords.grid_gap) {
31940                    finish[num - 1] = 100 + this.coords.grid_gap;
31941                    start[num - 1] = this.toFixed(finish[num - 1] - this.coords.big_p[num - 1]);
31942
31943                    this.coords.big_x[num - 1] = this.toFixed(this.coords.big_p[num - 1] - this.coords.grid_gap);
31944                }
31945            }
31946
31947            this.calcGridCollision(2, start, finish);
31948            this.calcGridCollision(4, start, finish);
31949
31950            for (i = 0; i < num; i++) {
31951                label = this.$cache.grid_labels[i][0];
31952
31953                if (this.coords.big_x[i] !== Number.POSITIVE_INFINITY) {
31954                    label.style.marginLeft = -this.coords.big_x[i] + "%";
31955                }
31956            }
31957        },
31958
31959        // Collisions Calc Beta
31960        // TODO: Refactor then have plenty of time
31961        calcGridCollision: function (step, start, finish) {
31962            var i, next_i, label,
31963                num = this.coords.big_num;
31964
31965            for (i = 0; i < num; i += step) {
31966                next_i = i + (step / 2);
31967                if (next_i >= num) {
31968                    break;
31969                }
31970
31971                label = this.$cache.grid_labels[next_i][0];
31972
31973                if (finish[i] <= start[next_i]) {
31974                    label.style.visibility = "visible";
31975                } else {
31976                    label.style.visibility = "hidden";
31977                }
31978            }
31979        },
31980
31981        calcGridMargin: function () {
31982            if (!this.options.grid_margin) {
31983                return;
31984            }
31985
31986            this.coords.w_rs = this.$cache.rs.outerWidth(false);
31987            if (!this.coords.w_rs) {
31988                return;
31989            }
31990
31991            if (this.options.type === "single") {
31992                this.coords.w_handle = this.$cache.s_single.outerWidth(false);
31993            } else {
31994                this.coords.w_handle = this.$cache.s_from.outerWidth(false);
31995            }
31996            this.coords.p_handle = this.toFixed(this.coords.w_handle  / this.coords.w_rs * 100);
31997            this.coords.grid_gap = this.toFixed((this.coords.p_handle / 2) - 0.1);
31998
31999            this.$cache.grid[0].style.width = this.toFixed(100 - this.coords.p_handle) + "%";
32000            this.$cache.grid[0].style.left = this.coords.grid_gap + "%";
32001        },
32002
32003
32004
32005        // =============================================================================================================
32006        // Public methods
32007
32008        update: function (options) {
32009            if (!this.input) {
32010                return;
32011            }
32012
32013            this.is_update = true;
32014
32015            this.options.from = this.result.from;
32016            this.options.to = this.result.to;
32017            this.update_check.from = this.result.from;
32018            this.update_check.to = this.result.to;
32019
32020            this.options = $.extend(this.options, options);
32021            this.validate();
32022            this.updateResult(options);
32023
32024            this.toggleInput();
32025            this.remove();
32026            this.init(true);
32027        },
32028
32029        reset: function () {
32030            if (!this.input) {
32031                return;
32032            }
32033
32034            this.updateResult();
32035            this.update();
32036        },
32037
32038        destroy: function () {
32039            if (!this.input) {
32040                return;
32041            }
32042
32043            this.toggleInput();
32044            this.$cache.input.prop("readonly", false);
32045            $.data(this.input, "ionRangeSlider", null);
32046
32047            this.remove();
32048            this.input = null;
32049            this.options = null;
32050        }
32051    };
32052
32053    $.fn.ionRangeSlider = function (options) {
32054        return this.each(function() {
32055            if (!$.data(this, "ionRangeSlider")) {
32056                $.data(this, "ionRangeSlider", new IonRangeSlider(this, options, plugin_count++));
32057            }
32058        });
32059    };
32060
32061
32062
32063    // =================================================================================================================
32064    // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
32065    // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
32066
32067    // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
32068
32069    // MIT license
32070
32071    (function() {
32072        var lastTime = 0;
32073        var vendors = ['ms', 'moz', 'webkit', 'o'];
32074        for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
32075            window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
32076            window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
32077                || window[vendors[x]+'CancelRequestAnimationFrame'];
32078        }
32079
32080        if (!window.requestAnimationFrame)
32081            window.requestAnimationFrame = function(callback, element) {
32082                var currTime = new Date().getTime();
32083                var timeToCall = Math.max(0, 16 - (currTime - lastTime));
32084                var id = window.setTimeout(function() { callback(currTime + timeToCall); },
32085                    timeToCall);
32086                lastTime = currTime + timeToCall;
32087                return id;
32088            };
32089
32090        if (!window.cancelAnimationFrame)
32091            window.cancelAnimationFrame = function(id) {
32092                clearTimeout(id);
32093            };
32094    }());
32095
32096}));
32097
32098"use strict";
32099
32100var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
32101
32102function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
32103
32104function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { c
32104onstructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
32105
32106function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
32107
32108/*
32109 *
32110 * More info at [www.dropzonejs.com](http://www.dropzonejs.com)
32111 *
32112 * Copyright (c) 2012, Matias Meno
32113 *
32114 * Permission is hereby granted, free of charge, to any person obtaining a copy
32115 * of this software and associated documentation files (the "Software"), to deal
32116 * in the Software without restriction, including without limitation the rights
32117 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
32118 * copies of the Software, and to permit persons to whom the Software is
32119 * furnished to do so, subject to the following conditions:
32120 *
32121 * The above copyright notice and this permission notice shall be included in
32122 * all copies or substantial portions of the Software.
32123 *
32124 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32125 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32126 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32127 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32128 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32129 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32130 * THE SOFTWARE.
32131 *
32132 */
32133
32134// The Emitter class provides the ability to call `.on()` on Dropzone to listen
32135// to events.
32136// It is strongly based on component's emitter class, and I removed the
32137// functionality because of the dependency hell with different frameworks.
32138var Emitter = function () {
32139  function Emitter() {
32140    _classCallCheck(this, Emitter);
32141  }
32142
32143  _createClass(Emitter, [{
32144    key: "on",
32145
32146    // Add an event listener for given event
32147    value: function on(event, fn) {
32148      this._callbacks = this._callbacks || {};
32149      // Create namespace for this event
32150      if (!this._callbacks[event]) {
32151        this._callbacks[event] = [];
32152      }
32153      this._callbacks[event].push(fn);
32154      return this;
32155    }
32156  }, {
32157    key: "emit",
32158    value: function emit(event) {
32159      this._callbacks = this._callbacks || {};
32160      var callbacks = this._callbacks[event];
32161
32162      if (callbacks) {
32163        for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
32164          args[_key - 1] = arguments[_key];
32165        }
32166
32167        for (var _iterator = callbacks, _isArray = true, _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
32168          var _ref;
32169
32170          if (_isArray) {
32171            if (_i >= _iterator.length) break;
32172            _ref = _iterator[_i++];
32173          } else {
32174            _i = _iterator.next();
32175            if (_i.done) break;
32176            _ref = _i.value;
32177          }
32178
32179          var callback = _ref;
32180
32181          callback.apply(this, args);
32182        }
32183      }
32184
32185      return this;
32186    }
32187
32188    // Remove event listener for given event. If fn is not provided, all event
32189    // listeners for that event will be removed. If neither is provided, all
32190    // event listeners will be removed.
32191
32192  }, {
32193    key: "off",
32194    value: function off(event, fn) {
32195      if (!this._callbacks || arguments.length === 0) {
32196        this._callbacks = {};
32197        return this;
32198      }
32199
32200      // specific event
32201      var callbacks = this._callbacks[event];
32202      if (!callbacks) {
32203        return this;
32204      }
32205
32206      // remove all handlers
32207      if (arguments.length === 1) {
32208        delete this._callbacks[event];
32209        return this;
32210      }
32211
32212      // remove specific handler
32213      for (var i = 0; i < callbacks.length; i++) {
32214        var callback = callbacks[i];
32215        if (callback === fn) {
32216          callbacks.splice(i, 1);
32217          break;
32218        }
32219      }
32220
32221      return this;
32222    }
32223  }]);
32224
32225  return Emitter;
32226}();
32227
32228var Dropzone = function (_Emitter) {
32229  _inherits(Dropzone, _Emitter);
32230
32231  _createClass(Dropzone, null, [{
32232    key: "initClass",
32233    value: function initClass() {
32234
32235      // Exposing the emitter class, mainly for tests
32236      this.prototype.Emitter = Emitter;
32237
32238      /*
32239       This is a list of all available events you can register on a dropzone object.
32240        You can register an event handler like this:
32241        dropzone.on("dragEnter", function() { });
32242        */
32243      this.prototype.events = ["drop", "dragstart", "dragend", "dragenter", "dragover", "dragleave", "addedfile", "addedfiles", "removedfile", "thumbnail", "error", "errormultiple", "processing", "processingmultiple", "uploadprogress", "totaluploadprogress", "sending", "sendingmultiple", "success", "successmultiple", "canceled", "canceledmultiple", "complete", "completemultiple", "reset", "maxfilesexceeded", "maxfilesreached", "queuecomplete"];
32244
32245      this.prototype.defaultOptions = {
32246        /**
32247         * Has to be specified on elements other than form (or when the form
32248         * doesn't have an `action` attribute). You can also
32249         * provide a function that will be called with `files` and
32250         * must return the url (since `v3.12.0`)
32251         */
32252        url: null,
32253
32254        /**
32255         * Can be changed to `"put"` if necessary. You can also provide a function
32256         * that will be called with `files` and must return the method (since `v3.12.0`).
32257         */
32258        method: "post",
32259
32260        /**
32261         * Will be set on the XHRequest.
32262         */
32263        withCredentials: false,
32264
32265        /**
32266         * The timeout for the XHR requests in milliseconds (since `v4.4.0`).
32267         */
32268        timeout: 30000,
32269
32270        /**
32271         * How many file uploads to process in parallel (See the
32272         * Enqueuing file uploads* documentation section for more info)
32273         */
32274        parallelUploads: 2,
32275
32276        /**
32277         * Whether to send multiple files in one request. If
32278         * this it set to true, then the fallback file input element will
32279         * have the `multiple` attribute as well. This option will
32280         * also trigger additional events (like `processingmultiple`). See the events
32281         * documentation section for more information.
32282         */
32283        uploadMultiple: false,
32284
32285        /**
32286         * Whether you want files to be uploaded in chunks to your server. This can't be
32287         * used in combination with `uploadMultiple`.
32288         *
32289         * See [chunksUploaded](#config-chunksUploaded) for the callback to finalise an upload.
32290         */
32291        chunking: false,
32292
32293        /**
32294         * If `chunking` is enabled, this defines whether **every** file should be chunked,
32295         * even if the file size is below chunkSize. This means, that the additional chunk
32296         * form data will be submitted and the `chunksUploaded` callback will be invoked.
32297         */
32298        forceChunking: false,
32299
32300        /**
32301         * If `chunking` is `true`, then this defines the chunk size in bytes.
32302         */
32303        chunkSize: 2000000,
32304
32305        /**
32306         * If `true`, the individual chunks of a file are being uploaded simultaneously.
32307         */
32308        parallelChunkUploads: false,
32309
32310        /**
32311         * Whether a chunk should be retried if it fails.
32312         */
32313        retryChunks: false,
32314
32315        /**
32316         * If `retryChunks` is true, how many times should it be retried.
32317         */
32318        retryChunksLimit: 3,
32319
32320        /**
32321         * If not `null` defines how many files this Dropzone handles. If it exceeds,
32322         * the event `maxfilesexceeded` will be called. The dropzone element gets the
32323         * class `dz-max-files-reached` accordingly so you can provide visual feedback.
32324         */
32325        maxFilesize: 256,
32326
32327        /**
32328         * The name of the file param that gets transferred.
32329         * **NOTE**: If you have the option  `uploadMultiple` set to `true`, then
32330         * Dropzone will append `[]` to the name.
32331         */
32332        paramName: "file",
32333
32334        /**
32335         * Whether thumbnails for images should be generated
32336         */
32337        createImageThumbnails: true,
32338
32339        /**
32340         * In MB. When the filename exceeds this limit, the thumbnail will not be generated.
32341         */
32342        maxThumbnailFilesize: 10,
32343
32344        /**
32345         * If `null`, the ratio of the image will be used to calculate it.
32346         */
32347        thumbnailWidth: 120,
32348
32349        /**
32350         * The same as `thumbnailWidth`. If both are null, images will not be resized.
32351         */
32352        thumbnailHeight: 120,
32353
32354        /**
32355         * How the images should be scaled down in case both, `thumbnailWidth` and `thumbnailHeight` are provided.
32356         * Can be either `contain` or `crop`.
32357         */
32358        thumbnailMethod: 'crop',
32359
32360        /**
32361         * If set, images will be resized to these dimensions before being **uploaded**.
32362         * If only one, `resizeWidth` **or** `resizeHeight` is provided, the original aspect
32363         * ratio of the file will be preserved.
32364         *
32365         * The `options.transformFile` function uses these options, so if the `transformFile` function
32366         * is overridden, these options don't do anything.
32367         */
32368        resizeWidth: null,
32369
32370        /**
32371         * See `resizeWidth`.
32372         */
32373        resizeHeight: null,
32374
32375        /**
32376         * The mime type of the resized image (before it gets uploaded to the server).
32377         * If `null` the original mime type will be used. To force jpeg, for example, use `image/jpeg`.
32378         * See `resizeWidth` for more information.
32379         */
32380        resizeMimeType: null,
32381
32382        /**
32383         * The quality of the resized images. See `resizeWidth`.
32384         */
32385        resizeQuality: 0.8,
32386
32387        /**
32388         * How the images should be scaled down in case both, `resizeWidth` and `resizeHeight` are provided.
32389         * Can be either `contain` or `crop`.
32390         */
32391        resizeMethod: 'contain',
32392
32393        /**
32394         * The base that is used to calculate the filesize. You can change this to
32395         * 1024 if you would rather display kibibytes, mebibytes, etc...
32396         * 1024 is technically incorrect, because `1024 bytes` are `1 kibibyte` not `1 kilobyte`.
32397         * You can change this to `1024` if you don't care about validity.
32398         */
32399        filesizeBase: 1000,
32400
32401        /**
32402         * Can be used to limit the maximum number of files that will be handled by this Dropzone
32403         */
32404        maxFiles: null,
32405
32406        /**
32407         * An optional object to send additional headers to the server. Eg:
32408         * `{ "My-Awesome-Header": "header value" }`
32409         */
32410        headers: null,
32411
32412        /**
32413         * If `true`, the dropzone element itself will be clickable, if `false`
32414         * nothing will be clickable.
32415         *
32416         * You can also pass an HTML element, a CSS selector (for multiple elements)
32417         * or an array of those. In that case, all of those elements will trigger an
32418         * upload when clicked.
32419         */
32420        clickable: true,
32421
32422        /**
32423         * Whether hidden files in directories should be ignored.
32424         */
32425        ignoreHiddenFiles: true,
32426
32427        /**
32428         * The default implementation of `accept` checks the file's mime type or
32429         * extension against this list. This is a comma separated list of mime
32430         * types or file extensions.
32431         *
32432         * Eg.: `image/*,application/pdf,.psd`
32433         *
32434         * If the Dropzone is `clickable` this option will also be used as
32435         * [`accept`](https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept)
32436         * parameter on the hidden file input as well.
32437         */
32438        acceptedFiles: null,
32439
32440        /**
32441         * **Deprecated!**
32442         * Use acceptedFiles instead.
32443         */
32444        acceptedMimeTypes: null,
32445
32446        /**
32447         * If false, files will be added to the queue but the queue will not be
32448         * processed automatically.
32449         * This can be useful if you need some additional user input before sending
32450         * files (or if you want want all files sent at once).
32451         * If you're ready to send the file simply call `myDropzone.processQueue()`.
32452         *
32453         * See the [enqueuing file uploads](#enqueuing-file-uploads) documentation
32454         * section for more information.
32455         */
32456        autoProcessQueue: true,
32457
32458        /**
32459         * If false, files added to the dropzone will not be queued by default.
32460         * You'll have to call `enqueueFile(file)` manually.
32461         */
32462        autoQueue: true,
32463
32464        /**
32465         * If `true`, this will add a link to every file preview to remove or cancel (if
32466         * already uploading) the file. The `dictCancelUpload`, `dictCancelUploadConfirmation`
32467         * and `dictRemoveFile` options are used for the wording.
32468         */
32469        addRemoveLinks: false,
32470
32471        /**
32472         * Defines where to display the file previews – if `null` the
32473         * Dropzone element itself is used. Can be a plain `HTMLElement` or a CSS
32474         * selector. The element should have the `dropzone-previews` class so
32475         * the previews are displayed properly.
32476         */
32477        previewsContainer: null,
32478
32479        /**
32480         * This is the element the hidden input field (which is used when clicking on the
32481         * dropzone to trigger file selection) will be appended to. This might
32482         * be important in case you use frameworks to switch the content of your page.
32483         *
32484         * Can be a selector string, or an element directly.
32485         */
32486        hiddenInputContainer: "body",
32487
32488        /**
32489         * If null, no capture type will be specified
32490         * If camera, mobile devices will skip the file selection and choose camera
32491         * If microphone, mobile devices will skip the file selection and choose the microphone
32492         * If camcorder, mobile devices will skip the file selection and choose the camera in video mode
32493         * On apple devices multiple must be set to false.  AcceptedFiles may need to
32494         * be set to an appropriate mime type (e.g. "image/*", "audio/*", or "video/*").
32495         */
32496        capture: null,
32497
32498        /**
32499         * **Deprecated**. Use `renameFile` instead.
32500         */
32501        renameFilename: null,
32502
32503        /**
32504         * A function that is invoked before the file is uploaded to the server and renames the file.
32505         * This function gets the `File` as argument and can use the `file.name`. The actual name of the
32506         * file that gets used during the upload can be accessed through `file.upload.filename`.
32507         */
32508        renameFile: null,
32509
32510        /**
32511         * If `true` the fallback will be forced. This is very useful to test your server
32512         * implementations first and make sure that everything works as
32513         * expected without dropzone if you experience problems, and to test
32514         * how your fallbacks will look.
32515         */
32516        forceFallback: false,
32517
32518        /**
32519         * The text used before any files are dropped.
32520         */
32521        dictDefaultMessage: "Drop files here to upload",
32522
32523        /**
32524         * The text that replaces the default message text it the browser is not supported.
32525         */
32526        dictFallbackMessage: "Your browser does not support drag'n'drop file uploads.",
32527
32528        /**
32529         * The text that will be added before the fallback form.
32530         * If you provide a  fallback element yourself, or if this option is `null` this will
32531         * be ignored.
32532         */
32533        dictFallbackText: "Please use the fallback form below to upload your files like in the olde
32533n days.",
32534
32535        /**
32536         * If the filesize is too big.
32537         * `{{filesize}}` and `{{maxFilesize}}` will be replaced with the respective configuration values.
32538         */
32539        dictFileTooBig: "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.",
32540
32541        /**
32542         * If the file doesn't match the file type.
32543         */
32544        dictInvalidFileType: "You can't upload files of this type.",
32545
32546        /**
32547         * If the server response was invalid.
32548         * `{{statusCode}}` will be replaced with the servers status code.
32549         */
32550        dictResponseError: "Server responded with {{statusCode}} code.",
32551
32552        /**
32553         * If `addRemoveLinks` is true, the text to be used for the cancel upload link.
32554         */
32555        dictCancelUpload: "Cancel upload",
32556
32557        /**
32558         * The text that is displayed if an upload was manually canceled
32559         */
32560        dictUploadCanceled: "Upload canceled.",
32561
32562        /**
32563         * If `addRemoveLinks` is true, the text to be used for confirmation when cancelling upload.
32564         */
32565        dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?",
32566
32567        /**
32568         * If `addRemoveLinks` is true, the text to be used to remove a file.
32569         */
32570        dictRemoveFile: "Remove file",
32571
32572        /**
32573         * If this is not null, then the user will be prompted before removing a file.
32574         */
32575        dictRemoveFileConfirmation: null,
32576
32577        /**
32578         * Displayed if `maxFiles` is st and exceeded.
32579         * The string `{{maxFiles}}` will be replaced by the configuration value.
32580         */
32581        dictMaxFilesExceeded: "You can not upload any more files.",
32582
32583        /**
32584         * Allows you to translate the different units. Starting with `tb` for terabytes and going down to
32585         * `b` for bytes.
32586         */
32587        dictFileSizeUnits: { tb: "TB", gb: "GB", mb: "MB", kb: "KB", b: "b" },
32588        /**
32589         * Called when dropzone initialized
32590         * You can add event listeners here
32591         */
32592        init: function init() {},
32593
32594
32595        /**
32596         * Can be an **object** of additional parameters to transfer to the server, **or** a `Function`
32597         * that gets invoked with the `files`, `xhr` and, if it's a chunked upload, `chunk` arguments. In case
32598         * of a function, this needs to return a map.
32599         *
32600         * The default implementation does nothing for normal uploads, but adds relevant information for
32601         * chunked uploads.
32602         *
32603         * This is the same as adding hidden input fields in the form element.
32604         */
32605        params: function params(files, xhr, chunk) {
32606          if (chunk) {
32607            return {
32608              dzuuid: chunk.file.upload.uuid,
32609              dzchunkindex: chunk.index,
32610              dztotalfilesize: chunk.file.size,
32611              dzchunksize: this.options.chunkSize,
32612              dztotalchunkcount: chunk.file.upload.totalChunkCount,
32613              dzchunkbyteoffset: chunk.index * this.options.chunkSize
32614            };
32615          }
32616        },
32617
32618
32619        /**
32620         * A function that gets a [file](https://developer.mozilla.org/en-US/docs/DOM/File)
32621         * and a `done` function as parameters.
32622         *
32623         * If the done function is invoked without arguments, the file is "accepted" and will
32624         * be processed. If you pass an error message, the file is rejected, and the error
32625         * message will be displayed.
32626         * This function will not be called if the file is too big or doesn't match the mime types.
32627         */
32628        accept: function accept(file, done) {
32629          return done();
32630        },
32631
32632
32633        /**
32634         * The callback that will be invoked when all chunks have been uploaded for a file.
32635         * It gets the file for which the chunks have been uploaded as the first parameter,
32636         * and the `done` function as second. `done()` needs to be invoked when everything
32637         * needed to finish the upload process is done.
32638         */
32639        chunksUploaded: function chunksUploaded(file, done) {
32640          done();
32641        },
32642
32643        /**
32644         * Gets called when the browser is not supported.
32645         * The default implementation shows the fallback input field and adds
32646         * a text.
32647         */
32648        fallback: function fallback() {
32649          // This code should pass in IE7... :(
32650          var messageElement = void 0;
32651          this.element.className = this.element.className + " dz-browser-not-supported";
32652
32653          for (var _iterator2 = this.element.getElementsByTagName("div"), _isArray2 = true, _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
32654            var _ref2;
32655
32656            if (_isArray2) {
32657              if (_i2 >= _iterator2.length) break;
32658              _ref2 = _iterator2[_i2++];
32659            } else {
32660              _i2 = _iterator2.next();
32661              if (_i2.done) break;
32662              _ref2 = _i2.value;
32663            }
32664
32665            var child = _ref2;
32666
32667            if (/(^| )dz-message($| )/.test(child.className)) {
32668              messageElement = child;
32669              child.className = "dz-message"; // Removes the 'dz-default' class
32670              break;
32671            }
32672          }
32673          if (!messageElement) {
32674            messageElement = Dropzone.createElement("<div class=\"dz-message\"><span></span></div>");
32675            this.element.appendChild(messageElement);
32676          }
32677
32678          var span = messageElement.getElementsByTagName("span")[0];
32679          if (span) {
32680            if (span.textContent != null) {
32681              span.textContent = this.options.dictFallbackMessage;
32682            }
vendor: 16,384 bytes, lines 32682-33033
32682 else if (span.innerText != null) {
32683              span.innerText = this.options.dictFallbackMessage;
32684            }
32685          }
32686
32687          return this.element.appendChild(this.getFallbackForm());
32688        },
32689
32690
32691        /**
32692         * Gets called to calculate the thumbnail dimensions.
32693         *
32694         * It gets `file`, `width` and `height` (both may be `null`) as parameters and must return an object containing:
32695         *
32696         *  - `srcWidth` & `srcHeight` (required)
32697         *  - `trgWidth` & `trgHeight` (required)
32698         *  - `srcX` & `srcY` (optional, default `0`)
32699         *  - `trgX` & `trgY` (optional, default `0`)
32700         *
32701         * Those values are going to be used by `ctx.drawImage()`.
32702         */
32703        resize: function resize(file, width, height, resizeMethod) {
32704          var info = {
32705            srcX: 0,
32706            srcY: 0,
32707            srcWidth: file.width,
32708            srcHeight: file.height
32709          };
32710
32711          var srcRatio = file.width / file.height;
32712
32713          // Automatically calculate dimensions if not specified
32714          if (width == null && height == null) {
32715            width = info.srcWidth;
32716            height = info.srcHeight;
32717          } else if (width == null) {
32718            width = height * srcRatio;
32719          } else if (height == null) {
32720            height = width / srcRatio;
32721          }
32722
32723          // Make sure images aren't upscaled
32724          width = Math.min(width, info.srcWidth);
32725          height = Math.min(height, info.srcHeight);
32726
32727          var trgRatio = width / height;
32728
32729          if (info.srcWidth > width || info.srcHeight > height) {
32730            // Image is bigger and needs rescaling
32731            if (resizeMethod === 'crop') {
32732              if (srcRatio > trgRatio) {
32733                info.srcHeight = file.height;
32734                info.srcWidth = info.srcHeight * trgRatio;
32735              } else {
32736                info.srcWidth = file.width;
32737                info.srcHeight = info.srcWidth / trgRatio;
32738              }
32739            } else if (resizeMethod === 'contain') {
32740              // Method 'contain'
32741              if (srcRatio > trgRatio) {
32742                height = width / srcRatio;
32743              } else {
32744                width = height * srcRatio;
32745              }
32746            } else {
32747              throw new Error("Unknown resizeMethod '" + resizeMethod + "'");
32748            }
32749          }
32750
32751          info.srcX = (file.width - info.srcWidth) / 2;
32752          info.srcY = (file.height - info.srcHeight) / 2;
32753
32754          info.trgWidth = width;
32755          info.trgHeight = height;
32756
32757          return info;
32758        },
32759
32760
32761        /**
32762         * Can be used to transform the file (for example, resize an image if necessary).
32763         *
32764         * The default implementation uses `resizeWidth` and `resizeHeight` (if provided) and resizes
32765         * images according to those dimensions.
32766         *
32767         * Gets the `file` as the first parameter, and a `done()` function as the second, that needs
32768         * to be invoked with the file when the transformation is done.
32769         */
32770        transformFile: function transformFile(file, done) {
32771          if ((this.options.resizeWidth || this.options.resizeHeight) && file.type.match(/image.*/)) {
32772            return this.resizeImage(file, this.options.resizeWidth, this.options.resizeHeight, this.options.resizeMethod, done);
32773          } else {
32774            return done(file);
32775          }
32776        },
32777
32778
32779        /**
32780         * A string that contains the template used for each dropped
32781         * file. Change it to fulfill your needs but make sure to properly
32782         * provide all elements.
32783         *
32784         * If you want to use an actual HTML element instead of providing a String
32785         * as a config option, you could create a div with the id `tpl`,
32786         * put the template inside it and provide the element like this:
32787         *
32788         *     document
32789         *       .querySelector('#tpl')
32790         *       .innerHTML
32791         *
32792         */
32793        previewTemplate: "<div class=\"dz-preview dz-file-preview\">\n  <div class=\"dz-image\"><img data-dz-thumbnail /></div>\n  <div class=\"dz-details\">\n    <div class=\"dz-size\"><span data-dz-size></span></div>\n    <div class=\"dz-filename\"><span data-dz-name></span></div>\n  </div>\n  <div class=\"dz-progress\"><span class=\"dz-upload\" data-dz-uploadprogress></span></div>\n  <div class=\"dz-error-message\"><span data-dz-errormessage></span></div>\n  <div class=\"dz-success-mark\">\n    <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n      <title>Check</title>\n      <defs></defs>\n      <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n        <path d=\"M23.5,31.8431458 L17.5852419,25.9283877 C16.0248253,24.3679711 13.4910294,24.366835 11.9289322,25.9289322 C10.3700136,27.4878508 10.3665912,30.0234455 11.9283877,31.5852419 L20.4147581,40.0716123 C20.5133999,40.1702541 20.6159315,40.2626649 20.7218615,40.3488435 C22.2835669,41.8725651 24.794234,41.8626202 26.3461564,40.3106978 L43.3106978,23.3461564 C44.8771021,21.7797521 44.8758057,19.2483887 43.3137085,17.6862915 C41.7547899,16.1273729 39.2176035,16.1255422 37.6538436,17.6893022 L23.5,31.8431458 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" id=\"Oval-2\" stroke-opacity=\"0.198794158\" stroke=\"#747474\" fill-opacity=\"0.816519475\" fill=\"#FFFFFF\" sketch:type=\"MSShapeGroup\"></path>\n      </g>\n    </svg>\n  </div>\n  <div class=\"dz-error-mark\">\n    <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n      <title>Error</title>\n      <defs></defs>\n      <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n        <g id=\"Check-+-Oval-2\" sketch:type=\"MSLayerGroup\" stroke=\"#747474\" stroke-opacity=\"0.198794158\" fill=\"#FFFFFF\" fill-opacity=\"0.816519475\">\n          <path d=\"M32.6568542,29 L38.3106978,23.3461564 C39.8771021,21.7797521 39.8758057,19.2483887 38.3137085,17.6862915 C36.7547899,16.1273729 34.2176035,16.1255422 32.6538436,17.6893022 L27,23.3431458 L21.3461564,17.6893022 C19.7823965,16.1255422 17.2452101,16.1273729 15.6862915,17.6862915 C14.1241943,19.2483887 14.1228979,21.7797521 15.6893022,23.3461564 L21.3431458,29 L15.6893022,34.6538436 C14.1228979,36.2202479 14.1241943,38.7516113 15.6862915,40.3137085 C17.2452101,41.8726271 19.7823965,41.8744578 21.3461564,40.3106978 L27,34.6568542 L32.6538436,40.3106978 C34.2176035,41.8744578 36.7547899,41.8726271 38.3137085,40.3137085 C39.8758057,38.7516113 39.8771021,36.2202479 38.3106978,34.6538436 L32.6568542,29 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" id=\"Oval-2\" sketch:type=\"MSShapeGroup\"></path>\n        </g>\n      </g>\n    </svg>\n  </div>\n</div>",
32794
32795        // END OPTIONS
32796        // (Required by the dropzone documentation parser)
32797
32798
32799        /*
32800         Those functions register themselves to the events on init and handle all
32801         the user interface specific stuff. Overwriting them won't break the upload
32802         but can break the way it's displayed.
32803         You can overwrite them if you don't like the default behavior. If you just
32804         want to add an additional event handler, register it on the dropzone object
32805         and don't overwrite those options.
32806         */
32807
32808        // Those are self explanatory and simply concern the DragnDrop.
32809        drop: function drop(e) {
32810          return this.element.classList.remove("dz-drag-hover");
32811        },
32812        dragstart: function dragstart(e) {},
32813        dragend: function dragend(e) {
32814          return this.element.classList.remove("dz-drag-hover");
32815        },
32816        dragenter: function dragenter(e) {
32817          return this.element.classList.add("dz-drag-hover");
32818        },
32819        dragover: function dragover(e) {
32820          return this.element.classList.add("dz-drag-hover");
32821        },
32822        dragleave: function dragleave(e) {
32823          return this.element.classList.remove("dz-drag-hover");
32824        },
32825        paste: function paste(e) {},
32826
32827
32828        // Called whenever there are no files left in the dropzone anymore, and the
32829        // dropzone should be displayed as if in the initial state.
32830        reset: function reset() {
32831          return this.element.classList.remove("dz-started");
32832        },
32833
32834
32835        // Called when a file is added to the queue
32836        // Receives `file`
32837        addedfile: function addedfile(file) {
32838          var _this2 = this;
32839
32840          if (this.element === this.previewsContainer) {
32841            this.element.classList.add("dz-started");
32842          }
32843
32844          if (this.previewsContainer) {
32845            file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim());
32846            file.previewTemplate = file.previewElement; // Backwards compatibility
32847
32848            this.previewsContainer.appendChild(file.previewElement);
32849            for (var _iterator3 = file.previewElement.querySelectorAll("[data-dz-name]"), _isArray3 = true, _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
32850              var _ref3;
32851
32852              if (_isArray3) {
32853                if (_i3 >= _iterator3.length) break;
32854                _ref3 = _iterator3[_i3++];
32855              } else {
32856                _i3 = _iterator3.next();
32857                if (_i3.done) break;
32858                _ref3 = _i3.value;
32859              }
32860
32861              var node = _ref3;
32862
32863              node.textContent = file.name;
32864            }
32865            for (var _iterator4 = file.previewElement.querySelectorAll("[data-dz-size]"), _isArray4 = true, _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) {
32866              if (_isArray4) {
32867                if (_i4 >= _iterator4.length) break;
32868                node = _iterator4[_i4++];
32869              } else {
32870                _i4 = _iterator4.next();
32871                if (_i4.done) break;
32872                node = _i4.value;
32873              }
32874
32875              node.innerHTML = this.filesize(file.size);
32876            }
32877
32878            if (this.options.addRemoveLinks) {
32879              file._removeLink = Dropzone.createElement("<a class=\"dz-remove\" href=\"javascript:undefined;\" data-dz-remove>" + this.options.dictRemoveFile + "</a>");
32880              file.previewElement.appendChild(file._removeLink);
32881            }
32882
32883            var removeFileEvent = function removeFileEvent(e) {
32884              e.preventDefault();
32885              e.stopPropagation();
32886              if (file.status === Dropzone.UPLOADING) {
32887                return Dropzone.confirm(_this2.options.dictCancelUploadConfirmation, function () {
32888                  return _this2.removeFile(file);
32889                });
32890              } else {
32891                if (_this2.options.dictRemoveFileConfirmation) {
32892                  return Dropzone.confirm(_this2.options.dictRemoveFileConfirmation, function () {
32893                    return _this2.removeFile(file);
32894                  });
32895                } else {
32896                  return _this2.removeFile(file);
32897                }
32898              }
32899            };
32900
32901            for (var _iterator5 = file.previewElement.querySelectorAll("[data-dz-remove]"), _isArray5 = true, _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) {
32902              var _ref4;
32903
32904              if (_isArray5) {
32905                if (_i5 >= _iterator5.length) break;
32906                _ref4 = _iterator5[_i5++];
32907              } else {
32908                _i5 = _iterator5.next();
32909                if (_i5.done) break;
32910                _ref4 = _i5.value;
32911              }
32912
32913              var removeLink = _ref4;
32914
32915              removeLink.addEventListener("click", removeFileEvent);
32916            }
32917          }
32918        },
32919
32920
32921        // Called whenever a file is removed.
32922        removedfile: function removedfile(file) {
32923          if (file.previewElement != null && file.previewElement.parentNode != null) {
32924            file.previewElement.parentNode.removeChild(file.previewElement);
32925          }
32926          return this._updateMaxFilesReachedClass();
32927        },
32928
32929
32930        // Called when a thumbnail has been generated
32931        // Receives `file` and `dataUrl`
32932        thumbnail: function thumbnail(file, dataUrl) {
32933          if (file.previewElement) {
32934            file.previewElement.classList.remove("dz-file-preview");
32935            for (var _iterator6 = file.previewElement.querySelectorAll("[data-dz-thumbnail]"), _isArray6 = true, _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) {
32936              var _ref5;
32937
32938              if (_isArray6) {
32939                if (_i6 >= _iterator6.length) break;
32940                _ref5 = _iterator6[_i6++];
32941              } else {
32942                _i6 = _iterator6.next();
32943                if (_i6.done) break;
32944                _ref5 = _i6.value;
32945              }
32946
32947              var thumbnailElement = _ref5;
32948
32949              thumbnailElement.alt = file.name;
32950              thumbnailElement.src = dataUrl;
32951            }
32952
32953            return setTimeout(function () {
32954              return file.previewElement.classList.add("dz-image-preview");
32955            }, 1);
32956          }
32957        },
32958
32959
32960        // Called whenever an error occurs
32961        // Receives `file` and `message`
32962        error: function error(file, message) {
32963          if (file.previewElement) {
32964            file.previewElement.classList.add("dz-error");
32965            if (typeof message !== "String" && message.error) {
32966              message = message.error;
32967            }
32968            for (var _iterator7 = file.previewElement.querySelectorAll("[data-dz-errormessage]"), _isArray7 = true, _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) {
32969              var _ref6;
32970
32971              if (_isArray7) {
32972                if (_i7 >= _iterator7.length) break;
32973                _ref6 = _iterator7[_i7++];
32974              } else {
32975                _i7 = _iterator7.next();
32976                if (_i7.done) break;
32977                _ref6 = _i7.value;
32978              }
32979
32980              var node = _ref6;
32981
32982              node.textContent = message;
32983            }
32984          }
32985        },
32986        errormultiple: function errormultiple() {},
32987
32988
32989        // Called when a file gets processed. Since there is a cue, not all added
32990        // files are processed immediately.
32991        // Receives `file`
32992        processing: function processing(file) {
32993          if (file.previewElement) {
32994            file.previewElement.classList.add("dz-processing");
32995            if (file._removeLink) {
32996              return file._removeLink.innerHTML = this.options.dictCancelUpload;
32997            }
32998          }
32999        },
33000        processingmultiple: function processingmultiple() {},
33001
33002
33003        // Called whenever the upload progress gets updated.
33004        // Receives `file`, `progress` (percentage 0-100) and `bytesSent`.
33005        // To get the total number of bytes of the file, use `file.size`
33006        uploadprogress: function uploadprogress(file, progress, bytesSent) {
33007          if (file.previewElement) {
33008            for (var _iterator8 = file.previewElement.querySelectorAll("[data-dz-uploadprogress]"), _isArray8 = true, _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) {
33009              var _ref7;
33010
33011              if (_isArray8) {
33012                if (_i8 >= _iterator8.length) break;
33013                _ref7 = _iterator8[_i8++];
33014              } else {
33015                _i8 = _iterator8.next();
33016                if (_i8.done) break;
33017                _ref7 = _i8.value;
33018              }
33019
33020              var node = _ref7;
33021
33022              node.nodeName === 'PROGRESS' ? node.value = progress : node.style.width = progress + "%";
33023            }
33024          }
33025        },
33026
33027
33028        // Called whenever the total upload progress gets updated.
33029        // Called with totalUploadProgress (0-100), totalBytes and totalBytesSent
33030        totaluploadprogress: function totaluploadprogress() {},
33031
33032
33033        // Called just before the file is sent. Get
33033s the `xhr` object as second
33034        // parameter, so you can modify it (for example to add a CSRF token) and a
33035        // `formData` object to add additional information.
33036        sending: function sending() {},
33037        sendingmultiple: function sendingmultiple() {},
33038
33039
33040        // When the complete upload is finished and successful
33041        // Receives `file`
33042        success: function success(file) {
33043          if (file.previewElement) {
33044            return file.previewElement.classList.add("dz-success");
33045          }
33046        },
33047        successmultiple: function successmultiple() {},
33048
33049
33050        // When the upload is canceled.
33051        canceled: function canceled(file) {
33052          return this.emit("error", file, this.options.dictUploadCanceled);
33053        },
33054        canceledmultiple: function canceledmultiple() {},
33055
33056
33057        // When the upload is finished, either with success or an error.
33058        // Receives `file`
33059        complete: function complete(file) {
33060          if (file._removeLink) {
33061            file._removeLink.innerHTML = this.options.dictRemoveFile;
33062          }
33063          if (file.previewElement) {
33064            return file.previewElement.classList.add("dz-complete");
33065          }
33066        },
33067        completemultiple: function completemultiple() {},
33068        maxfilesexceeded: function maxfilesexceeded() {},
33069        maxfilesreached: function maxfilesreached() {},
33070        queuecomplete: function queuecomplete() {},
33071        addedfiles: function addedfiles() {}
33072      };
33073
33074      this.prototype._thumbnailQueue = [];
33075      this.prototype._processingThumbnail = false;
33076    }
33077
33078    // global utility
33079
33080  }, {
33081    key: "extend",
33082    value: function extend(target) {
33083      for (var _len2 = arguments.length, objects = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
33084        objects[_key2 - 1] = arguments[_key2];
33085      }
33086
33087      for (var _iterator9 = objects, _isArray9 = true, _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) {
33088        var _ref8;
33089
33090        if (_isArray9) {
33091          if (_i9 >= _iterator9.length) break;
33092          _ref8 = _iterator9[_i9++];
33093        } else {
33094          _i9 = _iterator9.next();
33095          if (_i9.done) break;
33096          _ref8 = _i9.value;
33097        }
33098
33099        var object = _ref8;
33100
33101        for (var key in object) {
33102          var val = object[key];
33103          target[key] = val;
33104        }
33105      }
33106      return target;
33107    }
33108  }]);
33109
33110  function Dropzone(el, options) {
33111    _classCallCheck(this, Dropzone);
33112
33113    var _this = _possibleConstructorReturn(this, (Dropzone.__proto__ || Object.getPrototypeOf(Dropzone)).call(this));
33114
33115    var fallback = void 0,
33116        left = void 0;
33117    _this.element = el;
33118    // For backwards compatibility since the version was in the prototype previously
33119    _this.version = Dropzone.version;
33120
33121    _this.defaultOptions.previewTemplate = _this.defaultOptions.previewTemplate.replace(/\n*/g, "");
33122
33123    _this.clickableElements = [];
33124    _this.listeners = [];
33125    _this.files = []; // All files
33126
33127    if (typeof _this.element === "string") {
33128      _this.element = document.querySelector(_this.element);
33129    }
33130
33131    // Not checking if instance of HTMLElement or Element since IE9 is extremely weird.
33132    if (!_this.element || _this.element.nodeType == null) {
33133      throw new Error("Invalid dropzone element.");
33134    }
33135
33136    if (_this.element.dropzone) {
33137      throw new Error("Dropzone already attached.");
33138    }
33139
33140    // Now add this dropzone to the instances.
33141    Dropzone.instances.push(_this);
33142
33143    // Put the dropzone inside the element itself.
33144    _this.element.dropzone = _this;
33145
33146    var elementOptions = (left = Dropzone.optionsForElement(_this.element)) != null ? left : {};
33147
33148    _this.options = Dropzone.extend({}, _this.defaultOptions, elementOptions, options != null ? options : {});
33149
33150    // If the browser failed, just call the fallback and leave
33151    if (_this.options.forceFallback || !Dropzone.isBrowserSupported()) {
33152      var _ret;
33153
33154      return _ret = _this.options.fallback.call(_this), _possibleConstructorReturn(_this, _ret);
33155    }
33156
33157    // @options.url = @element.getAttribute "action" unless @options.url?
33158    if (_this.options.url == null) {
33159      _this.options.url = _this.element.getAttribute("action");
33160    }
33161
33162    if (!_this.options.url) {
33163      throw new Error("No URL provided.");
33164    }
33165
33166    if (_this.options.acceptedFiles && _this.options.acceptedMimeTypes) {
33167      throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.");
33168    }
33169
33170    if (_this.options.uploadMultiple && _this.options.chunking) {
33171      throw new Error('You cannot set both: uploadMultiple and chunking.');
33172    }
33173
33174    // Backwards compatibility
33175    if (_this.options.acceptedMimeTypes) {
33176      _this.options.acceptedFiles = _this.options.acceptedMimeTypes;
33177      delete _this.options.acceptedMimeTypes;
33178    }
33179
33180    // Backwards compatibility
33181    if (_this.options.renameFilename != null) {
33182      _this.options.renameFile = function (file) {
33183        return _this.options.renameFilename.call(_this, file.name, file);
33184      };
33185    }
33186
33187    _this.options.method = _this.options.method.toUpperCase();
33188
33189    if ((fallback = _this.getExistingFallback()) && fallback.parentNode) {
33190      // Remove the fallback
33191      fallback.parentNode.removeChild(fallback);
33192    }
33193
33194    // Display previews in the previewsContainer element or the Dropzone element unless explicitly set to false
33195    if (_this.options.previewsContainer !== false) {
33196      if (_this.options.previewsContainer) {
33197        _this.previewsContainer = Dropzone.getElement(_this.options.previewsContainer, "previewsContainer");
33198      } else {
33199        _this.previewsContainer = _this.element;
33200      }
33201    }
33202
33203    if (_this.options.clickable) {
33204      if (_this.options.clickable === true) {
33205        _this.clickableElements = [_this.element];
33206      } else {
33207        _this.clickableElements = Dropzone.getElements(_this.options.clickable, "clickable");
33208      }
33209    }
33210
33211    _this.init();
33212    return _this;
33213  }
33214
33215  // Returns all files that have been accepted
33216
33217
33218  _createClass(Dropzone, [{
33219    key: "getAcceptedFiles",
33220    value: function getAcceptedFiles() {
33221      return this.files.filter(function (file) {
33222        return file.accepted;
33223      }).map(function (file) {
33224        return file;
33225      });
33226    }
33227
33228    // Returns all files that have been rejected
33229    // Not sure when that's going to be useful, but added for completeness.
33230
33231  }, {
33232    key: "getRejectedFiles",
33233    value: function getRejectedFiles() {
33234      return this.files.filter(function (file) {
33235        return !file.accepted;
33236      }).map(function (file) {
33237        return file;
33238      });
33239    }
33240  }, {
33241    key: "getFilesWithStatus",
33242    value: function getFilesWithStatus(status) {
33243      return this.files.filter(function (file) {
33244        return file.status === status;
33245      }).map(function (file) {
33246        return file;
33247      });
33248    }
33249
33250    // Returns all files that are in the queue
33251
33252  }, {
33253    key: "getQueuedFiles",
33254    value: function getQueuedFiles() {
33255      return this.getFilesWithStatus(Dropzone.QUEUED);
33256    }
33257  }, {
33258    key: "getUploadingFiles",
33259    value: function getUploadingFiles() {
33260      return this.getFilesWithStatus(Dropzone.UPLOADING);
33261    }
33262  }, {
33263    key: "getAddedFiles",
33264    value: function getAddedFiles() {
33265      return this.getFilesWithStatus(Dropzone.ADDED);
33266    }
33267
33268    // Files that are either queued or uploading
33269
33270  }, {
33271    key: "getActiveFiles",
33272    value: function getActiveFiles() {
33273      return this.files.filter(function (file) {
33274        return file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED;
33275      }).map(function (file) {
33276        return file;
33277      });
33278    }
33279
33280    // The function that gets called when Dropzone is initialized. You
33281    // can (and should) setup event listeners inside this function.
33282
33283  }, {
33284    key: "init",
33285    value: function init() {
33286      var _this3 = this;
33287
33288      // In case it isn't set already
33289      if (this.element.tagName === "form") {
33290        this.element.setAttribute("enctype", "multipart/form-data");
33291      }
33292
33293      if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) {
33294        this.element.appendChild(Dropzone.createElement("<div class=\"dz-default dz-message\"><span>" + this.options.dictDefaultMessage + "</span></div>"));
33295      }
33296
33297      if (this.clickableElements.length) {
33298        var setupHiddenFileInput = function setupHiddenFileInput() {
33299          if (_this3.hiddenFileInput) {
33300            _this3.hiddenFileInput.parentNode.removeChild(_this3.hiddenFileInput);
33301          }
33302          _this3.hiddenFileInput = document.createElement("input");
33303          _this3.hiddenFileInput.setAttribute("type", "file");
33304          if (_this3.options.maxFiles === null || _this3.options.maxFiles > 1) {
33305            _this3.hiddenFileInput.setAttribute("multiple", "multiple");
33306          }
33307          _this3.hiddenFileInput.className = "dz-hidden-input";
33308
33309          if (_this3.options.acceptedFiles !== null) {
33310            _this3.hiddenFileInput.setAttribute("accept", _this3.options.acceptedFiles);
33311          }
33312          if (_this3.options.capture !== null) {
33313            _this3.hiddenFileInput.setAttribute("capture", _this3.options.capture);
33314          }
33315
33316          // Not setting `display="none"` because some browsers don't accept clicks
33317          // on elements that aren't displayed.
33318          _this3.hiddenFileInput.style.visibility = "hidden";
33319          _this3.hiddenFileInput.style.position = "absolute";
33320          _this3.hiddenFileInput.style.top = "0";
33321          _this3.hiddenFileInput.style.left = "0";
33322          _this3.hiddenFileInput.style.height = "0";
33323          _this3.hiddenFileInput.style.width = "0";
33324          Dropzone.getElement(_this3.options.hiddenInputContainer, 'hiddenInputContainer').appendChild(_this3.hiddenFileInput);
33325          return _this3.hiddenFileInput.addEventListener("change", function () {
33326            var files = _this3.hiddenFileInput.files;
33327
33328            if (files.length) {
33329              for (var _iterator10 = files, _isArray10 = true, _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) {
33330                var _ref9;
33331
33332                if (_isArray10) {
33333                  if (_i10 >= _iterator10.length) break;
33334                  _ref9 = _iterator10[_i10++];
33335                } else {
33336                  _i10 = _iterator10.next();
33337                  if (_i10.done) break;
33338                  _ref9 = _i10.value;
33339                }
33340
33341                var file = _ref9;
33342
33343                _this3.addFile(file);
33344              }
33345            }
33346            _this3.emit("addedfiles", files);
33347            return setupHiddenFileInput();
33348          });
33349        };
33350        setupHiddenFileInput();
33351      }
33352
33353      this.URL = window.URL !== null ? window.URL : window.webkitURL;
33354
33355      // Setup all event listeners on the Dropzone object itself.
33356      // They're not in @setupEventListeners() because they shouldn't be removed
33357      // again when the dropzone gets disabled.
33358      for (var _iterator11 = this.events, _isArray11 = true, _i11 = 0, _iterator11 = _isArray11 ? _iterator11 : _iterator11[Symbol.iterator]();;) {
33359        var _ref10;
33360
33361        if (_isArray11) {
33362          if (_i11 >= _iterator11.length) break;
33363          _ref10 = _iterator11[_i11++];
33364        } else {
33365          _i11 = _iterator11.next();
33366          if (_i11.done) break;
33367          _ref10 = _i11.value;
33368        }
33369
33370        var eventName = _ref10;
33371
33372        this.on(eventName, this.options[eventName]);
33373      }
33374
33375      this.on("uploadprogress", function () {
33376        return _this3.updateTotalUploadProgress();
33377      });
33378
33379      this.on("removedfile", function () {
33380        return _this3.updateTotalUploadProgress();
33381      });
33382
33383      this.on("canceled", function (file) {
33384        return _this3.emit("complete", file);
33385      });
33386
33387      // Emit a `queuecomplete` event if all files finished uploading.
33388      this.on("complete", function (file) {
33389        if (_this3.getAddedFiles().length === 0 && _this3.getUploadingFiles().length === 0 && _this3.getQueuedFiles().length === 0) {
33390          // This needs to be deferred so that `queuecomplete` really triggers after `complete`
33391          return setTimeout(function () {
33392            return _this3.emit("queuecomplete");
33393          }, 0);
33394        }
33395      });
33396
33397      var noPropagation = function noPropagation(e) {
33398        e.stopPropagation();
33399        if (e.preventDefault) {
33400          return e.preventDefault();
33401        } else {
33402          return e.returnValue = false;
33403        }
33404      };
33405
33406      // Create the listeners
33407      this.listeners = [{
33408        element: this.element,
33409        events: {
33410          "dragstart": function dragstart(e) {
33411            return _this3.emit("dragstart", e);
33412          },
33413          "dragenter": function dragenter(e) {
33414            noPropagation(e);
33415            return _this3.emit("dragenter", e);
33416          },
33417          "dragover": function dragover(e) {
33418            // Makes it possible to drag files from chrome's download bar
33419            // http://stackoverflow.com/questions/19526430/drag-and-drop-file-uploads-from-chrome-downloads-bar
33420            // Try is required to prevent bug in Internet Explorer 11 (SCRIPT65535 exception)
33421            var efct = void 0;
33422            try {
33423              efct = e.dataTransfer.effectAllowed;
33424            } catch (error) {}
33425            e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy';
33426
33427            noPropagation(e);
33428            return _this3.emit("dragover", e);
33429          },
33430          "dragleave": function dragleave(e) {
33431            return _this3.emit("dragleave", e);
33432          },
33433          "drop": function drop(e) {
33434            noPropagation(e);
33435            return _this3.drop(e);
33436          },
33437          "dragend": function dragend(e) {
33438            return _this3.emit("dragend", e);
33439          }
33440
33441          // This is disabled right now, because the browsers don't implement it properly.
33442          // "paste": (e) =>
33443          //   noPropagation e
33444          //   @paste e
33445        } }];
33446
33447      this.clickableElements.forEach(function (clickableElement) {
33448        return _this3.listeners.push({
33449          element: clickableElement,
33450          events: {
33451            "click": function click(evt) {
33452              // Only the actual dropzone or the message element should trigger file selection
33453              if (clickableElement !== _this3.element || evt.target === _this3.element || Dropzone.elementInside(evt.target, _this3.element.querySelector(".dz-message"))) {
33454                _this3.hiddenFileInput.click(); // Forward the click
33455              }
33456              return true;
33457            }
33458          }
33459        });
33460      });
33461
33462      this.enable();
33463
33464      return this.options.init.call(this);
33465    }
33466
33467    // Not fully tested yet
33468
33469  }, {
33470    key: "destroy",
33471    value: function destroy() {
33472      this.disable();
33473      this.removeAllFiles(true);
33474      if (this.hiddenFileInput != null ? this.hiddenFileInput.parentNode : undefined) {
33475        this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput);
33476        this.hiddenFileInput = null;
33477      }
33478      delete this.element.dropzone;
33479      return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1);
33480    }
33481  }, {
33482    key: "updateTotalUploadProgress",
33483    value: function updateTotalUploadProgress() {
33484      var totalUploadProgress = void 0;
33485      var totalBytesSent = 0;
33486      var totalBytes = 0;
33487
33488      var activeFiles = this.getActiveFiles();
33489
33490      if (activeFiles.length) {
33491        for (var _iterator12 = this.getActiveFiles(), _isArray12 = true, _i12 = 0, _iterator12 = _isArray12 ? _iterator12 : _iterator12[Symbol.iterator]();;) {
33492          var _ref11;
33493
33494          if (_isArray12) {
33495            if (_i12 >= _iterator12.length) break;
33496            _ref11 = _iterator12[_i12++];
33497          } else {
33498            _i12 = _iterator12.next();
33499            if (_i12.done) break;
33500            _ref11 = _i12.value;
33501          }
33502
33503          var file = _ref11;
33504
33505          totalBytesSent += file.upload.bytesSent;
33506          totalBytes += file.upload.total;
33507        }
33508        totalUploadProgress = 100 * totalBytesSent / totalBytes;
33509      } else {
33510        totalUploadProgress = 100;
33511      }
33512
33513      return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent);
33514    }
33515
33516    // @options.paramName can be a function taking one parameter rather than a string.
33517    // A parameter name for a file is obtained simply by calling this with an index number.
33518
33519  }, {
33520    key: "_getParamName",
33521    value: function _getParamName(n) {
33522      if (typeof this.options.paramName === "function") {
33523        return this.options.paramName(n);
33524      } else {
33525        return "" + this.options.paramName + (this.options.uploadMultiple ? "[" + n + "]" : "");
33526      }
33527    }
33528
33529    // If @options.renameFile is a function,
33530    // the function will be used to rename the file.name before appending it to the formData
33531
33532  }, {
33533    key: "_renameFile",
33534    value: function _renameFile(file) {
33535      if (typeof this.options.renameFile !== "function") {
33536        return file.name;
33537      }
33538      return this.options.renameFile(file);
33539    }
33540
33541    // Returns a form that can be used as fallback if the browser does not support DragnDrop
33542    //
33543    // If the dropzone is already a form, only the input field and button are returned. Otherwise a complete form element is provided.
33544    // This code has to pass in IE7 :(
33545
33546  }, {
33547    key: "getFallbackForm",
33548    value: function getFallbackForm() {
33549      var existingFallback = void 0,
33550          form = void 0;
33551      if (existingFallback = this.getExistingFallback()) {
33552        return existingFallback;
33553      }
33554
33555      var fieldsString = "<div class=\"dz-fallback\">";
33556      if (this.options.dictFallbackText) {
33557        fieldsString += "<p>" + this.options.dictFallbackText + "</p>";
33558      }
33559      fieldsString += "<input type=\"file\" name=\"" + this._getParamName(0) + "\" " + (this.options.uploadMultiple ? 'multiple="multiple"' : undefined) + " /><input type=\"submit\" value=\"Upload!\"></div>";
33560
33561      var fields = Dropzone.createElement(fieldsString);
33562      if (this.element.tagName !== "FORM") {
33563        form = Dropzone.createElement("<form action=\"" + this.options.url + "\" enctype=\"multipart/form-data\" method=\"" + this.options.method + "\"></form>");
33564        form.appendChild(fields);
33565      } else {
33566        // Make sure that the enctype and method attributes are set properly
33567        this.element.setAttribute("enctype", "multipart/form-data");
33568        this.element.setAttribute("method", this.options.method);
33569      }
33570      return form != null ? form : fields;
33571    }
33572
33573    // Returns the fallback elements if they exist already
33574    //
33575    // This code has to pass in IE7 :(
33576
33577  }, {
33578    key: "getExistingFallback",
33579    value: function getExistingFallback() {
33580      var getFallback = function getFallback(elements) {
33581        for (var _iterator13 = elements, _isArray13 = true, _i13 = 0, _iterator13 = _isArray13 ? _iterator13 : _iterator13[Symbol.iterator]();;) {
33582          var _ref12;
33583
33584          if (_isArray13) {
33585            if (_i13 >= _iterator13.length) break;
33586            _ref12 = _iterator13[_i13++];
33587          } else {
33588            _i13 = _iterator13.next();
33589            if (_i13.done) break;
33590            _ref12 = _i13.value;
33591          }
33592
33593          var el = _ref12;
33594
33595          if (/(^| )fallback($| )/.test(el.className)) {
33596            return el;
33597          }
33598        }
33599      };
33600
33601      var _arr = ["div", "form"];
33602      for (var _i14 = 0; _i14 < _arr.length; _i14++) {
33603        var tagName = _arr[_i14];
33604        var fallback;
33605        if (fallback = getFallback(this.element.getElementsByTagName(tagName))) {
33606          return fallback;
33607        }
33608      }
33609    }
33610
33611    // Activates all listeners stored in @listeners
33612
33613  }, {
33614    key: "setupEventListeners",
33615    value: function setupEventListeners() {
33616      return this.listeners.map(function (elementListeners) {
33617        return function () {
33618          var result = [];
33619          for (var event in elementListeners.events) {
33620            var listener = elementListeners.events[event];
33621            result.push(elementListeners.element.addEventListener(event, listener, false));
33622          }
33623          return result;
33624        }();
33625      });
33626    }
33627
33628    // Deactivates all listeners stored in @listeners
33629
33630  }, {
33631    key: "removeEventListeners",
33632    value: function removeEventListeners() {
33633      return this.listeners.map(function (elementListeners) {
33634        return function () {
33635          var result = [];
33636          for (var event in elementListeners.events) {
33637            var listener = elementListeners.events[event];
33638            result.push(elementListeners.element.removeEventListener(event, listener, false));
33639          }
33640          return result;
33641        }();
33642      });
33643    }
33644
33645    // Removes all event listeners and cancels all files in the queue or being processed.
33646
33647  }, {
33648    key: "disable",
33649    value: function disable() {
33650      var _this4 = this;
33651
vendor: 8,038 bytes, lines 33652-33901
33652      this.clickableElements.forEach(function (element) {
33653        return element.classList.remove("dz-clickable");
33654      });
33655      this.removeEventListeners();
33656      this.disabled = true;
33657
33658      return this.files.map(function (file) {
33659        return _this4.cancelUpload(file);
33660      });
33661    }
33662  }, {
33663    key: "enable",
33664    value: function enable() {
33665      delete this.disabled;
33666      this.clickableElements.forEach(function (element) {
33667        return element.classList.add("dz-clickable");
33668      });
33669      return this.setupEventListeners();
33670    }
33671
33672    // Returns a nicely formatted filesize
33673
33674  }, {
33675    key: "filesize",
33676    value: function filesize(size) {
33677      var selectedSize = 0;
33678      var selectedUnit = "b";
33679
33680      if (size > 0) {
33681        var units = ['tb', 'gb', 'mb', 'kb', 'b'];
33682
33683        for (var i = 0; i < units.length; i++) {
33684          var unit = units[i];
33685          var cutoff = Math.pow(this.options.filesizeBase, 4 - i) / 10;
33686
33687          if (size >= cutoff) {
33688            selectedSize = size / Math.pow(this.options.filesizeBase, 4 - i);
33689            selectedUnit = unit;
33690            break;
33691          }
33692        }
33693
33694        selectedSize = Math.round(10 * selectedSize) / 10; // Cutting of digits
33695      }
33696
33697      return "<strong>" + selectedSize + "</strong> " + this.options.dictFileSizeUnits[selectedUnit];
33698    }
33699
33700    // Adds or removes the `dz-max-files-reached` class from the form.
33701
33702  }, {
33703    key: "_updateMaxFilesReachedClass",
33704    value: function _updateMaxFilesReachedClass() {
33705      if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) {
33706        if (this.getAcceptedFiles().length === this.options.maxFiles) {
33707          this.emit('maxfilesreached', this.files);
33708        }
33709        return this.element.classList.add("dz-max-files-reached");
33710      } else {
33711        return this.element.classList.remove("dz-max-files-reached");
33712      }
33713    }
33714  }, {
33715    key: "drop",
33716    value: function drop(e) {
33717      if (!e.dataTransfer) {
33718        return;
33719      }
33720      this.emit("drop", e);
33721
33722      // Convert the FileList to an Array
33723      // This is necessary for IE11
33724      var files = [];
33725      for (var i = 0; i < e.dataTransfer.files.length; i++) {
33726        files[i] = e.dataTransfer.files[i];
33727      }
33728
33729      this.emit("addedfiles", files);
33730
33731      // Even if it's a folder, files.length will contain the folders.
33732      if (files.length) {
33733        var items = e.dataTransfer.items;
33734
33735        if (items && items.length && items[0].webkitGetAsEntry != null) {
33736          // The browser supports dropping of folders, so handle items instead of files
33737          this._addFilesFromItems(items);
33738        } else {
33739          this.handleFiles(files);
33740        }
33741      }
33742    }
33743  }, {
33744    key: "paste",
33745    value: function paste(e) {
33746      if (__guard__(e != null ? e.clipboardData : undefined, function (x) {
33747        return x.items;
33748      }) == null) {
33749        return;
33750      }
33751
33752      this.emit("paste", e);
33753      var items = e.clipboardData.items;
33754
33755
33756      if (items.length) {
33757        return this._addFilesFromItems(items);
33758      }
33759    }
33760  }, {
33761    key: "handleFiles",
33762    value: function handleFiles(files) {
33763      for (var _iterator14 = files, _isArray14 = true, _i15 = 0, _iterator14 = _isArray14 ? _iterator14 : _iterator14[Symbol.iterator]();;) {
33764        var _ref13;
33765
33766        if (_isArray14) {
33767          if (_i15 >= _iterator14.length) break;
33768          _ref13 = _iterator14[_i15++];
33769        } else {
33770          _i15 = _iterator14.next();
33771          if (_i15.done) break;
33772          _ref13 = _i15.value;
33773        }
33774
33775        var file = _ref13;
33776
33777        this.addFile(file);
33778      }
33779    }
33780
33781    // When a folder is dropped (or files are pasted), items must be handled
33782    // instead of files.
33783
33784  }, {
33785    key: "_addFilesFromItems",
33786    value: function _addFilesFromItems(items) {
33787      var _this5 = this;
33788
33789      return function () {
33790        var result = [];
33791        for (var _iterator15 = items, _isArray15 = true, _i16 = 0, _iterator15 = _isArray15 ? _iterator15 : _iterator15[Symbol.iterator]();;) {
33792          var _ref14;
33793
33794          if (_isArray15) {
33795            if (_i16 >= _iterator15.length) break;
33796            _ref14 = _iterator15[_i16++];
33797          } else {
33798            _i16 = _iterator15.next();
33799            if (_i16.done) break;
33800            _ref14 = _i16.value;
33801          }
33802
33803          var item = _ref14;
33804
33805          var entry;
33806          if (item.webkitGetAsEntry != null && (entry = item.webkitGetAsEntry())) {
33807            if (entry.isFile) {
33808              result.push(_this5.addFile(item.getAsFile()));
33809            } else if (entry.isDirectory) {
33810              // Append all files from that directory to files
33811              result.push(_this5._addFilesFromDirectory(entry, entry.name));
33812            } else {
33813              result.push(undefined);
33814            }
33815          } else if (item.getAsFile != null) {
33816            if (item.kind == null || item.kind === "file") {
33817              result.push(_this5.addFile(item.getAsFile()));
33818            } else {
33819              result.push(undefined);
33820            }
33821          } else {
33822            result.push(undefined);
33823          }
33824        }
33825        return result;
33826      }();
33827    }
33828
33829    // Goes through the directory, and adds each file it finds recursively
33830
33831  }, {
33832    key: "_addFilesFromDirectory",
33833    value: function _addFilesFromDirectory(directory, path) {
33834      var _this6 = this;
33835
33836      var dirReader = directory.createReader();
33837
33838      var errorHandler = function errorHandler(error) {
33839        return __guardMethod__(console, 'log', function (o) {
33840          return o.log(error);
33841        });
33842      };
33843
33844      var readEntries = function readEntries() {
33845        return dirReader.readEntries(function (entries) {
33846          if (entries.length > 0) {
33847            for (var _iterator16 = entries, _isArray16 = true, _i17 = 0, _iterator16 = _isArray16 ? _iterator16 : _iterator16[Symbol.iterator]();;) {
33848              var _ref15;
33849
33850              if (_isArray16) {
33851                if (_i17 >= _iterator16.length) break;
33852                _ref15 = _iterator16[_i17++];
33853              } else {
33854                _i17 = _iterator16.next();
33855                if (_i17.done) break;
33856                _ref15 = _i17.value;
33857              }
33858
33859              var entry = _ref15;
33860
33861              if (entry.isFile) {
33862                entry.file(function (file) {
33863                  if (_this6.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') {
33864                    return;
33865                  }
33866                  file.fullPath = path + "/" + file.name;
33867                  return _this6.addFile(file);
33868                });
33869              } else if (entry.isDirectory) {
33870                _this6._addFilesFromDirectory(entry, path + "/" + entry.name);
33871              }
33872            }
33873
33874            // Recursively call readEntries() again, since browser only handle
33875            // the first 100 entries.
33876            // See: https://developer.mozilla.org/en-US/docs/Web/API/DirectoryReader#readEntries
33877            readEntries();
33878          }
33879          return null;
33880        }, errorHandler);
33881      };
33882
33883      return readEntries();
33884    }
33885
33886    // If `done()` is called without argument the file is accepted
33887    // If you call it with an error message, the file is rejected
33888    // (This allows for asynchronous validation)
33889    //
33890    // This function checks the filesize, and if the file.type passes the
33891    // `acceptedFiles` check.
33892
33893  }, {
33894    key: "accept",
33895    value: function accept(file, done) {
33896      if (this.options.maxFilesize && file.size > this.options.maxFilesize * 1024 * 1024) {
33897        return done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize));
33898      } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) {
33899        return done(this.options.dictInvalidFileType);
33900      } else if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) {
33901        done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles));
33902        return this.emit("maxfilesexceeded", file);
33903      } else {
33904        return this.options.accept.call(this, file, done);
33905      }
33906    }
33907  }, {
33908    key: "addFile",
33909    value: function addFile(file) {
33910      var _this7 = this;
33911
33912      file.upload = {
33913        uuid: Dropzone.uuidv4(),
33914        progress: 0,
33915        // Setting the total upload size to file.size for the beginning
33916        // It's actual different than the size to be transmitted.
33917        total: file.size,
33918        bytesSent: 0,
33919        filename: this._renameFile(file),
33920        chunked: this.options.chunking && (this.options.forceChunking || file.size > this.options.chunkSize),
33921        totalChunkCount: Math.ceil(file.size / this.options.chunkSize)
33922      };
33923      this.files.push(file);
33924
33925      file.status = Dropzone.ADDED;
33926
33927      this.emit("addedfile", file);
33928
33929      this._enqueueThumbnail(file);
33930
33931      return this.accept(file, function (error) {
33932        if (error) {
33933          file.accepted = false;
33934          _this7._errorProcessing([file], error); // Will set the file.status
33935        } else {
33936          file.accepted = true;
33937          if (_this7.options.autoQueue) {
33938            _this7.enqueueFile(file);
33939          } // Will set .accepted = true
33940        }
33941        return _this7._updateMaxFilesReachedClass();
33942      });
33943    }
33944
33945    // Wrapper for enqueueFile
33946
33947  }, {
33948    key: "enqueueFiles",
33949    value: function enqueueFiles(files) {
33950      for (var _iterator17 = files, _isArray17 = true, _i18 = 0, _iterator17 = _isArray17 ? _iterator17 : _iterator17[Symbol.iterator]();;) {
33951        var _ref16;
33952
33953        if (_isArray17) {
33954          if (_i18 >= _iterator17.length) break;
33955          _ref16 = _iterator17[_i18++];
33956        } else {
33957          _i18 = _iterator17.next();
33958          if (_i18.done) break;
33959          _ref16 = _i18.value;
33960        }
33961
33962        var file = _ref16;
33963
33964        this.enqueueFile(file);
33965      }
33966      return null;
33967    }
33968  }, {
33969    key: "enqueueFile",
33970    value: function enqueueFile(file) {
33971      var _this8 = this;
33972
33973      if (file.status === Dropzone.ADDED && file.accepted === true) {
33974        file.status = Dropzone.QUEUED;
33975        if (this.options.autoProcessQueue) {
33976          return setTimeout(function () {
33977            return _this8.processQueue();
33978          }, 0); // Deferring the call
33979        }
33980      } else {
33981        throw new Error("This file can't be queued because it has already been processed or was rejected.");
33982      }
33983    }
33984  }, {
33985    key: "_enqueueThumbnail",
33986    value: function _enqueueThumbnail(file) {
33987      var _this9 = this;
33988
33989      if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) {
33990        this._thumbnailQueue.push(file);
33991        return setTimeout(function () {
33992          return _this9._processThumbnailQueue();
33993        }, 0); // Deferring the call
33994      }
33995    }
33996  }, {
33997    key: "_processThumbnailQueue",
33998    value: function _processThumbnailQueue() {
33999      var _this10 = this;
34000
34001      if (this._processingThumbnail || this._thumbnailQueue.length === 0) {
34002        return;
34003      }
34004
34005      this._processingThumbnail = true;
34006      var file = this._thumbnailQueue.shift();
34007      return this.createThumbnail(file, this.options.thumbnailWidth, this.options.thumbnailHeight, this.options.thumbnailMethod, true, function (dataUrl) {
34008        _this10.emit("thumbnail", file, dataUrl);
34009        _this10._processingThumbnail = false;
34010        return _this10._processThumbnailQueue();
34011      });
34012    }
34013
34014    // Can be called by the user to remove a file
34015
34016  }, {
34017    key: "removeFile",
34018    value: function removeFile(file) {
34019      if (file.status === Dropzone.UPLOADING) {
34020        this.cancelUpload(file);
34021      }
34022      this.files = without(this.files, file);
34023
34024      this.emit("removedfile", file);
34025      if (this.files.length === 0) {
34026        return this.emit("reset");
34027      }
34028    }
34029
34030    // Removes all files that aren't currently processed from the list
34031
34032  }, {
34033    key: "removeAllFiles",
34034    value: function removeAllFiles(cancelIfNecessary) {
34035      // Create a copy of files since removeFile() changes the @files array.
34036      if (cancelIfNecessary == null) {
34037        cancelIfNecessary = false;
vendor: 5,578 bytes, lines 34038-34198
34038      }
34039      for (var _iterator18 = this.files.slice(), _isArray18 = true, _i19 = 0, _iterator18 = _isArray18 ? _iterator18 : _iterator18[Symbol.iterator]();;) {
34040        var _ref17;
34041
34042        if (_isArray18) {
34043          if (_i19 >= _iterator18.length) break;
34044          _ref17 = _iterator18[_i19++];
34045        } else {
34046          _i19 = _iterator18.next();
34047          if (_i19.done) break;
34048          _ref17 = _i19.value;
34049        }
34050
34051        var file = _ref17;
34052
34053        if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) {
34054          this.removeFile(file);
34055        }
34056      }
34057      return null;
34058    }
34059
34060    // Resizes an image before it gets sent to the server. This function is the default behavior of
34061    // `options.transformFile` if `resizeWidth` or `resizeHeight` are set. The callback is invoked with
34062    // the resized blob.
34063
34064  }, {
34065    key: "resizeImage",
34066    value: function resizeImage(file, width, height, resizeMethod, callback) {
34067      var _this11 = this;
34068
34069      return this.createThumbnail(file, width, height, resizeMethod, true, function (dataUrl, canvas) {
34070        if (canvas == null) {
34071          // The image has not been resized
34072          return callback(file);
34073        } else {
34074          var resizeMimeType = _this11.options.resizeMimeType;
34075
34076          if (resizeMimeType == null) {
34077            resizeMimeType = file.type;
34078          }
34079          var resizedDataURL = canvas.toDataURL(resizeMimeType, _this11.options.resizeQuality);
34080          if (resizeMimeType === 'image/jpeg' || resizeMimeType === 'image/jpg') {
34081            // Now add the original EXIF information
34082            resizedDataURL = ExifRestore.restore(file.dataURL, resizedDataURL);
34083          }
34084          return callback(Dropzone.dataURItoBlob(resizedDataURL));
34085        }
34086      });
34087    }
34088  }, {
34089    key: "createThumbnail",
34090    value: function createThumbnail(file, width, height, resizeMethod, fixOrientation, callback) {
34091      var _this12 = this;
34092
34093      var fileReader = new FileReader();
34094
34095      fileReader.onload = function () {
34096
34097        file.dataURL = fileReader.result;
34098
34099        // Don't bother creating a thumbnail for SVG images since they're vector
34100        if (file.type === "image/svg+xml") {
34101          if (callback != null) {
34102            callback(fileReader.result);
34103          }
34104          return;
34105        }
34106
34107        return _this12.createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback);
34108      };
34109
34110      return fileReader.readAsDataURL(file);
34111    }
34112  }, {
34113    key: "createThumbnailFromUrl",
34114    value: function createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback, crossOrigin) {
34115      var _this13 = this;
34116
34117      // Not using `new Image` here because of a bug in latest Chrome versions.
34118      // See https://github.com/enyo/dropzone/pull/226
34119      var img = document.createElement("img");
34120
34121      if (crossOrigin) {
34122        img.crossOrigin = crossOrigin;
34123      }
34124
34125      img.onload = function () {
34126        var loadExif = function loadExif(callback) {
34127          return callback(1);
34128        };
34129        if (typeof EXIF !== 'undefined' && EXIF !== null && fixOrientation) {
34130          loadExif = function loadExif(callback) {
34131            return EXIF.getData(img, function () {
34132              return callback(EXIF.getTag(this, 'Orientation'));
34133            });
34134          };
34135        }
34136
34137        return loadExif(function (orientation) {
34138          file.width = img.width;
34139          file.height = img.height;
34140
34141          var resizeInfo = _this13.options.resize.call(_this13, file, width, height, resizeMethod);
34142
34143          var canvas = document.createElement("canvas");
34144          var ctx = canvas.getContext("2d");
34145
34146          canvas.width = resizeInfo.trgWidth;
34147          canvas.height = resizeInfo.trgHeight;
34148
34149          if (orientation > 4) {
34150            canvas.width = resizeInfo.trgHeight;
34151            canvas.height = resizeInfo.trgWidth;
34152          }
34153
34154          switch (orientation) {
34155            case 2:
34156              // horizontal flip
34157              ctx.translate(canvas.width, 0);
34158              ctx.scale(-1, 1);
34159              break;
34160            case 3:
34161              // 180° rotate left
34162              ctx.translate(canvas.width, canvas.height);
34163              ctx.rotate(Math.PI);
34164              break;
34165            case 4:
34166              // vertical flip
34167              ctx.translate(0, canvas.height);
34168              ctx.scale(1, -1);
34169              break;
34170            case 5:
34171              // vertical flip + 90 rotate right
34172              ctx.rotate(0.5 * Math.PI);
34173              ctx.scale(1, -1);
34174              break;
34175            case 6:
34176              // 90° rotate right
34177              ctx.rotate(0.5 * Math.PI);
34178              ctx.translate(0, -canvas.width);
34179              break;
34180            case 7:
34181              // horizontal flip + 90 rotate right
34182              ctx.rotate(0.5 * Math.PI);
34183              ctx.translate(canvas.height, -canvas.width);
34184              ctx.scale(-1, 1);
34185              break;
34186            case 8:
34187              // 90° rotate left
34188              ctx.rotate(-0.5 * Math.PI);
34189              ctx.translate(-canvas.height, 0);
34190              break;
34191          }
34192
34193          // This is a bugfix for iOS' scaling bug.
34194          drawImageIOSFix(ctx, img, resizeInfo.srcX != null ? resizeInfo.srcX : 0, resizeInfo.srcY != null ? resizeInfo.srcY : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, resizeInfo.trgX != null ? resizeInfo.trgX : 0, resizeInfo.trgY != null ? resizeInfo.trgY : 0, resizeInfo.trgWidth, resizeInfo.trgHeight);
34195
34196          var thumbnail = canvas.toDataURL("image/png");
34197
34198          if (callback != null) {
34199            return callback(thumbnail, canvas);
34200          }
34201        });
34202      };
34203
34204      if (callback != null) {
34205        img.onerror = callback;
34206      }
34207
34208      return img.src = file.dataURL;
34209    }
34210
34211    // Goes through the queue and processes files if there aren't too many already.
34212
34213  }, {
34214    key: "processQueue",
34215    value: function processQueue() {
34216      var parallelUploads = this.options.parallelUploads;
34217
34218      var processingLength = this.getUploadingFiles().length;
34219      var i = processingLength;
34220
34221      // There are already at least as many files uploading than should be
34222      if (processingLength >= parallelUploads) {
34223        return;
34224      }
34225
34226      var queuedFiles = this.getQueuedFiles();
34227
34228      if (!(queuedFiles.length > 0)) {
34229        return;
34230      }
34231
34232      if (this.options.uploadMultiple) {
34233        // The files should be uploaded in one request
34234        return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength));
34235      } else {
34236        while (i < parallelUploads) {
34237          if (!queuedFiles.length) {
34238            return;
34239          } // Nothing left to process
34240          this.processFile(queuedFiles.shift());
34241          i++;
34242        }
34243      }
34244    }
34245
34246    // Wrapper for `processFiles`
34247
34248  }, {
34249    key: "processFile",
34250    value: function processFile(file) {
34251      return this.processFiles([file]);
34252    }
34253
34254    // Loads the file, then calls finishedLoading()
34255
34256  }, {
34257    key: "processFiles",
34258    value: function processFiles(files) {
34259      for (var _iterator19 = files, _isArray19 = true, _i20 = 0, _iterator19 = _isArray19 ? _iterator19 : _iterator19[Symbol.iterator]();;) {
34260        var _ref18;
34261
34262        if (_isArray19) {
34263          if (_i20 >= _iterator19.length) break;
34264          _ref18 = _iterator19[_i20++];
34265        } else {
34266          _i20 = _iterator19.next();
34267          if (_i20.done) break;
34268          _ref18 = _i20.value;
34269        }
34270
34271        var file = _ref18;
34272
34273        file.processing = true; // Backwards compatibility
34274        file.status = Dropzone.UPLOADING;
34275
34276        this.emit("processing", file);
34277      }
34278
34279      if (this.options.uploadMultiple) {
34280        this.emit("processingmultiple", files);
34281      }
34282
34283      return this.uploadFiles(files);
34284    }
34285  }, {
34286    key: "_getFilesWithXhr",
34287    value: function _getFilesWithXhr(xhr) {
34288      var files = void 0;
34289      return files = this.files.filter(function (file) {
34290        return file.xhr === xhr;
34291      }).map(function (file) {
34292        return file;
34293      });
34294    }
34295
34296    // Cancels the file upload and sets the status to CANCELED
34297    // **if** the file is actually being uploaded.
34298    // If it's still in the queue, the file is being removed from it and the status
34299    // set to CANCELED.
34300
34301  }, {
34302    key: "cancelUpload",
34303    value: function cancelUpload(file) {
34304      if (file.status === Dropzone.UPLOADING) {
34305        var groupedFiles = this._getFilesWithXhr(file.xhr);
34306        for (var _iterator20 = groupedFiles, _isArray20 = true, _i21 = 0, _iterator20 = _isArray20 ? _iterator20 : _iterator20[Symbol.iterator]();;) {
34307          var _ref19;
34308
34309          if (_isArray20) {
34310            if (_i21 >= _iterator20.length) break;
34311            _ref19 = _iterator20[_i21++];
34312          } else {
34313            _i21 = _iterator20.next();
34314            if (_i21.done) break;
34315            _ref19 = _i21.value;
34316          }
34317
34318          var groupedFile = _ref19;
34319
34320          groupedFile.status = Dropzone.CANCELED;
34321        }
34322        if (typeof file.xhr !== 'undefined') {
34323          file.xhr.abort();
34324        }
34325        for (var _iterator21 = groupedFiles, _isArray21 = true, _i22 = 0, _iterator21 = _isArray21 ? _iterator21 : _iterator21[Symbol.iterator]();;) {
34326          var _ref20;
34327
34328          if (_isArray21) {
34329            if (_i22 >= _iterator21.length) break;
34330            _ref20 = _iterator21[_i22++];
34331          } else {
34332            _i22 = _iterator21.next();
34333            if (_i22.done) break;
34334            _ref20 = _i22.value;
34335          }
34336
34337          var _groupedFile = _ref20;
34338
34339          this.emit("canceled", _groupedFile);
34340        }
34341        if (this.options.uploadMultiple) {
34342          this.emit("canceledmultiple", groupedFiles);
34343        }
34344      } else if (file.status === Dropzone.ADDED || file.status === Dropzone.QUEUED) {
34345        file.status = Dropzone.CANCELED;
vendor: 7,503 bytes, lines 34346-34572
34346        this.emit("canceled", file);
34347        if (this.options.uploadMultiple) {
34348          this.emit("canceledmultiple", [file]);
34349        }
34350      }
34351
34352      if (this.options.autoProcessQueue) {
34353        return this.processQueue();
34354      }
34355    }
34356  }, {
34357    key: "resolveOption",
34358    value: function resolveOption(option) {
34359      if (typeof option === 'function') {
34360        for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
34361          args[_key3 - 1] = arguments[_key3];
34362        }
34363
34364        return option.apply(this, args);
34365      }
34366      return option;
34367    }
34368  }, {
34369    key: "uploadFile",
34370    value: function uploadFile(file) {
34371      return this.uploadFiles([file]);
34372    }
34373  }, {
34374    key: "uploadFiles",
34375    value: function uploadFiles(files) {
34376      var _this14 = this;
34377
34378      this._transformFiles(files, function (transformedFiles) {
34379        if (files[0].upload.chunked) {
34380          // This file should be sent in chunks!
34381
34382          // If the chunking option is set, we **know** that there can only be **one** file, since
34383          // uploadMultiple is not allowed with this option.
34384          var file = files[0];
34385          var transformedFile = transformedFiles[0];
34386          var startedChunkCount = 0;
34387
34388          file.upload.chunks = [];
34389
34390          var handleNextChunk = function handleNextChunk() {
34391            var chunkIndex = 0;
34392
34393            // Find the next item in file.upload.chunks that is not defined yet.
34394            while (file.upload.chunks[chunkIndex] !== undefined) {
34395              chunkIndex++;
34396            }
34397
34398            // This means, that all chunks have already been started.
34399            if (chunkIndex >= file.upload.totalChunkCount) return;
34400
34401            startedChunkCount++;
34402
34403            var start = chunkIndex * _this14.options.chunkSize;
34404            var end = Math.min(start + _this14.options.chunkSize, file.size);
34405
34406            var dataBlock = {
34407              name: _this14._getParamName(0),
34408              data: transformedFile.webkitSlice ? transformedFile.webkitSlice(start, end) : transformedFile.slice(start, end),
34409              filename: file.upload.filename,
34410              chunkIndex: chunkIndex
34411            };
34412
34413            file.upload.chunks[chunkIndex] = {
34414              file: file,
34415              index: chunkIndex,
34416              dataBlock: dataBlock, // In case we want to retry.
34417              status: Dropzone.UPLOADING,
34418              progress: 0,
34419              retries: 0 // The number of times this block has been retried.
34420            };
34421
34422            _this14._uploadData(files, [dataBlock]);
34423          };
34424
34425          file.upload.finishedChunkUpload = function (chunk) {
34426            var allFinished = true;
34427            chunk.status = Dropzone.SUCCESS;
34428
34429            // Clear the data from the chunk
34430            chunk.dataBlock = null;
34431            // Leaving this reference to xhr intact here will cause memory leaks in some browsers
34432            chunk.xhr = null;
34433
34434            for (var i = 0; i < file.upload.totalChunkCount; i++) {
34435              if (file.upload.chunks[i] === undefined) {
34436                return handleNextChunk();
34437              }
34438              if (file.upload.chunks[i].status !== Dropzone.SUCCESS) {
34439                allFinished = false;
34440              }
34441            }
34442
34443            if (allFinished) {
34444              _this14.options.chunksUploaded(file, function () {
34445                _this14._finished(files, '', null);
34446              });
34447            }
34448          };
34449
34450          if (_this14.options.parallelChunkUploads) {
34451            for (var i = 0; i < file.upload.totalChunkCount; i++) {
34452              handleNextChunk();
34453            }
34454          } else {
34455            handleNextChunk();
34456          }
34457        } else {
34458          var dataBlocks = [];
34459          for (var _i23 = 0; _i23 < files.length; _i23++) {
34460            dataBlocks[_i23] = {
34461              name: _this14._getParamName(_i23),
34462              data: transformedFiles[_i23],
34463              filename: files[_i23].upload.filename
34464            };
34465          }
34466          _this14._uploadData(files, dataBlocks);
34467        }
34468      });
34469    }
34470
34471    /// Returns the right chunk for given file and xhr
34472
34473  }, {
34474    key: "_getChunk",
34475    value: function _getChunk(file, xhr) {
34476      for (var i = 0; i < file.upload.totalChunkCount; i++) {
34477        if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].xhr === xhr) {
34478          return file.upload.chunks[i];
34479        }
34480      }
34481    }
34482
34483    // This function actually uploads the file(s) to the server.
34484    // If dataBlocks contains the actual data to upload (meaning, that this could either be transformed
34485    // files, or individual chunks for chunked upload).
34486
34487  }, {
34488    key: "_uploadData",
34489    value: function _uploadData(files, dataBlocks) {
34490      var _this15 = this;
34491
34492      var xhr = new XMLHttpRequest();
34493
34494      // Put the xhr object in the file objects to be able to reference it later.
34495      for (var _iterator22 = files, _isArray22 = true, _i24 = 0, _iterator22 = _isArray22 ? _iterator22 : _iterator22[Symbol.iterator]();;) {
34496        var _ref21;
34497
34498        if (_isArray22) {
34499          if (_i24 >= _iterator22.length) break;
34500          _ref21 = _iterator22[_i24++];
34501        } else {
34502          _i24 = _iterator22.next();
34503          if (_i24.done) break;
34504          _ref21 = _i24.value;
34505        }
34506
34507        var file = _ref21;
34508
34509        file.xhr = xhr;
34510      }
34511      if (files[0].upload.chunked) {
34512        // Put the xhr object in the right chunk object, so it can be associated later, and found with _getChunk
34513        files[0].upload.chunks[dataBlocks[0].chunkIndex].xhr = xhr;
34514      }
34515
34516      var method = this.resolveOption(this.options.method, files);
34517      var url = this.resolveOption(this.options.url, files);
34518      xhr.open(method, url, true);
34519
34520      // Setting the timeout after open because of IE11 issue: https://gitlab.com/meno/dropzone/issues/8
34521      xhr.timeout = this.resolveOption(this.options.timeout, files);
34522
34523      // Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179
34524      xhr.withCredentials = !!this.options.withCredentials;
34525
34526      xhr.onload = function (e) {
34527        _this15._finishedUploading(files, xhr, e);
34528      };
34529
34530      xhr.onerror = function () {
34531        _this15._handleUploadError(files, xhr);
34532      };
34533
34534      // Some browsers do not have the .upload property
34535      var progressObj = xhr.upload != null ? xhr.upload : xhr;
34536      progressObj.onprogress = function (e) {
34537        return _this15._updateFilesUploadProgress(files, xhr, e);
34538      };
34539
34540      var headers = {
34541        "Accept": "application/json",
34542        "Cache-Control": "no-cache",
34543        "X-Requested-With": "XMLHttpRequest"
34544      };
34545
34546      if (this.options.headers) {
34547        Dropzone.extend(headers, this.options.headers);
34548      }
34549
34550      for (var headerName in headers) {
34551        var headerValue = headers[headerName];
34552        if (headerValue) {
34553          xhr.setRequestHeader(headerName, headerValue);
34554        }
34555      }
34556
34557      var formData = new FormData();
34558
34559      // Adding all @options parameters
34560      if (this.options.params) {
34561        var additionalParams = this.options.params;
34562        if (typeof additionalParams === 'function') {
34563          additionalParams = additionalParams.call(this, files, xhr, files[0].upload.chunked ? this._getChunk(files[0], xhr) : null);
34564        }
34565
34566        for (var key in additionalParams) {
34567          var value = additionalParams[key];
34568          formData.append(key, value);
34569        }
34570      }
34571
34572      // Let the user add additional data if necessary
34573      for (var _iterator23 = files, _isArray23 = true, _i25 = 0, _iterator23 = _isArray23 ? _iterator23 : _iterator23[Symbol.iterator]();;) {
34574        var _ref22;
34575
34576        if (_isArray23) {
34577          if (_i25 >= _iterator23.length) break;
34578          _ref22 = _iterator23[_i25++];
34579        } else {
34580          _i25 = _iterator23.next();
34581          if (_i25.done) break;
34582          _ref22 = _i25.value;
34583        }
34584
34585        var _file = _ref22;
34586
34587        this.emit("sending", _file, xhr, formData);
34588      }
34589      if (this.options.uploadMultiple) {
34590        this.emit("sendingmultiple", files, xhr, formData);
34591      }
34592
34593      this._addFormElementData(formData);
34594
34595      // Finally add the files
34596      // Has to be last because some servers (eg: S3) expect the file to be the last parameter
34597      for (var i = 0; i < dataBlocks.length; i++) {
34598        var dataBlock = dataBlocks[i];
34599        formData.append(dataBlock.name, dataBlock.data, dataBlock.filename);
34600      }
34601
34602      this.submitRequest(xhr, formData, files);
34603    }
34604
34605    // Transforms all files with this.options.transformFile and invokes done with the transformed files when done.
34606
34607  }, {
34608    key: "_transformFiles",
34609    value: function _transformFiles(files, done) {
34610      var _this16 = this;
34611
34612      var transformedFiles = [];
34613      // Clumsy way of handling asynchronous calls, until I get to add a proper Future library.
34614      var doneCounter = 0;
34615
34616      var _loop = function _loop(i) {
34617        _this16.options.transformFile.call(_this16, files[i], function (transformedFile) {
34618          transformedFiles[i] = transformedFile;
34619          if (++doneCounter === files.length) {
34620            done(transformedFiles);
34621          }
34622        });
34623      };
34624
34625      for (var i = 0; i < files.length; i++) {
34626        _loop(i);
34627      }
34628    }
34629
34630    // Takes care of adding other input elements of the form to the AJAX request
34631
34632  }, {
34633    key: "_addFormElementData",
34634    value: function _addFormElementData(formData) {
34635      // Take care of other input elements
34636      if (this.element.tagName === "FORM") {
34637        for (var _iterator24 = this.element.querySelectorAll("input, textarea, select, button"), _isArray24 = true, _i26 = 0, _iterator24 = _isArray24 ? _iterator24 : _iterator24[Symbol.iterator]();;) {
34638          var _ref23;
34639
34640          if (_isArray24) {
34641            if (_i26 >= _iterator24.length) break;
34642            _ref23 = _iterator24[_i26++];
34643          } else {
34644            _i26 = _iterator24.next();
34645            if (_i26.done) break;
34646            _ref23 = _i26.value;
34647          }
34648
34649          var input = _ref23;
34650
34651          var inputName = input.getAttribute("name");
34652          var inputType = input.getAttribute("type");
34653          if (inputType) inputType = inputType.toLowerCase();
34654
34655          // If the input doesn't have a name, we can't use it.
34656          if (typeof inputName === 'undefined' || inputName === null) continue;
34657
34658          if (input.tagName === "SELECT" && input.hasAttribute("multiple")) {
34659            // Possibly multiple values
34660            for (var _iterator25 = input.options, _isArray25 = true, _i27 = 0, _iterator25 = _isArray25 ? _iterator25 : _iterator25[Symbol.iterator]();;) {
34661              var _ref24;
34662
34663              if (_isArray25) {
34664                if (_i27 >= _iterator25.length) break;
34665                _ref24 = _iterator25[_i27++];
34666              } else {
34667                _i27 = _iterator25.next();
34668                if (_i27.done) break;
34669                _ref24 = _i27.value;
34670              }
34671
34672              var option = _ref24;
34673
34674              if (option.selected) {
34675                formData.append(inputName, option.value);
34676              }
34677            }
34678          } else if (!inputType || inputType !== "checkbox" && inputType !== "radio" || input.checked) {
34679            formData.append(inputName, input.value);
34680          }
34681        }
34682      }
34683    }
34684
34685    // Invoked when there is new progress information about given files.
34686    // If e is not provided, it is assumed that the upload is finished.
34687
34688  }, {
34689    key: "_updateFilesUploadProgress",
34690    value: function _updateFilesUploadProgress(files, xhr, e) {
34691      var progress = void 0;
34692      if (typeof e !== 'undefined') {
34693        progress = 100 * e.loaded / e.total;
34694
34695        if (files[0].upload.chunked) {
34696          var file = files[0];
34697          // Since this is a chunked upload, we need to update the appropriate chunk progress.
34698          var chunk = this._getChunk(file, xhr);
34699          chunk.progress = progress;
34700          chunk.total = e.total;
34701          chunk.bytesSent = e.loaded;
34702          var fileProgress = 0,
34703              fileTotal = void 0,
34704              fileBytesSent = void 0;
34705          file.upload.progress = 0;
34706          file.upload.total = 0;
34707          file.upload.bytesSent = 0;
34708          for (var i = 0; i < file.upload.totalChunkCount; i++) {
34709            if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].progress !== undefined) {
34710              file.upload.progress += file.upload.chunks[i].progress;
34711              file.upload.total += file.upload.chunks[i].total;
34712              file.upload.bytesSent += file.upload.chunks[i].bytesSent;
34713            }
34714          }
34715          file.upload.progress = file.upload.progress / file.upload.totalChunkCount;
34716        } else {
34717          for (var _iterator26 = files, _isArray26 = true, _i28 = 0, _iterator26 = _isArray26 ? _iterator26 : _iterator26[Symbol.iterator]();;) {
34718            var _ref25;
34719
34720            if (_isArray26) {
34721              if (_i28 >= _iterator26.length) break;
34722              _ref25 = _iterator26[_i28++];
34723            } else {
34724              _i28 = _iterator26.next();
34725              if (_i28.done) break;
34726              _ref25 = _i28.value;
34727            }
34728
34729            var _file2 = _ref25;
34730
34731            _file2.upload.progress = progress;
34732            _file2.upload.total = e.total;
34733            _file2.upload.bytesSent = e.loaded;
34734          }
34735        }
34736        for (var _iterator27 = files, _isArray27 = true, _i29 = 0, _iterator27 = _isArray27 ? _iterator27 : _iterator27[Symbol.iterator]();;) {
34737          var _ref26;
34738
34739          if (_isArray27) {
34740            if (_i29 >= _iterator27.length) break;
34741            _ref26 = _iterator27[_i29++];
34742          } else {
34743            _i29 = _iterator27.next();
34744            if (_i29.done) break;
34745            _ref26 = _i29.value;
34746          }
34747
34748          var _file3 = _ref26;
34749
34750          this.emit("uploadprogress", _file3, _file3.upload.progress, _file3.upload.bytesSent);
34751        }
34752      } else {
34753        // Called when the file finished uploading
34754
34755        var allFilesFinished = true;
34756
34757        progress = 100;
34758
34759        for (var _iterator28 = files, _isArray28 = true, _i30 = 0, _iterator28 = _isArray28 ? _iterator28 : _iterator28[Symbol.iterator]();;) {
34760          var _ref27;
34761
34762          if (_isArray28) {
34763            if (_i30 >= _iterator28.length) break;
34764            _ref27 = _iterator28[_i30++];
34765          } else {
34766            _i30 = _iterator28.next();
34767            if (_i30.done) break;
34768            _ref27 = _i30.value;
34769          }
34770
34771          var _file4 = _ref27;
34772
34773          if (_file4.upload.progress !== 100 || _file4.upload.bytesSent !== _file4.upload.total) {
34774            allFilesFinished = false;
34775          }
34776          _file4.upload.progress = progress;
34777          _file4.upload.bytesSent = _file4.upload.total;
34778        }
34779
34780        // Nothing to do, all files already at 100%
34781        if (allFilesFinished) {
34782          return;
34783        }
34784
34785        for (var _iterator29 = files, _isArray29 = true, _i31 = 0, _iterator29 = _isArray29 ? _iterator29 : _iterator29[Symbol.iterator]();;) {
34786          var _ref28;
34787
34788          if (_isArray29) {
34789            if (_i31 >= _iterator29.length) break;
34790            _ref28 = _iterator29[_i31++];
34791          } else {
34792            _i31 = _iterator29.next();
34793            if (_i31.done) break;
34794            _ref28 = _i31.value;
34795          }
34796
34797          var _file5 = _ref28;
34798
34799          this.emit("uploadprogress", _file5, progress, _file5.upload.bytesSent);
34800        }
34801      }
34802    }
34803  }, {
34804    key: "_finishedUploading",
34805    value: function _finishedUploading(files, xhr, e) {
34806      var response = void 0;
34807
34808      if (files[0].status === Dropzone.CANCELED) {
34809        return;
34810      }
34811
34812      if (xhr.readyState !== 4) {
34813        return;
34814      }
34815
34816      if (xhr.responseType !== 'arraybuffer' && xhr.responseType !== 'blob') {
34817        response = xhr.responseText;
34818
34819        if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) {
34820          try {
34821            response = JSON.parse(response);
34822          } catch (error) {
34823            e = error;
34824            response = "Invalid JSON response from server.";
34825          }
34826        }
34827      }
34828
34829      this._updateFilesUploadProgress(files);
34830
34831      if (!(200 <= xhr.status && xhr.status < 300)) {
34832        this._handleUploadError(files, xhr, response);
34833      } else {
34834        if (files[0].upload.chunked) {
34835          files[0].upload.finishedChunkUpload(this._getChunk(files[0], xhr));
34836        } else {
34837          this._finished(files, response, e);
34838        }
34839      }
34840    }
34841  }, {
34842    key: "_handleUploadError",
34843    value: function _handleUploadError(files, xhr, response) {
34844      if (files[0].status === Dropzone.CANCELED) {
34845        return;
34846      }
34847
34848      if (files[0].upload.chunked && this.options.retryChunks) {
34849        var chunk = this._getChunk(files[0], xhr);
34850        if (chunk.retries++ < this.options.retryChunksLimit) {
34851          this._uploadData(files, [chunk.dataBlock]);
34852          return;
34853        } else {
34854          console.warn('Retried this chunk too often. Giving up.');
34855        }
34856      }
34857
34858      for (var _iterator30 = files, _isArray30 = true, _i32 = 0, _iterator30 = _isArray30 ? _iterator30 : _iterator30[Symbol.iterator]();;) {
34859        var _ref29;
34860
34861        if (_isArray30) {
34862          if (_i32 >= _iterator30.length) break;
34863          _ref29 = _iterator30[_i32++];
34864        } else {
34865          _i32 = _iterator30.next();
34866          if (_i32.done) break;
34867          _ref29 = _i32.value;
34868        }
34869
34870        var file = _ref29;
34871
34872        this._errorProcessing(files, response || this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr);
34873      }
34874    }
34875  }, {
34876    key: "submitRequest",
34877    value: function submitRequest(xhr, formData, files) {
34878      xhr.send(formData);
34879    }
34880
vendor: 6,855 bytes, lines 34881-35095
34881    // Called internally when processing is finished.
34882    // Individual callbacks have to be called in the appropriate sections.
34883
34884  }, {
34885    key: "_finished",
34886    value: function _finished(files, responseText, e) {
34887      for (var _iterator31 = files, _isArray31 = true, _i33 = 0, _iterator31 = _isArray31 ? _iterator31 : _iterator31[Symbol.iterator]();;) {
34888        var _ref30;
34889
34890        if (_isArray31) {
34891          if (_i33 >= _iterator31.length) break;
34892          _ref30 = _iterator31[_i33++];
34893        } else {
34894          _i33 = _iterator31.next();
34895          if (_i33.done) break;
34896          _ref30 = _i33.value;
34897        }
34898
34899        var file = _ref30;
34900
34901        file.status = Dropzone.SUCCESS;
34902        this.emit("success", file, responseText, e);
34903        this.emit("complete", file);
34904      }
34905      if (this.options.uploadMultiple) {
34906        this.emit("successmultiple", files, responseText, e);
34907        this.emit("completemultiple", files);
34908      }
34909
34910      if (this.options.autoProcessQueue) {
34911        return this.processQueue();
34912      }
34913    }
34914
34915    // Called internally when processing is finished.
34916    // Individual callbacks have to be called in the appropriate sections.
34917
34918  }, {
34919    key: "_errorProcessing",
34920    value: function _errorProcessing(files, message, xhr) {
34921      for (var _iterator32 = files, _isArray32 = true, _i34 = 0, _iterator32 = _isArray32 ? _iterator32 : _iterator32[Symbol.iterator]();;) {
34922        var _ref31;
34923
34924        if (_isArray32) {
34925          if (_i34 >= _iterator32.length) break;
34926          _ref31 = _iterator32[_i34++];
34927        } else {
34928          _i34 = _iterator32.next();
34929          if (_i34.done) break;
34930          _ref31 = _i34.value;
34931        }
34932
34933        var file = _ref31;
34934
34935        file.status = Dropzone.ERROR;
34936        this.emit("error", file, message, xhr);
34937        this.emit("complete", file);
34938      }
34939      if (this.options.uploadMultiple) {
34940        this.emit("errormultiple", files, message, xhr);
34941        this.emit("completemultiple", files);
34942      }
34943
34944      if (this.options.autoProcessQueue) {
34945        return this.processQueue();
34946      }
34947    }
34948  }], [{
34949    key: "uuidv4",
34950    value: function uuidv4() {
34951      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
34952        var r = Math.random() * 16 | 0,
34953            v = c === 'x' ? r : r & 0x3 | 0x8;
34954        return v.toString(16);
34955      });
34956    }
34957  }]);
34958
34959  return Dropzone;
34960}(Emitter);
34961
34962Dropzone.initClass();
34963
34964Dropzone.version = "5.5.1";
34965
34966// This is a map of options for your different dropzones. Add configurations
34967// to this object for your different dropzone elemens.
34968//
34969// Example:
34970//
34971//     Dropzone.options.myDropzoneElementId = { maxFilesize: 1 };
34972//
34973// To disable autoDiscover for a specific element, you can set `false` as an option:
34974//
34975//     Dropzone.options.myDisabledElementId = false;
34976//
34977// And in html:
34978//
34979//     <form action="/upload" id="my-dropzone-element-id" class="dropzone"></form>
34980Dropzone.options = {};
34981
34982// Returns the options for an element or undefined if none available.
34983Dropzone.optionsForElement = function (element) {
34984  // Get the `Dropzone.options.elementId` for this element if it exists
34985  if (element.getAttribute("id")) {
34986    return Dropzone.options[camelize(element.getAttribute("id"))];
34987  } else {
34988    return undefined;
34989  }
34990};
34991
34992// Holds a list of all dropzone instances
34993Dropzone.instances = [];
34994
34995// Returns the dropzone for given element if any
34996Dropzone.forElement = function (element) {
34997  if (typeof element === "string") {
34998    element = document.querySelector(element);
34999  }
35000  if ((element != null ? element.dropzone : undefined) == null) {
35001    throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.");
35002  }
35003  return element.dropzone;
35004};
35005
35006// Set to false if you don't want Dropzone to automatically find and attach to .dropzone elements.
35007Dropzone.autoDiscover = true;
35008
35009// Looks for all .dropzone elements and creates a dropzone for them
35010Dropzone.discover = function () {
35011  var dropzones = void 0;
35012  if (document.querySelectorAll) {
35013    dropzones = document.querySelectorAll(".dropzone");
35014  } else {
35015    dropzones = [];
35016    // IE :(
35017    var checkElements = function checkElements(elements) {
35018      return function () {
35019        var result = [];
35020        for (var _iterator33 = elements, _isArray33 = true, _i35 = 0, _iterator33 = _isArray33 ? _iterator33 : _iterator33[Symbol.iterator]();;) {
35021          var _ref32;
35022
35023          if (_isArray33) {
35024            if (_i35 >= _iterator33.length) break;
35025            _ref32 = _iterator33[_i35++];
35026          } else {
35027            _i35 = _iterator33.next();
35028            if (_i35.done) break;
35029            _ref32 = _i35.value;
35030          }
35031
35032          var el = _ref32;
35033
35034          if (/(^| )dropzone($| )/.test(el.className)) {
35035            result.push(dropzones.push(el));
35036          } else {
35037            result.push(undefined);
35038          }
35039        }
35040        return result;
35041      }();
35042    };
35043    checkElements(document.getElementsByTagName("div"));
35044    checkElements(document.getElementsByTagName("form"));
35045  }
35046
35047  return function () {
35048    var result = [];
35049    for (var _iterator34 = dropzones, _isArray34 = true, _i36 = 0, _iterator34 = _isArray34 ? _iterator34 : _iterator34[Symbol.iterator]();;) {
35050      var _ref33;
35051
35052      if (_isArray34) {
35053        if (_i36 >= _iterator34.length) break;
35054        _ref33 = _iterator34[_i36++];
35055      } else {
35056        _i36 = _iterator34.next();
35057        if (_i36.done) break;
35058        _ref33 = _i36.value;
35059      }
35060
35061      var dropzone = _ref33;
35062
35063      // Create a dropzone unless auto discover has been disabled for specific element
35064      if (Dropzone.optionsForElement(dropzone) !== false) {
35065        result.push(new Dropzone(dropzone));
35066      } else {
35067        result.push(undefined);
35068      }
35069    }
35070    return result;
35071  }();
35072};
35073
35074// Since the whole Drag'n'Drop API is pretty new, some browsers implement it,
35075// but not correctly.
35076// So I created a blacklist of userAgents. Yes, yes. Browser sniffing, I know.
35077// But what to do when browsers *theoretically* support an API, but crash
35078// when using it.
35079//
35080// This is a list of regular expressions tested against navigator.userAgent
35081//
35082// ** It should only be used on browser that *do* support the API, but
35083// incorrectly **
35084//
35085Dropzone.blacklistedBrowsers = [
35086// The mac os and windows phone version of opera 12 seems to have a problem with the File drag'n'drop API.
35087/opera.*(Macintosh|Windows Phone).*version\/12/i];
35088
35089// Checks if the browser is supported
35090Dropzone.isBrowserSupported = function () {
35091  var capableBrowser = true;
35092
35093  if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) {
35094    if (!("classList" in document.createElement("a"))) {
35095      capableBrowser = false;
35096    } else {
35097      // The browser supports the API, but may be blacklisted.
35098      for (var _iterator35 = Dropzone.blacklistedBrowsers, _isArray35 = true, _i37 = 0, _iterator35 = _isArray35 ? _iterator35 : _iterator35[Symbol.iterator]();;) {
35099        var _ref34;
35100
35101        if (_isArray35) {
35102          if (_i37 >= _iterator35.length) break;
35103          _ref34 = _iterator35[_i37++];
35104        } else {
35105          _i37 = _iterator35.next();
35106          if (_i37.done) break;
35107          _ref34 = _i37.value;
35108        }
35109
35110        var regex = _ref34;
35111
35112        if (regex.test(navigator.userAgent)) {
35113          capableBrowser = false;
35114          continue;
35115        }
35116      }
35117    }
35118  } else {
35119    capableBrowser = false;
35120  }
35121
35122  return capableBrowser;
35123};
35124
35125Dropzone.dataURItoBlob = function (dataURI) {
35126  // convert base64 to raw binary data held in a string
35127  // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
35128  var byteString = atob(dataURI.split(',')[1]);
35129
35130  // separate out the mime component
35131  var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
35132
35133  // write the bytes of the string to an ArrayBuffer
35134  var ab = new ArrayBuffer(byteString.length);
35135  var ia = new Uint8Array(ab);
35136  for (var i = 0, end = byteString.length, asc = 0 <= end; asc ? i <= end : i >= end; asc ? i++ : i--) {
35137    ia[i] = byteString.charCodeAt(i);
35138  }
35139
35140  // write the ArrayBuffer to a blob
35141  return new Blob([ab], { type: mimeString });
35142};
35143
35144// Returns an array without the rejected item
35145var without = function without(list, rejectedItem) {
35146  return list.filter(function (item) {
35147    return item !== rejectedItem;
35148  }).map(function (item) {
35149    return item;
35150  });
35151};
35152
35153// abc-def_ghi -> abcDefGhi
35154var camelize = function camelize(str) {
35155  return str.replace(/[\-_](\w)/g, function (match) {
35156    return match.charAt(1).toUpperCase();
35157  });
35158};
35159
35160// Creates an element from string
35161Dropzone.createElement = function (string) {
35162  var div = document.createElement("div");
35163  div.innerHTML = string;
35164  return div.childNodes[0];
35165};
35166
35167// Tests if given element is inside (or simply is) the container
35168Dropzone.elementInside = function (element, container) {
35169  if (element === container) {
35170    return true;
35171  } // Coffeescript doesn't support do/while loops
35172  while (element = element.parentNode) {
35173    if (element === container) {
35174      return true;
35175    }
35176  }
35177  return false;
35178};
35179
35180Dropzone.getElement = function (el, name) {
35181  var element = void 0;
35182  if (typeof el === "string") {
35183    element = document.querySelector(el);
35184  } else if (el.nodeType != null) {
35185    element = el;
35186  }
35187  if (element == null) {
35188    throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector or a plain HTML element.");
35189  }
35190  return element;
35191};
35192
35193Dropzone.getElements = function (els, name) {
35194  var el = void 0,
35195      elements = void 0;
35196  if (els instanceof Array) {
35197    elements = [];
35198    try {
35199      for (var _iterator36 = els, _isArray36 = true, _i38 = 0, _iterator36 = _isArray36 ? _iterator36 : _iterator36[Symbol.iterator]();;) {
35200        if (_isArray36) {
35201          if (_i38 >= _iterator36.length) break;
35202          el = _iterator36[_i38++];
35203        } else {
35204          _i38 = _iterator36.next();
35205          if (_i38.done) break;
35206          el = _i38.value;
35207        }
35208
35209        elements.push(this.getElement(el, name));
35210      }
35211    } catch (e) {
35212      elements = null;
35213    }
35214  } else if (typeof els === "string") {
35215    elements = [];
35216    for (var _iterator37 = document.querySelectorAll(els), _isArray37 = true, _i39 = 0, _iterator37 = _isArray37 ? _iterator37 : _iterator37[Symbol.iterator]();;) {
35217      if (_isArray37) {
35218        if (_i39 >= _iterator37.length) break;
35219        el = _iterator37[_i39++];
35220      } else {
35221        _i39 = _iterator37.next();
35222        if (_i39.done) break;
35223        el = _i39.value;
35224      }
35225
35226      elements.push(el);
35227    }
35228  } else if (els.nodeType != null) {
35229    elements = [els];
35230  }
35231
35232  if (elements == null || !elements.length) {
35233    throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector, a plain HTML element or a list of those.");
35234  }
35235
35236  return elements;
35237};
35238
35239// Asks the user the question and calls accepted or rejected accordingly
35240//
35241// The default implementation just uses `window.confirm` and then calls the
35242// appropriate callback.
35243Dropzone.confirm = function (question, accepted, rejected) {
35244  if (window.confirm(question)) {
35245    return accepted();
35246  } else if (rejected != null) {
35247    return rejected();
35248  }
35249};
35250
35251// Validates the mime type like this:
35252//
35253// https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept
35254Dropzone.isValidFile = function (file, acceptedFiles) {
35255  if (!acceptedFiles) {
35256    return true;
35257  } // If there are no accepted mime types, it's OK
35258  acceptedFiles = acceptedFiles.split(",");
35259
35260  var mimeType = file.type;
35261  var baseMimeType = mimeType.replace(/\/.*$/, "");
35262
35263  for (var _iterator38 = acceptedFiles, _isArray38 = true, _i40 = 0, _iterator38 = _isArray38 ? _iterator38 : _iterator38[Symbol.iterator]();;) {
35264    var _ref35;
35265
35266    if (_isArray38) {
35267      if (_i40 >= _iterator38.length) break;
35268      _ref35 = _iterator38[_i40++];
35269    } else {
35270      _i40 = _iterator38.next();
35271      if (_i40.done) break;
35272      _ref35 = _i40.value;
35273    }
35274
35275    var validType = _ref35;
35276
35277    validType = validType.trim();
35278    if (validType.charAt(0) === ".") {
35279      if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) {
35280        return true;
35281      }
35282    } else if (/\/\*$/.test(validType)) {
35283      // This is something like a image/* mime type
35284      if (baseMimeType === validType.replace(/\/.*$/, "")) {
35285        return true;
35286      }
35287    } else {
35288      if (mimeType === validType) {
35289        return true;
35290      }
35291    }
35292  }
35293
35294  return false;
35295};
35296
35297// Augment jQuery
35298if (typeof jQuery !== 'undefined' && jQuery !== null) {
35299  jQuery.fn.dropzone = function (options) {
35300    return this.each(function () {
35301      return new Dropzone(this, options);
35302    });
35303  };
35304}
35305
35306if (typeof module !== 'undefined' && module !== null) {
35307  module.exports = Dropzone;
35308} else {
35309  window.Dropzone = Dropzone;
35310}
35311
35312// Dropzone file status codes
35313Dropzone.ADDED = "added";
35314
35315Dropzone.QUEUED = "queued";
35316// For backwards compatibility. Now, if a file is accepted, it's either queued
35317// or uploading.
35318Dropzone.ACCEPTED = Dropzone.QUEUED;
35319
35320Dropzone.UPLOADING = "uploading";
35321Dropzone.PROCESSING = Dropzone.UPLOADING; // alias
35322
35323Dropzone.CANCELED = "canceled";
35324Dropzone.ERROR = "error";
35325Dropzone.SUCCESS = "success";
35326
35327/*
35328
35329 Bugfix for iOS 6 and 7
35330 Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios
35331 based on the work of https://github.com/stomita/ios-imagefile-megapixel
35332
35333 */
35334
35335// Detecting vertical squash in loaded image.
35336// Fixes a bug which squash image vertically while drawing into canvas for some images.
35337// This is a bug in iOS6 devices. This function from https://github.com/stomita/ios-imagefile-megapixel
35338var detectVerticalSquash = function detectVerticalSquash(img) {
35339  var iw = img.naturalWidth;
35340  var ih = img.naturalHeight;
35341  var canvas = document.createElement("canvas");
35342  canvas.width = 1;
35343  canvas.height = ih;
35344  var ctx = canvas.getContext("2d");
35345  ctx.drawImage(img, 0, 0);
35346
35347  var _ctx$getImageData = ctx.getImageData(1, 0, 1, ih),
35348      data = _ctx$getImageData.data;
35349
35350  // search image edge pixel position in case it is squashed vertically.
35351
35352
35353  var sy = 0;
35354  var ey = ih;
35355  var py = ih;
35356  while (py > sy) {
35357    var alpha = data[(py - 1) * 4 + 3];
35358
35359    if (alpha === 0) {
35360      ey = py;
35361    } else {
35362      sy = py;
35363    }
35364
35365    py = ey + sy >> 1;
35366  }
35367  var ratio = py / ih;
35368
35369  if (ratio === 0) {
35370    return 1;
35371  } else {
35372    return ratio;
35373  }
35374};
35375
35376// A replacement for context.drawImage
35377// (args are for source and destination).
35378var drawImageIOSFix = function drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {
35379  var vertSquashRatio = detectVerticalSquash(img);
35380  return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);
35381};
35382
35383// Based on MinifyJpeg
35384// Source: http://www.perry.cz/files/ExifRestorer.js
35385// http://elicon.blog57.fc2.com/blog-entry-206.html
35386
35387var ExifRestore = function () {
35388  function ExifRestore() {
35389    _classCallCheck(this, ExifRestore);
35390  }
35391
35392  _createClass(ExifRestore, null, [{
35393    key: "initClass",
35394    value: function initClass() {
35395      this.KEY_STR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
vendor: 7,423 bytes, lines 35395-35646
35395+/=';
35396    }
35397  }, {
35398    key: "encode64",
35399    value: function encode64(input) {
35400      var output = '';
35401      var chr1 = undefined;
35402      var chr2 = undefined;
35403      var chr3 = '';
35404      var enc1 = undefined;
35405      var enc2 = undefined;
35406      var enc3 = undefined;
35407      var enc4 = '';
35408      var i = 0;
35409      while (true) {
35410        chr1 = input[i++];
35411        chr2 = input[i++];
35412        chr3 = input[i++];
35413        enc1 = chr1 >> 2;
35414        enc2 = (chr1 & 3) << 4 | chr2 >> 4;
35415        enc3 = (chr2 & 15) << 2 | chr3 >> 6;
35416        enc4 = chr3 & 63;
35417        if (isNaN(chr2)) {
35418          enc3 = enc4 = 64;
35419        } else if (isNaN(chr3)) {
35420          enc4 = 64;
35421        }
35422        output = output + this.KEY_STR.charAt(enc1) + this.KEY_STR.charAt(enc2) + this.KEY_STR.charAt(enc3) + this.KEY_STR.charAt(enc4);
35423        chr1 = chr2 = chr3 = '';
35424        enc1 = enc2 = enc3 = enc4 = '';
35425        if (!(i < input.length)) {
35426          break;
35427        }
35428      }
35429      return output;
35430    }
35431  }, {
35432    key: "restore",
35433    value: function restore(origFileBase64, resizedFileBase64) {
35434      if (!origFileBase64.match('data:image/jpeg;base64,')) {
35435        return resizedFileBase64;
35436      }
35437      var rawImage = this.decode64(origFileBase64.replace('data:image/jpeg;base64,', ''));
35438      var segments = this.slice2Segments(rawImage);
35439      var image = this.exifManipulation(resizedFileBase64, segments);
35440      return "data:image/jpeg;base64," + this.encode64(image);
35441    }
35442  }, {
35443    key: "exifManipulation",
35444    value: function exifManipulation(resizedFileBase64, segments) {
35445      var exifArray = this.getExifArray(segments);
35446      var newImageArray = this.insertExif(resizedFileBase64, exifArray);
35447      var aBuffer = new Uint8Array(newImageArray);
35448      return aBuffer;
35449    }
35450  }, {
35451    key: "getExifArray",
35452    value: function getExifArray(segments) {
35453      var seg = undefined;
35454      var x = 0;
35455      while (x < segments.length) {
35456        seg = segments[x];
35457        if (seg[0] === 255 & seg[1] === 225) {
35458          return seg;
35459        }
35460        x++;
35461      }
35462      return [];
35463    }
35464  }, {
35465    key: "insertExif",
35466    value: function insertExif(resizedFileBase64, exifArray) {
35467      var imageData = resizedFileBase64.replace('data:image/jpeg;base64,', '');
35468      var buf = this.decode64(imageData);
35469      var separatePoint = buf.indexOf(255, 3);
35470      var mae = buf.slice(0, separatePoint);
35471      var ato = buf.slice(separatePoint);
35472      var array = mae;
35473      array = array.concat(exifArray);
35474      array = array.concat(ato);
35475      return array;
35476    }
35477  }, {
35478    key: "slice2Segments",
35479    value: function slice2Segments(rawImageArray) {
35480      var head = 0;
35481      var segments = [];
35482      while (true) {
35483        var length;
35484        if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 218) {
35485          break;
35486        }
35487        if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 216) {
35488          head += 2;
35489        } else {
35490          length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3];
35491          var endPoint = head + length + 2;
35492          var seg = rawImageArray.slice(head, endPoint);
35493          segments.push(seg);
35494          head = endPoint;
35495        }
35496        if (head > rawImageArray.length) {
35497          break;
35498        }
35499      }
35500      return segments;
35501    }
35502  }, {
35503    key: "decode64",
35504    value: function decode64(input) {
35505      var output = '';
35506      var chr1 = undefined;
35507      var chr2 = undefined;
35508      var chr3 = '';
35509      var enc1 = undefined;
35510      var enc2 = undefined;
35511      var enc3 = undefined;
35512      var enc4 = '';
35513      var i = 0;
35514      var buf = [];
35515      // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
35516      var base64test = /[^A-Za-z0-9\+\/\=]/g;
35517      if (base64test.exec(input)) {
35518        console.warn('There were invalid base64 characters in the input text.\nValid base64 characters are A-Z, a-z, 0-9, \'+\', \'/\',and \'=\'\nExpect errors in decoding.');
35519      }
35520      input = input.replace(/[^A-Za-z0-9\+\/\=]/g, '');
35521      while (true) {
35522        enc1 = this.KEY_STR.indexOf(input.charAt(i++));
35523        enc2 = this.KEY_STR.indexOf(input.charAt(i++));
35524        enc3 = this.KEY_STR.indexOf(input.charAt(i++));
35525        enc4 = this.KEY_STR.indexOf(input.charAt(i++));
35526        chr1 = enc1 << 2 | enc2 >> 4;
35527        chr2 = (enc2 & 15) << 4 | enc3 >> 2;
35528        chr3 = (enc3 & 3) << 6 | enc4;
35529        buf.push(chr1);
35530        if (enc3 !== 64) {
35531          buf.push(chr2);
35532        }
35533        if (enc4 !== 64) {
35534          buf.push(chr3);
35535        }
35536        chr1 = chr2 = chr3 = '';
35537        enc1 = enc2 = enc3 = enc4 = '';
35538        if (!(i < input.length)) {
35539          break;
35540        }
35541      }
35542      return buf;
35543    }
35544  }]);
35545
35546  return ExifRestore;
35547}();
35548
35549ExifRestore.initClass();
35550
35551/*
35552 * contentloaded.js
35553 *
35554 * Author: Diego Perini (diego.perini at gmail.com)
35555 * Summary: cross-browser wrapper for DOMContentLoaded
35556 * Updated: 20101020
35557 * License: MIT
35558 * Version: 1.2
35559 *
35560 * URL:
35561 * http://javascript.nwbox.com/ContentLoaded/
35562 * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
35563 */
35564
35565// @win window reference
35566// @fn function reference
35567var contentLoaded = function contentLoaded(win, fn) {
35568  var done = false;
35569  var top = true;
35570  var doc = win.document;
35571  var root = doc.documentElement;
35572  var add = doc.addEventListener ? "addEventListener" : "attachEvent";
35573  var rem = doc.addEventListener ? "removeEventListener" : "detachEvent";
35574  var pre = doc.addEventListener ? "" : "on";
35575  var init = function init(e) {
35576    if (e.type === "readystatechange" && doc.readyState !== "complete") {
35577      return;
35578    }
35579    (e.type === "load" ? win : doc)[rem](pre + e.type, init, false);
35580    if (!done && (done = true)) {
35581      return fn.call(win, e.type || e);
35582    }
35583  };
35584
35585  var poll = function poll() {
35586    try {
35587      root.doScroll("left");
35588    } catch (e) {
35589      setTimeout(poll, 50);
35590      return;
35591    }
35592    return init("poll");
35593  };
35594
35595  if (doc.readyState !== "complete") {
35596    if (doc.createEventObject && root.doScroll) {
35597      try {
35598        top = !win.frameElement;
35599      } catch (error) {}
35600      if (top) {
35601        poll();
35602      }
35603    }
35604    doc[add](pre + "DOMContentLoaded", init, false);
35605    doc[add](pre + "readystatechange", init, false);
35606    return win[add](pre + "load", init, false);
35607  }
35608};
35609
35610// As a single function to be able to write tests.
35611Dropzone._autoDiscoverFunction = function () {
35612  if (Dropzone.autoDiscover) {
35613    return Dropzone.discover();
35614  }
35615};
35616contentLoaded(window, Dropzone._autoDiscoverFunction);
35617
35618function __guard__(value, transform) {
35619  return typeof value !== 'undefined' && value !== null ? transform(value) : undefined;
35620}
35621function __guardMethod__(obj, methodName, transform) {
35622  if (typeof obj !== 'undefined' && obj !== null && typeof obj[methodName] === 'function') {
35623    return transform(obj, methodName);
35624  } else {
35625    return undefined;
35626  }
35627}
35628
35629/**
35630 * Super simple wysiwyg editor v0.8.11
35631 * https://summernote.org
35632 *
35633 * Copyright 2013- Alan Hong. and other contributors
35634 * summernote may be freely distributed under the MIT license.
35635 *
35636 * Date: 2018-11-24T12:13Z
35637 */
35638(function (global, factory) {
35639  typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('jquery')) :
35640  typeof define === 'function' && define.amd ? define(['jquery'], factory) :
35641  (factory(global.jQuery));
35642}(this, (function ($$1) { 'use strict';
35643
35644  $$1 = $$1 && $$1.hasOwnProperty('default') ? $$1['default'] : $$1;
35645
35646  var Renderer = /** @class */ (function () {
35647      function Renderer(markup, children, options, callback) {
35648          this.markup = markup;
35649          this.children = children;
35650          this.options = options;
35651          this.callback = callback;
35652      }
35653      Renderer.prototype.render = function ($parent) {
35654          var $node = $$1(this.markup);
35655          if (this.options && this.options.contents) {
35656              $node.html(this.options.contents);
35657          }
35658          if (this.options && this.options.className) {
35659              $node.addClass(this.options.className);
35660          }
35661          if (this.options && this.options.data) {
35662              $$1.each(this.options.data, function (k, v) {
35663                  $node.attr('data-' + k, v);
35664              });
35665          }
35666          if (this.options && this.options.click) {
35667              $node.on('click', this.options.click);
35668          }
35669          if (this.children) {
35670              var $container_1 = $node.find('.note-children-container');
35671              this.children.forEach(function (child) {
35672                  child.render($container_1.length ? $container_1 : $node);
35673              });
35674          }
35675          if (this.callback) {
35676              this.callback($node, this.options);
35677          }
35678          if (this.options && this.options.callback) {
35679              this.options.callback($node);
35680          }
35681          if ($parent) {
35682              $parent.append($node);
35683          }
35684          return $node;
35685      };
35686      return Renderer;
35687  }());
35688  var renderer = {
35689      create: function (markup, callback) {
35690          return function () {
35691              var options = typeof arguments[1] === 'object' ? arguments[1] : arguments[0];
35692              var children = $$1.isArray(arguments[0]) ? arguments[0] : [];
35693              if (options && options.children) {
35694                  children = options.children;
35695              }
35696              return new Renderer(markup, children, options, callback);
35697          };
35698      }
35699  };
35700
35701  var editor = renderer.create('<div class="note-editor note-frame panel panel-default"/>');
35702  var toolbar = renderer.create('<div class="note-toolbar panel-heading" role="toolbar"></div></div>');
35703  var editingArea = renderer.create('<div class="note-editing-area"/>');
35704  var codable = renderer.create('<textarea class="note-codable" role="textbox" aria-multiline="true"/>');
35705  var editable = renderer.create('<div class="note-editable" contentEditable="true" role="textbox" aria-multiline="true"/>');
35706  var statusbar = renderer.create([
35707      '<output class="note-status-output" aria-live="polite"/>',
35708      '<div class="note-statusbar" role="status">',
35709      '  <div class="note-resizebar" role="seperator" aria-orientation="horizontal" aria-label="Resize">',
35710      '    <div class="note-icon-bar"/>',
35711      '    <div class="note-icon-bar"/>',
35712      '    <div class="note-icon-bar"/>',
35713      '  </div>',
35714      '</div>'
35715  ].join(''));
35716  var airEditor = renderer.create('<div class="note-editor"/>');
35717  var airEditable = renderer.create([
35718      '<div class="note-editable" contentEditable="true" role="textbox" aria-multiline="true"/>',
35719      '<output class="note-status-output" aria-live="polite"/>'
35720  ].join(''));
35721  var buttonGroup = renderer.create('<div class="note-btn-group btn-group">');
35722  var dropdown = renderer.create('<ul class="dropdown-menu" role="list">', function ($node, options) {
35723      var markup = $$1.isArray(options.items) ? options.items.map(function (item) {
35724          var value = (typeof item === 'string') ? item : (item.value || '');
35725          var content = options.template ? options.template(item) : item;
35726          var option = (typeof item === 'object') ? item.option : undefined;
35727          var dataValue = 'data-value="' + value + '"';
35728          var dataOption = (option !== undefined) ? ' data-option="' + option + '"' : '';
35729          return '<li role="listitem" aria-label="' + item + '"><a href="#" ' + (dataValue + dataOption) + '>' + content + '</a></li>';
35730      }).join('') : options.items;
35731      $node.html(markup).attr({ 'aria-label': options.title });
35732  });
35733  var dropdownButtonContents = function (contents, options) {
35734      return contents + ' ' + icon(options.icons.caret, 'span');
35735  };
35736  var dropdownCheck = renderer.create('<ul class="dropdown-menu note-check" role="list">', function ($node, options) {
35737      var markup = $$1.isArray(options.items) ? options.items.map(function (item) {
35738          var value = (typeof item === 'string') ? item : (item.value || '');
35739          var content = options.template ? options.template(item) : item;
35740          return '<li role="listitem" aria-label="' + item + '"><a href="#" data-value="' + value + '">' + icon(options.checkClassName) + ' ' + content + '</a></li>';
35741      }).join('') : options.items;
35742      $node.html(markup).attr({ 'aria-label': options.title });
35743  });
35744  var palette = renderer.create('<div class="note-color-palette"/>', function ($node, options) {
35745      var contents = [];
35746      for (var row = 0, rowSize = options.colors.length; row < rowSize; row++) {
35747          var eventName = options.eventName;
35748          var colors = options.colors[row];
35749          var colorsName = options.colorsName[row];
35750          var buttons = [];
35751          for (var col = 0, colSize = colors.length; col < colSize; col++) {
35752              var color = colors[col];
35753              var colorName = colorsName[col];
35754              buttons.push([
35755                  '<button type="button" class="note-color-btn"',
35756                  'style="background-color:', color, '" ',
35757                  'data-event="', eventName, '" ',
35758                  'data-value="', color, '" ',
35759                  'title="', colorName, '" ',
35760                  'aria-label="', colorName, '" ',
35761                  'data-toggle="button" tabindex="-1"></button>'
35762              ].join(''));
35763          }
35764          contents.push('<div class="note-color-row">' + buttons.join('') + '</div>');
35765      }
35766      $node.html(contents.join(''));
35767      if (options.tooltip) {
35768          $node.find('.note-color-btn').tooltip({
35769              container: options.container,
35770              trigger: 'hover',
35771              placement: 'bottom'
35772          });
35773      }
35774  });
35775  var dialog = renderer.create('<div class="modal" aria-hidden="false" tabindex="-1" role="dialog"/>', function ($node, options) {
35776      if (options.fade) {
35777          $node.addClass('fade');
35778      }
35779      $node.attr({
35780          'aria-label': options.title
35781      });
35782      $node.html([
35783          '<div class="modal-dialog">',
35784          '  <div class="modal-content">',
35785          (options.title
35786              ? '    <div class="modal-header">' +
35787                  '      <button type="button" class="close" data-dismiss="modal" aria-label="Close" aria-hidden="true">&times;</button>' +
35788                  '      <h4 class="modal-title">' + options.title + '</h4>' +
35789                  '    </div>' : ''),
35790          '    <div class="modal-body">' + options.body + '</div>',
35791          (options.footer
35792              ? '    <div class="modal-footer">' + options.footer + '</div>' : ''),
35793          '  </div>',
35794          '</div>'
35795      ].join(''));
35796  });
35797  var popover = renderer.create([
35798      '<div class="note-popover popover in">',
35799      '  <div class="arrow"/>',
35800      '  <div class="popover-content note-children-container"/>',
35801      '</div>'
35802  ].join(''), function ($node, options) {
35803      var direction = typeof options.direction !== 'undefined' ? options.direction : 'bottom';
35804      $node.addClass(direction);
35805      if (options.hideArrow) {
35806          $node.find('.arrow').hide();
35807      }
35808  });
35809  var checkbox = renderer.create('<div class="checkbox"></div>', function ($node, options) {
35810      $node.html([
35811          '<label' + (options.id ? ' for="' + options.id + '"' : '') + '>',
35812          ' <input role="checkbox" type="checkbox"' + (options.id ? ' id="' + options.id + '"' : ''),
35813          (options.checked ? ' checked' : ''),
35814          ' aria-checked="' + (options.checked ? 'true' : 'false') + '"/>',
35815          (options.text ? options.text : ''),
35816          '</label>'
35817      ].join(''));
35818  });
35819  var icon = function (iconClassName, tagName) {
35820      tagName = tagName || 'i';
35821      return '<' + tagName + ' class="' + iconClassName + '"/>';
35822  };
35823  var ui = {
35824      editor: editor,
35825      toolbar: toolbar,
35826      editingArea: editingArea,
35827      codable: codable,
35828      editable: editable,
35829      statusbar: statusbar,
35830      airEditor: airEditor,
35831      airEditable: airEditable,
35832      buttonGroup: buttonGroup,
35833      dropdown: dropdown,
35834      dropdownButtonContents: dropdownButtonContents,
35835      dropdownCheck: dropdownCheck,
35836      palette: palette,
35837      dialog: dialog,
35838      popover: popover,
35839      checkbox: checkbox,
35840      icon: icon,
35841      options: {},
35842      button: function ($node, options) {
35843          return renderer.create('<button type="button" class="note-btn btn btn-default btn-sm" role="button" tabindex="-1">', function ($node, options) {
35844              if (options && options.tooltip) {
35845                  $node.attr({
35846                      title: options.tooltip,
35847                      'aria-label': options.tooltip
35848                  }).tooltip({
35849                      container: (options.container !== undefined) ? options.container : 'body',
35850                      trigger: 'hover',
35851                      placement: 'bottom'
35852                  });
35853              }
35854          })($node, options);
35855      },
35856      toggleBtn: function ($btn, isEnable) {
35857          $btn.toggleClass('disabled', !isEnable);
35858          $btn.attr('disabled', !isEnable);
35859      },
35860      toggleBtnActive: function ($btn, isActive) {
35861          $btn.toggleClass('active', isActive);
35862      },
35863      onDialogShown: function ($dialog, handler) {
35864          $dialog.one('shown.bs.modal', handler);
35865      },
35866      onDialogHidden: function ($dialog, handler) {
35867          $dialog.one('hidden.bs.modal', handler);
35868      },
35869      showDialog: function ($dialog) {
35870          $dialog.modal('show');
35871      },
35872      hideDialog: function ($dialog) {
35873          $dialog.modal('hide');
35874      },
35875      createLayout: function ($note, options) {
35876          var $editor = (options.airMode ? ui.airEditor([
35877              ui.editingArea([
35878                  ui.airEditable()
35879              ])
35880          ]) : ui.editor([
35881              ui.toolbar(),
35882              ui.editingArea([
35883                  ui.codable(),
35884                  ui.editable()
35885              ]),
35886              ui.statusbar()
35887          ])).render();
35888          $editor.insertAfter($note);
35889          return {
35890              note: $note,
35891              editor: $editor,
35892              toolbar: $editor.find('.note-toolbar'),
35893              editingArea: $editor.find('.note-editing-area'),
35894              editable: $editor.find('.note-editable'),
35895              codable: $editor.find('.note-codable'),
35896              statusbar: $editor.find('.note-statusbar')
35897          };
35898      },
35899      removeLayout: function ($note, layoutInfo) {
35900          $note.html(layoutInfo.editable.html());
35901          layoutInfo.editor.remove();
35902          $note.show();
35903      }
35904  };
35905
35906  /**
35907   * @class core.func
35908   *
35909   * func utils (for high-order func's arg)
35910   *
35911   * @singleton
35912   * @alternateClassName func
35913   */
35914  function eq(itemA) {
35915      return function (itemB) {
35916          return itemA === itemB;
35917      };
35918  }
35919  function eq2(itemA, itemB) {
35920      return itemA === itemB;
35921  }
35922  function peq2(propName) {
35923      return function (itemA, itemB) {
35924          return itemA[propName] === itemB[propName];
35925      };
35926  }
35927  function ok() {
35928      return true;
35929  }
35930  function fail() {
35931      return false;
vendor: 4,286 bytes, lines 35932-36103
35932  }
35933  function not(f) {
35934      return function () {
35935          return !f.apply(f, arguments);
35936      };
35937  }
35938  function and(fA, fB) {
35939      return function (item) {
35940          return fA(item) && fB(item);
35941      };
35942  }
35943  function self(a) {
35944      return a;
35945  }
35946  function invoke(obj, method) {
35947      return function () {
35948          return obj[method].apply(obj, arguments);
35949      };
35950  }
35951  var idCounter = 0;
35952  /**
35953   * generate a globally-unique id
35954   *
35955   * @param {String} [prefix]
35956   */
35957  function uniqueId(prefix) {
35958      var id = ++idCounter + '';
35959      return prefix ? prefix + id : id;
35960  }
35961  /**
35962   * returns bnd (bounds) from rect
35963   *
35964   * - IE Compatibility Issue: http://goo.gl/sRLOAo
35965   * - Scroll Issue: http://goo.gl/sNjUc
35966   *
35967   * @param {Rect} rect
35968   * @return {Object} bounds
35969   * @return {Number} bounds.top
35970   * @return {Number} bounds.left
35971   * @return {Number} bounds.width
35972   * @return {Number} bounds.height
35973   */
35974  function rect2bnd(rect) {
35975      var $document = $(document);
35976      return {
35977          top: rect.top + $document.scrollTop(),
35978          left: rect.left + $document.scrollLeft(),
35979          width: rect.right - rect.left,
35980          height: rect.bottom - rect.top
35981      };
35982  }
35983  /**
35984   * returns a copy of the object where the keys have become the values and the values the keys.
35985   * @param {Object} obj
35986   * @return {Object}
35987   */
35988  function invertObject(obj) {
35989      var inverted = {};
35990      for (var key in obj) {
35991          if (obj.hasOwnProperty(key)) {
35992              inverted[obj[key]] = key;
35993          }
35994      }
35995      return inverted;
35996  }
35997  /**
35998   * @param {String} namespace
35999   * @param {String} [prefix]
36000   * @return {String}
36001   */
36002  function namespaceToCamel(namespace, prefix) {
36003      prefix = prefix || '';
36004      return prefix + namespace.split('.').map(function (name) {
36005          return name.substring(0, 1).toUpperCase() + name.substring(1);
36006      }).join('');
36007  }
36008  /**
36009   * Returns a function, that, as long as it continues to be invoked, will not
36010   * be triggered. The function will be called after it stops being called for
36011   * N milliseconds. If `immediate` is passed, trigger the function on the
36012   * leading edge, instead of the trailing.
36013   * @param {Function} func
36014   * @param {Number} wait
36015   * @param {Boolean} immediate
36016   * @return {Function}
36017   */
36018  function debounce(func, wait, immediate) {
36019      var timeout;
36020      return function () {
36021          var context = this;
36022          var args = arguments;
36023          var later = function () {
36024              timeout = null;
36025              if (!immediate) {
36026                  func.apply(context, args);
36027              }
36028          };
36029          var callNow = immediate && !timeout;
36030          clearTimeout(timeout);
36031          timeout = setTimeout(later, wait);
36032          if (callNow) {
36033              func.apply(context, args);
36034          }
36035      };
36036  }
36037  var func = {
36038      eq: eq,
36039      eq2: eq2,
36040      peq2: peq2,
36041      ok: ok,
36042      fail: fail,
36043      self: self,
36044      not: not,
36045      and: and,
36046      invoke: invoke,
36047      uniqueId: uniqueId,
36048      rect2bnd: rect2bnd,
36049      invertObject: invertObject,
36050      namespaceToCamel: namespaceToCamel,
36051      debounce: debounce
36052  };
36053
36054  /**
36055   * returns the first item of an array.
36056   *
36057   * @param {Array} array
36058   */
36059  function head(array) {
36060      return array[0];
36061  }
36062  /**
36063   * returns the last item of an array.
36064   *
36065   * @param {Array} array
36066   */
36067  function last(array) {
36068      return array[array.length - 1];
36069  }
36070  /**
36071   * returns everything but the last entry of the array.
36072   *
36073   * @param {Array} array
36074   */
36075  function initial(array) {
36076      return array.slice(0, array.length - 1);
36077  }
36078  /**
36079   * returns the rest of the items in an array.
36080   *
36081   * @param {Array} array
36082   */
36083  function tail(array) {
36084      return array.slice(1);
36085  }
36086  /**
36087   * returns item of array
36088   */
36089  function find(array, pred) {
36090      for (var idx = 0, len = array.length; idx < len; idx++) {
36091          var item = array[idx];
36092          if (pred(item)) {
36093              return item;
36094          }
36095      }
36096  }
36097  /**
36098   * returns true if all of the values in the array pass the predicate truth test.
36099   */
36100  function all(array, pred) {
36101      for (var idx = 0, len = array.length; idx < len; idx++) {
36102          if (!pred(array[idx])) {
36103              return false;
36104          }
36105      }
36106      return true;
36107  }
36108  /**
36109   * returns index of item
36110   */
36111  function indexOf(array, item) {
36112      return $$1.inArray(item, array);
36113  }
36114  /**
36115   * returns true if the value is present in the list.
36116   */
36117  function contains(array, item) {
36118      return indexOf(array, item) !== -1;
36119  }
36120  /**
36121   * get sum from a list
36122   *
36123   * @param {Array} array - array
36124   * @param {Function} fn - iterator
36125   */
36126  function sum(array, fn) {
36127      fn = fn || func.self;
36128      return array.reduce(function (memo, v) {
36129          return memo + fn(v);
36130      }, 0);
36131  }
36132  /**
36133   * returns a copy of the collection with array type.
36134   * @param {Collection} collection - collection eg) node.childNodes, ...
36135   */
36136  function from(collection) {
36137      var result = [];
36138      var length = collection.length;
36139      var idx = -1;
36140      while (++idx < length) {
36141          result[idx] = collection[idx];
36142      }
36143      return result;
36144  }
36145  /**
36146   * returns whether list is empty or not
36147   */
36148  function isEmpty(array) {
36149      return !array || !array.length;
36150  }
36151  /**
36152   * cluster elements by predicate function.
36153   *
36154   * @param {Array} array - array
36155   * @param {Function} fn - predicate function for cluster rule
36156   * @param {Array[]}
36157   */
36158  function clusterBy(array, fn) {
36159      if (!array.length) {
36160          return [];
36161      }
36162      var aTail = tail(array);
36163      return aTail.reduce(function (memo, v) {
36164          var aLast = last(memo);
36165          if (fn(last(aLast), v)) {
36166              aLast[aLast.length] = v;
36167          }
36168          else {
36169              memo[memo.length] = [v];
36170          }
36171          return memo;
36172      }, [[head(array)]]);
36173  }
36174  /**
36175   * returns a copy of the array with all false values removed
36176   *
36177   * @param {Array} array - array
36178   * @param {Function} fn - predicate function for cluster rule
36179   */
36180  function compact(array) {
36181      var aResult = [];
36182      for (var idx = 0, len = array.length; idx < len; idx++) {
36183          if (array[idx]) {
36184              aResult.push(array[idx]);
36185          }
36186      }
36187      return aResult;
36188  }
36189  /**
36190   * produces a duplicate-free version of the array
36191   *
36192   * @param {Array} array
36193   */
36194  function unique(array) {
36195      var results = [];
36196      for (var idx = 0, len = array.length; idx < len; idx++) {
36197          if (!contains(results, array[idx])) {
36198              results.push(array[idx]);
36199          }
36200      }
36201      return results;
36202  }
36203  /**
36204   * returns next item.
36205   * @param {Array} array
36206   */
36207  function next(array, item) {
36208      var idx = indexOf(array, item);
36209      if (idx === -1) {
36210          return null;
36211      }
36212      return array[idx + 1];
36213  }
36214  /**
36215   * returns prev item.
36216   * @param {Array} array
36217   */
36218  function prev(array, item) {
36219      var idx = indexOf(array, item);
36220      if (idx === -1) {
36221          return null;
36222      }
36223      return array[idx - 1];
36224  }
36225  /**
36226   * @class core.list
36227   *
36228   * list utils
36229   *
36230   * @singleton
36231   * @alternateClassName list
36232   */
36233  var lists = {
36234      head: head,
36235      last: last,
36236      initial: initial,
36237      tail: tail,
36238      prev: prev,
36239      next: next,
36240      find: find,
36241      contains: contains,
36242      all: all,
36243      sum: sum,
36244      from: from,
36245      isEmpty: isEmpty,
36246      clusterBy: clusterBy,
36247      compact: compact,
36248      unique: unique
36249  };
36250
36251  var isSupportAmd = typeof define === 'function' && define.amd; // eslint-disable-line
36252  /**
36253   * returns whether font is installed or not.
36254   *
36255   * @param {String} fontName
36256   * @return {Boolean}
36257   */
36258  function isFontInstalled(fontName) {
36259      var testFontName = fontName === 'Comic Sans MS' ? 'Courier New' : 'Comic Sans MS';
36260      var $tester = $$1('<div>').css({
36261          position: 'absolute',
36262          left: '-9999px',
36263          top: '-9999px',
36264          fontSize: '200px'
36265      }).text('mmmmmmmmmwwwwwww').appendTo(document.body);
36266      var originalWidth = $tester.css('fontFamily', testFontName).width();
36267      var width = $tester.css('fontFamily', fontName + ',' + testFontName).width();
36268      $tester.remove();
36269      return originalWidth !== width;
36270  }
36271  var userAgent = navigator.userAgent;
36272  var isMSIE = /MSIE|Trident/i.test(userAgent);
36273  var browserVersion;
36274  if (isMSIE) {
36275      var matches = /MSIE (\d+[.]\d+)/.exec(userAgent);
36276      if (matches) {
36277          browserVersion = parseFloat(matches[1]);
36278      }
36279      matches = /Trident\/.*rv:([0-9]{1,}[.0-9]{0,})/.exec(userAgent);
36280      if (matches) {
36281          browserVersion = parseFloat(matches[1]);
36282      }
36283  }
36284  var isEdge = /Edge\/\d+/.test(userAgent);
36285  var hasCodeMirror = !!window.CodeMirror;
36286  if (!hasCodeMirror && isSupportAmd) {
36287      // Webpack
36288      if (typeof __webpack_require__ === 'function') { // eslint-disable-line
36289          try {
36290              // If CodeMirror can't be resolved, `require.resolve` will throw an
36291              // exception and `hasCodeMirror` won't be set to `true`.
vendor: 32,927 bytes, lines 36292-37422
36292              require.resolve('codemirror');
36293              hasCodeMirror = true;
36294          }
36295          catch (e) {
36296              // do nothing
36297          }
36298      }
36299      else if (typeof require !== 'undefined') {
36300          // Browserify
36301          if (typeof require.resolve !== 'undefined') {
36302              try {
36303                  // If CodeMirror can't be resolved, `require.resolve` will throw an
36304                  // exception and `hasCodeMirror` won't be set to `true`.
36305                  require.resolve('codemirror');
36306                  hasCodeMirror = true;
36307              }
36308              catch (e) {
36309                  // do nothing
36310              }
36311              // Almond/Require
36312          }
36313          else if (typeof require.specified !== 'undefined') {
36314              hasCodeMirror = require.specified('codemirror');
36315          }
36316      }
36317  }
36318  var isSupportTouch = (('ontouchstart' in window) ||
36319      (navigator.MaxTouchPoints > 0) ||
36320      (navigator.msMaxTouchPoints > 0));
36321  // [workaround] IE doesn't have input events for contentEditable
36322  // - see: https://goo.gl/4bfIvA
36323  var inputEventName = (isMSIE || isEdge) ? 'DOMCharacterDataModified DOMSubtreeModified DOMNodeInserted' : 'input';
36324  /**
36325   * @class core.env
36326   *
36327   * Object which check platform and agent
36328   *
36329   * @singleton
36330   * @alternateClassName env
36331   */
36332  var env = {
36333      isMac: navigator.appVersion.indexOf('Mac') > -1,
36334      isMSIE: isMSIE,
36335      isEdge: isEdge,
36336      isFF: !isEdge && /firefox/i.test(userAgent),
36337      isPhantom: /PhantomJS/i.test(userAgent),
36338      isWebkit: !isEdge && /webkit/i.test(userAgent),
36339      isChrome: !isEdge && /chrome/i.test(userAgent),
36340      isSafari: !isEdge && /safari/i.test(userAgent),
36341      browserVersion: browserVersion,
36342      jqueryVersion: parseFloat($$1.fn.jquery),
36343      isSupportAmd: isSupportAmd,
36344      isSupportTouch: isSupportTouch,
36345      hasCodeMirror: hasCodeMirror,
36346      isFontInstalled: isFontInstalled,
36347      isW3CRangeSupport: !!document.createRange,
36348      inputEventName: inputEventName
36349  };
36350
36351  var NBSP_CHAR = String.fromCharCode(160);
36352  var ZERO_WIDTH_NBSP_CHAR = '\ufeff';
36353  /**
36354   * @method isEditable
36355   *
36356   * returns whether node is `note-editable` or not.
36357   *
36358   * @param {Node} node
36359   * @return {Boolean}
36360   */
36361  function isEditable(node) {
36362      return node && $$1(node).hasClass('note-editable');
36363  }
36364  /**
36365   * @method isControlSizing
36366   *
36367   * returns whether node is `note-control-sizing` or not.
36368   *
36369   * @param {Node} node
36370   * @return {Boolean}
36371   */
36372  function isControlSizing(node) {
36373      return node && $$1(node).hasClass('note-control-sizing');
36374  }
36375  /**
36376   * @method makePredByNodeName
36377   *
36378   * returns predicate which judge whether nodeName is same
36379   *
36380   * @param {String} nodeName
36381   * @return {Function}
36382   */
36383  function makePredByNodeName(nodeName) {
36384      nodeName = nodeName.toUpperCase();
36385      return function (node) {
36386          return node && node.nodeName.toUpperCase() === nodeName;
36387      };
36388  }
36389  /**
36390   * @method isText
36391   *
36392   *
36393   *
36394   * @param {Node} node
36395   * @return {Boolean} true if node's type is text(3)
36396   */
36397  function isText(node) {
36398      return node && node.nodeType === 3;
36399  }
36400  /**
36401   * @method isElement
36402   *
36403   *
36404   *
36405   * @param {Node} node
36406   * @return {Boolean} true if node's type is element(1)
36407   */
36408  function isElement(node) {
36409      return node && node.nodeType === 1;
36410  }
36411  /**
36412   * ex) br, col, embed, hr, img, input, ...
36413   * @see http://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements
36414   */
36415  function isVoid(node) {
36416      return node && /^BR|^IMG|^HR|^IFRAME|^BUTTON|^INPUT|^VIDEO|^EMBED/.test(node.nodeName.toUpperCase());
36417  }
36418  function isPara(node) {
36419      if (isEditable(node)) {
36420          return false;
36421      }
36422      // Chrome(v31.0), FF(v25.0.1) use DIV for paragraph
36423      return node && /^DIV|^P|^LI|^H[1-7]/.test(node.nodeName.toUpperCase());
36424  }
36425  function isHeading(node) {
36426      return node && /^H[1-7]/.test(node.nodeName.toUpperCase());
36427  }
36428  var isPre = makePredByNodeName('PRE');
36429  var isLi = makePredByNodeName('LI');
36430  function isPurePara(node) {
36431      return isPara(node) && !isLi(node);
36432  }
36433  var isTable = makePredByNodeName('TABLE');
36434  var isData = makePredByNodeName('DATA');
36435  function isInline(node) {
36436      return !isBodyContainer(node) &&
36437          !isList(node) &&
36438          !isHr(node) &&
36439          !isPara(node) &&
36440          !isTable(node) &&
36441          !isBlockquote(node) &&
36442          !isData(node);
36443  }
36444  function isList(node) {
36445      return node && /^UL|^OL/.test(node.nodeName.toUpperCase());
36446  }
36447  var isHr = makePredByNodeName('HR');
36448  function isCell(node) {
36449      return node && /^TD|^TH/.test(node.nodeName.toUpperCase());
36450  }
36451  var isBlockquote = makePredByNodeName('BLOCKQUOTE');
36452  function isBodyContainer(node) {
36453      return isCell(node) || isBlockquote(node) || isEditable(node);
36454  }
36455  var isAnchor = makePredByNodeName('A');
36456  function isParaInline(node) {
36457      return isInline(node) && !!ancestor(node, isPara);
36458  }
36459  function isBodyInline(node) {
36460      return isInline(node) && !ancestor(node, isPara);
36461  }
36462  var isBody = makePredByNodeName('BODY');
36463  /**
36464   * returns whether nodeB is closest sibling of nodeA
36465   *
36466   * @param {Node} nodeA
36467   * @param {Node} nodeB
36468   * @return {Boolean}
36469   */
36470  function isClosestSibling(nodeA, nodeB) {
36471      return nodeA.nextSibling === nodeB ||
36472          nodeA.previousSibling === nodeB;
36473  }
36474  /**
36475   * returns array of closest siblings with node
36476   *
36477   * @param {Node} node
36478   * @param {function} [pred] - predicate function
36479   * @return {Node[]}
36480   */
36481  function withClosestSiblings(node, pred) {
36482      pred = pred || func.ok;
36483      var siblings = [];
36484      if (node.previousSibling && pred(node.previousSibling)) {
36485          siblings.push(node.previousSibling);
36486      }
36487      siblings.push(node);
36488      if (node.nextSibling && pred(node.nextSibling)) {
36489          siblings.push(node.nextSibling);
36490      }
36491      return siblings;
36492  }
36493  /**
36494   * blank HTML for cursor position
36495   * - [workaround] old IE only works with &nbsp;
36496   * - [workaround] IE11 and other browser works with bogus br
36497   */
36498  var blankHTML = env.isMSIE && env.browserVersion < 11 ? '&nbsp;' : '<br>';
36499  /**
36500   * @method nodeLength
36501   *
36502   * returns #text's text size or element's childNodes size
36503   *
36504   * @param {Node} node
36505   */
36506  function nodeLength(node) {
36507      if (isText(node)) {
36508          return node.nodeValue.length;
36509      }
36510      if (node) {
36511          return node.childNodes.length;
36512      }
36513      return 0;
36514  }
36515  /**
36516   * returns whether node is empty or not.
36517   *
36518   * @param {Node} node
36519   * @return {Boolean}
36520   */
36521  function isEmpty$1(node) {
36522      var len = nodeLength(node);
36523      if (len === 0) {
36524          return true;
36525      }
36526      else if (!isText(node) && len === 1 && node.innerHTML === blankHTML) {
36527          // ex) <p><br></p>, <span><br></span>
36528          return true;
36529      }
36530      else if (lists.all(node.childNodes, isText) && node.innerHTML === '') {
36531          // ex) <p></p>, <span></span>
36532          return true;
36533      }
36534      return false;
36535  }
36536  /**
36537   * padding blankHTML if node is empty (for cursor position)
36538   */
36539  function paddingBlankHTML(node) {
36540      if (!isVoid(node) && !nodeLength(node)) {
36541          node.innerHTML = blankHTML;
36542      }
36543  }
36544  /**
36545   * find nearest ancestor predicate hit
36546   *
36547   * @param {Node} node
36548   * @param {Function} pred - predicate function
36549   */
36550  function ancestor(node, pred) {
36551      while (node) {
36552          if (pred(node)) {
36553              return node;
36554          }
36555          if (isEditable(node)) {
36556              break;
36557          }
36558          node = node.parentNode;
36559      }
36560      return null;
36561  }
36562  /**
36563   * find nearest ancestor only single child blood line and predicate hit
36564   *
36565   * @param {Node} node
36566   * @param {Function} pred - predicate function
36567   */
36568  function singleChildAncestor(node, pred) {
36569      node = node.parentNode;
36570      while (node) {
36571          if (nodeLength(node) !== 1) {
36572              break;
36573          }
36574          if (pred(node)) {
36575              return node;
36576          }
36577          if (isEditable(node)) {
36578              break;
36579          }
36580          node = node.parentNode;
36581      }
36582      return null;
36583  }
36584  /**
36585   * returns new array of ancestor nodes (until predicate hit).
36586   *
36587   * @param {Node} node
36588   * @param {Function} [optional] pred - predicate function
36589   */
36590  function listAncestor(node, pred) {
36591      pred = pred || func.fail;
36592      var ancestors = [];
36593      ancestor(node, function (el) {
36594          if (!isEditable(el)) {
36595              ancestors.push(el);
36596          }
36597          return pred(el);
36598      });
36599      return ancestors;
36600  }
36601  /**
36602   * find farthest ancestor predicate hit
36603   */
36604  function lastAncestor(node, pred) {
36605      var ancestors = listAncestor(node);
36606      return lists.last(ancestors.filter(pred));
36607  }
36608  /**
36609   * returns common ancestor node between two nodes.
36610   *
36611   * @param {Node} nodeA
36612   * @param {Node} nodeB
36613   */
36614  function commonAncestor(nodeA, nodeB) {
36615      var ancestors = listAncestor(nodeA);
36616      for (var n = nodeB; n; n = n.parentNode) {
36617          if ($$1.inArray(n, ancestors) > -1) {
36618              return n;
36619          }
36620      }
36621      return null; // difference document area
36622  }
36623  /**
36624   * listing all previous siblings (until predicate hit).
36625   *
36626   * @param {Node} node
36627   * @param {Function} [optional] pred - predicate function
36628   */
36629  function listPrev(node, pred) {
36630      pred = pred || func.fail;
36631      var nodes = [];
36632      while (node) {
36633          if (pred(node)) {
36634              break;
36635          }
36636          nodes.push(node);
36637          node = node.previousSibling;
36638      }
36639      return nodes;
36640  }
36641  /**
36642   * listing next siblings (until predicate hit).
36643   *
36644   * @param {Node} node
36645   * @param {Function} [pred] - predicate function
36646   */
36647  function listNext(node, pred) {
36648      pred = pred || func.fail;
36649      var nodes = [];
36650      while (node) {
36651          if (pred(node)) {
36652              break;
36653          }
36654          nodes.push(node);
36655          node = node.nextSibling;
36656      }
36657      return nodes;
36658  }
36659  /**
36660   * listing descendant nodes
36661   *
36662   * @param {Node} node
36663   * @param {Function} [pred] - predicate function
36664   */
36665  function listDescendant(node, pred) {
36666      var descendants = [];
36667      pred = pred || func.ok;
36668      // start DFS(depth first search) with node
36669      (function fnWalk(current) {
36670          if (node !== current && pred(current)) {
36671              descendants.push(current);
36672          }
36673          for (var idx = 0, len = current.childNodes.length; idx < len; idx++) {
36674              fnWalk(current.childNodes[idx]);
36675          }
36676      })(node);
36677      return descendants;
36678  }
36679  /**
36680   * wrap node with new tag.
36681   *
36682   * @param {Node} node
36683   * @param {Node} tagName of wrapper
36684   * @return {Node} - wrapper
36685   */
36686  function wrap(node, wrapperName) {
36687      var parent = node.parentNode;
36688      var wrapper = $$1('<' + wrapperName + '>')[0];
36689      parent.insertBefore(wrapper, node);
36690      wrapper.appendChild(node);
36691      return wrapper;
36692  }
36693  /**
36694   * insert node after preceding
36695   *
36696   * @param {Node} node
36697   * @param {Node} preceding - predicate function
36698   */
36699  function insertAfter(node, preceding) {
36700      var next = preceding.nextSibling;
36701      var parent = preceding.parentNode;
36702      if (next) {
36703          parent.insertBefore(node, next);
36704      }
36705      else {
36706          parent.appendChild(node);
36707      }
36708      return node;
36709  }
36710  /**
36711   * append elements.
36712   *
36713   * @param {Node} node
36714   * @param {Collection} aChild
36715   */
36716  function appendChildNodes(node, aChild) {
36717      $$1.each(aChild, function (idx, child) {
36718          node.appendChild(child);
36719      });
36720      return node;
36721  }
36722  /**
36723   * returns whether boundaryPoint is left edge or not.
36724   *
36725   * @param {BoundaryPoint} point
36726   * @return {Boolean}
36727   */
36728  function isLeftEdgePoint(point) {
36729      return point.offset === 0;
36730  }
36731  /**
36732   * returns whether boundaryPoint is right edge or not.
36733   *
36734   * @param {BoundaryPoint} point
36735   * @return {Boolean}
36736   */
36737  function isRightEdgePoint(point) {
36738      return point.offset === nodeLength(point.node);
36739  }
36740  /**
36741   * returns whether boundaryPoint is edge or not.
36742   *
36743   * @param {BoundaryPoint} point
36744   * @return {Boolean}
36745   */
36746  function isEdgePoint(point) {
36747      return isLeftEdgePoint(point) || isRightEdgePoint(point);
36748  }
36749  /**
36750   * returns whether node is left edge of ancestor or not.
36751   *
36752   * @param {Node} node
36753   * @param {Node} ancestor
36754   * @return {Boolean}
36755   */
36756  function isLeftEdgeOf(node, ancestor) {
36757      while (node && node !== ancestor) {
36758          if (position(node) !== 0) {
36759              return false;
36760          }
36761          node = node.parentNode;
36762      }
36763      return true;
36764  }
36765  /**
36766   * returns whether node is right edge of ancestor or not.
36767   *
36768   * @param {Node} node
36769   * @param {Node} ancestor
36770   * @return {Boolean}
36771   */
36772  function isRightEdgeOf(node, ancestor) {
36773      if (!ancestor) {
36774          return false;
36775      }
36776      while (node && node !== ancestor) {
36777          if (position(node) !== nodeLength(node.parentNode) - 1) {
36778              return false;
36779          }
36780          node = node.parentNode;
36781      }
36782      return true;
36783  }
36784  /**
36785   * returns whether point is left edge of ancestor or not.
36786   * @param {BoundaryPoint} point
36787   * @param {Node} ancestor
36788   * @return {Boolean}
36789   */
36790  function isLeftEdgePointOf(point, ancestor) {
36791      return isLeftEdgePoint(point) && isLeftEdgeOf(point.node, ancestor);
36792  }
36793  /**
36794   * returns whether point is right edge of ancestor or not.
36795   * @param {BoundaryPoint} point
36796   * @param {Node} ancestor
36797   * @return {Boolean}
36798   */
36799  function isRightEdgePointOf(point, ancestor) {
36800      return isRightEdgePoint(point) && isRightEdgeOf(point.node, ancestor);
36801  }
36802  /**
36803   * returns offset from parent.
36804   *
36805   * @param {Node} node
36806   */
36807  function position(node) {
36808      var offset = 0;
36809      while ((node = node.previousSibling)) {
36810          offset += 1;
36811      }
36812      return offset;
36813  }
36814  function hasChildren(node) {
36815      return !!(node && node.childNodes && node.childNodes.length);
36816  }
36817  /**
36818   * returns previous boundaryPoint
36819   *
36820   * @param {BoundaryPoint} point
36821   * @param {Boolean} isSkipInnerOffset
36822   * @return {BoundaryPoint}
36823   */
36824  function prevPoint(point, isSkipInnerOffset) {
36825      var node;
36826      var offset;
36827      if (point.offset === 0) {
36828          if (isEditable(point.node)) {
36829              return null;
36830          }
36831          node = point.node.parentNode;
36832          offset = position(point.node);
36833      }
36834      else if (hasChildren(point.node)) {
36835          node = point.node.childNodes[point.offset - 1];
36836          offset = nodeLength(node);
36837      }
36838      else {
36839          node = point.node;
36840          offset = isSkipInnerOffset ? 0 : point.offset - 1;
36841      }
36842      return {
36843          node: node,
36844          offset: offset
36845      };
36846  }
36847  /**
36848   * returns next boundaryPoint
36849   *
36850   * @param {BoundaryPoint} point
36851   * @param {Boolean} isSkipInnerOffset
36852   * @return {BoundaryPoint}
36853   */
36854  function nextPoint(point, isSkipInnerOffset) {
36855      var node, offset;
36856      if (nodeLength(point.node) === point.offset) {
36857          if (isEditable(point.node)) {
36858              return null;
36859          }
36860          node = point.node.parentNode;
36861          offset = position(point.node) + 1;
36862      }
36863      else if (hasChildren(point.node)) {
36864          node = point.node.childNodes[point.offset];
36865          offset = 0;
36866      }
36867      else {
36868          node = point.node;
36869          offset = isSkipInnerOffset ? nodeLength(point.node) : point.offset + 1;
36870      }
36871      return {
36872          node: node,
36873          offset: offset
36874      };
36875  }
36876  /**
36877   * returns whether pointA and pointB is same or not.
36878   *
36879   * @param {BoundaryPoint} pointA
36880   * @param {BoundaryPoint} pointB
36881   * @return {Boolean}
36882   */
36883  function isSamePoint(pointA, pointB) {
36884      return pointA.node === pointB.node && pointA.offset === pointB.offset;
36885  }
36886  /**
36887   * returns whether point is visible (can set cursor) or not.
36888   *
36889   * @param {BoundaryPoint} point
36890   * @return {Boolean}
36891   */
36892  function isVisiblePoint(point) {
36893      if (isText(point.node) || !hasChildren(point.node) || isEmpty$1(point.node)) {
36894          return true;
36895      }
36896      var leftNode = point.node.childNodes[point.offset - 1];
36897      var rightNode = point.node.childNodes[point.offset];
36898      if ((!leftNode || isVoid(leftNode)) && (!rightNode || isVoid(rightNode))) {
36899          return true;
36900      }
36901      return false;
36902  }
36903  /**
36904   * @method prevPointUtil
36905   *
36906   * @param {BoundaryPoint} point
36907   * @param {Function} pred
36908   * @return {BoundaryPoint}
36909   */
36910  function prevPointUntil(point, pred) {
36911      while (point) {
36912          if (pred(point)) {
36913              return point;
36914          }
36915          point = prevPoint(point);
36916      }
36917      return null;
36918  }
36919  /**
36920   * @method nextPointUntil
36921   *
36922   * @param {BoundaryPoint} point
36923   * @param {Function} pred
36924   * @return {BoundaryPoint}
36925   */
36926  function nextPointUntil(point, pred) {
36927      while (point) {
36928          if (pred(point)) {
36929              return point;
36930          }
36931          point = nextPoint(point);
36932      }
36933      return null;
36934  }
36935  /**
36936   * returns whether point has character or not.
36937   *
36938   * @param {Point} point
36939   * @return {Boolean}
36940   */
36941  function isCharPoint(point) {
36942      if (!isText(point.node)) {
36943          return false;
36944      }
36945      var ch = point.node.nodeValue.charAt(point.offset - 1);
36946      return ch && (ch !== ' ' && ch !== NBSP_CHAR);
36947  }
36948  /**
36949   * @method walkPoint
36950   *
36951   * @param {BoundaryPoint} startPoint
36952   * @param {BoundaryPoint} endPoint
36953   * @param {Function} handler
36954   * @param {Boolean} isSkipInnerOffset
36955   */
36956  function walkPoint(startPoint, endPoint, handler, isSkipInnerOffset) {
36957      var point = startPoint;
36958      while (point) {
36959          handler(point);
36960          if (isSamePoint(point, endPoint)) {
36961              break;
36962          }
36963          var isSkipOffset = isSkipInnerOffset &&
36964              startPoint.node !== point.node &&
36965              endPoint.node !== point.node;
36966          point = nextPoint(point, isSkipOffset);
36967      }
36968  }
36969  /**
36970   * @method makeOffsetPath
36971   *
36972   * return offsetPath(array of offset) from ancestor
36973   *
36974   * @param {Node} ancestor - ancestor node
36975   * @param {Node} node
36976   */
36977  function makeOffsetPath(ancestor, node) {
36978      var ancestors = listAncestor(node, func.eq(ancestor));
36979      return ancestors.map(position).reverse();
36980  }
36981  /**
36982   * @method fromOffsetPath
36983   *
36984   * return element from offsetPath(array of offset)
36985   *
36986   * @param {Node} ancestor - ancestor node
36987   * @param {array} offsets - offsetPath
36988   */
36989  function fromOffsetPath(ancestor, offsets) {
36990      var current = ancestor;
36991      for (var i = 0, len = offsets.length; i < len; i++) {
36992          if (current.childNodes.length <= offsets[i]) {
36993              current = current.childNodes[current.childNodes.length - 1];
36994          }
36995          else {
36996              current = current.childNodes[offsets[i]];
36997          }
36998      }
36999      return current;
37000  }
37001  /**
37002   * @method splitNode
37003   *
37004   * split element or #text
37005   *
37006   * @param {BoundaryPoint} point
37007   * @param {Object} [options]
37008   * @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false
37009   * @param {Boolean} [options.isNotSplitEdgePoint] - default: false
37010   * @param {Boolean} [options.isDiscardEmptySplits] - default: false
37011   * @return {Node} right node of boundaryPoint
37012   */
37013  function splitNode(point, options) {
37014      var isSkipPaddingBlankHTML = options && options.isSkipPaddingBlankHTML;
37015      var isNotSplitEdgePoint = options && options.isNotSplitEdgePoint;
37016      var isDiscardEmptySplits = options && options.isDiscardEmptySplits;
37017      if (isDiscardEmptySplits) {
37018          isSkipPaddingBlankHTML = true;
37019      }
37020      // edge case
37021      if (isEdgePoint(point) && (isText(point.node) || isNotSplitEdgePoint)) {
37022          if (isLeftEdgePoint(point)) {
37023              return point.node;
37024          }
37025          else if (isRightEdgePoint(point)) {
37026              return point.node.nextSibling;
37027          }
37028      }
37029      // split #text
37030      if (isText(point.node)) {
37031          return point.node.splitText(point.offset);
37032      }
37033      else {
37034          var childNode = point.node.childNodes[point.offset];
37035          var clone = insertAfter(point.node.cloneNode(false), point.node);
37036          appendChildNodes(clone, listNext(childNode));
37037          if (!isSkipPaddingBlankHTML) {
37038              paddingBlankHTML(point.node);
37039              paddingBlankHTML(clone);
37040          }
37041          if (isDiscardEmptySplits) {
37042              if (isEmpty$1(point.node)) {
37043                  remove(point.node);
37044              }
37045              if (isEmpty$1(clone)) {
37046                  remove(clone);
37047                  return point.node.nextSibling;
37048              }
37049          }
37050          return clone;
37051      }
37052  }
37053  /**
37054   * @method splitTree
37055   *
37056   * split tree by point
37057   *
37058   * @param {Node} root - split root
37059   * @param {BoundaryPoint} point
37060   * @param {Object} [options]
37061   * @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false
37062   * @param {Boolean} [options.isNotSplitEdgePoint] - default: false
37063   * @return {Node} right node of boundaryPoint
37064   */
37065  function splitTree(root, point, options) {
37066      // ex) [#text, <span>, <p>]
37067      var ancestors = listAncestor(point.node, func.eq(root));
37068      if (!ancestors.length) {
37069          return null;
37070      }
37071      else if (ancestors.length === 1) {
37072          return splitNode(point, options);
37073      }
37074      return ancestors.reduce(function (node, parent) {
37075          if (node === point.node) {
37076              node = splitNode(point, options);
37077          }
37078          return splitNode({
37079              node: parent,
37080              offset: node ? position(node) : nodeLength(parent)
37081          }, options);
37082      });
37083  }
37084  /**
37085   * split point
37086   *
37087   * @param {Point} point
37088   * @param {Boolean} isInline
37089   * @return {Object}
37090   */
37091  function splitPoint(point, isInline) {
37092      // find splitRoot, container
37093      //  - inline: splitRoot is a child of paragraph
37094      //  - block: splitRoot is a child of bodyContainer
37095      var pred = isInline ? isPara : isBodyContainer;
37096      var ancestors = listAncestor(point.node, pred);
37097      var topAncestor = lists.last(ancestors) || point.node;
37098      var splitRoot, container;
37099      if (pred(topAncestor)) {
37100          splitRoot = ancestors[ancestors.length - 2];
37101          container = topAncestor;
37102      }
37103      else {
37104          splitRoot = topAncestor;
37105          container = splitRoot.parentNode;
37106      }
37107      // if splitRoot is exists, split with splitTree
37108      var pivot = splitRoot && splitTree(splitRoot, point, {
37109          isSkipPaddingBlankHTML: isInline,
37110          isNotSplitEdgePoint: isInline
37111      });
37112      // if container is point.node, find pivot with point.offset
37113      if (!pivot && container === point.node) {
37114          pivot = point.node.childNodes[point.offset];
37115      }
37116      return {
37117          rightNode: pivot,
37118          container: container
37119      };
37120  }
37121  function create(nodeName) {
37122      return document.createElement(nodeName);
37123  }
37124  function createText(text) {
37125      return document.createTextNode(text);
37126  }
37127  /**
37128   * @method remove
37129   *
37130   * remove node, (isRemoveChild: remove child or not)
37131   *
37132   * @param {Node} node
37133   * @param {Boolean} isRemoveChild
37134   */
37135  function remove(node, isRemoveChild) {
37136      if (!node || !node.parentNode) {
37137          return;
37138      }
37139      if (node.removeNode) {
37140          return node.removeNode(isRemoveChild);
37141      }
37142      var parent = node.parentNode;
37143      if (!isRemoveChild) {
37144          var nodes = [];
37145          for (var i = 0, len = node.childNodes.length; i < len; i++) {
37146              nodes.push(node.childNodes[i]);
37147          }
37148          for (var i = 0, len = nodes.length; i < len; i++) {
37149              parent.insertBefore(nodes[i], node);
37150          }
37151      }
37152      parent.removeChild(node);
37153  }
37154  /**
37155   * @method removeWhile
37156   *
37157   * @param {Node} node
37158   * @param {Function} pred
37159   */
37160  function removeWhile(node, pred) {
37161      while (node) {
37162          if (isEditable(node) || !pred(node)) {
37163              break;
37164          }
37165          var parent = node.parentNode;
37166          remove(node);
37167          node = parent;
37168      }
37169  }
37170  /**
37171   * @method replace
37172   *
37173   * replace node with provided nodeName
37174   *
37175   * @param {Node} node
37176   * @param {String} nodeName
37177   * @return {Node} - new node
37178   */
37179  function replace(node, nodeName) {
37180      if (node.nodeName.toUpperCase() === nodeName.toUpperCase()) {
37181          return node;
37182      }
37183      var newNode = create(nodeName);
37184      if (node.style.cssText) {
37185          newNode.style.cssText = node.style.cssText;
37186      }
37187      appendChildNodes(newNode, lists.from(node.childNodes));
37188      insertAfter(newNode, node);
37189      remove(node);
37190      return newNode;
37191  }
37192  var isTextarea = makePredByNodeName('TEXTAREA');
37193  /**
37194   * @param {jQuery} $node
37195   * @param {Boolean} [stripLinebreaks] - default: false
37196   */
37197  function value($node, stripLinebreaks) {
37198      var val = isTextarea($node[0]) ? $node.val() : $node.html();
37199      if (stripLinebreaks) {
37200          return val.replace(/[\n\r]/g, '');
37201      }
37202      return val;
37203  }
37204  /**
37205   * @method html
37206   *
37207   * get the HTML contents of node
37208   *
37209   * @param {jQuery} $node
37210   * @param {Boolean} [isNewlineOnBlock]
37211   */
37212  function html($node, isNewlineOnBlock) {
37213      var markup = value($node);
37214      if (isNewlineOnBlock) {
37215          var regexTag = /<(\/?)(\b(?!!)[^>\s]*)(.*?)(\s*\/?>)/g;
37216          markup = markup.replace(regexTag, function (match, endSlash, name) {
37217              name = name.toUpperCase();
37218              var isEndOfInlineContainer = /^DIV|^TD|^TH|^P|^LI|^H[1-7]/.test(name) &&
37219                  !!endSlash;
37220              var isBlockNode = /^BLOCKQUOTE|^TABLE|^TBODY|^TR|^HR|^UL|^OL/.test(name);
37221              return match + ((isEndOfInlineContainer || isBlockNode) ? '\n' : '');
37222          });
37223          markup = $$1.trim(markup);
37224      }
37225      return markup;
37226  }
37227  function posFromPlaceholder(placeholder) {
37228      var $placeholder = $$1(placeholder);
37229      var pos = $placeholder.offset();
37230      var height = $placeholder.outerHeight(true); // include margin
37231      return {
37232          left: pos.left,
37233          top: pos.top + height
37234      };
37235  }
37236  function attachEvents($node, events) {
37237      Object.keys(events).forEach(function (key) {
37238          $node.on(key, events[key]);
37239      });
37240  }
37241  function detachEvents($node, events) {
37242      Object.keys(events).forEach(function (key) {
37243          $node.off(key, events[key]);
37244      });
37245  }
37246  /**
37247   * @method isCustomStyleTag
37248   *
37249   * assert if a node contains a "note-styletag" class,
37250   * which implies that's a custom-made style tag node
37251   *
37252   * @param {Node} an HTML DOM node
37253   */
37254  function isCustomStyleTag(node) {
37255      return node && !isText(node) && lists.contains(node.classList, 'note-styletag');
37256  }
37257  var dom = {
37258      /** @property {String} NBSP_CHAR */
37259      NBSP_CHAR: NBSP_CHAR,
37260      /** @property {String} ZERO_WIDTH_NBSP_CHAR */
37261      ZERO_WIDTH_NBSP_CHAR: ZERO_WIDTH_NBSP_CHAR,
37262      /** @property {String} blank */
37263      blank: blankHTML,
37264      /** @property {String} emptyPara */
37265      emptyPara: "<p>" + blankHTML + "</p>",
37266      makePredByNodeName: makePredByNodeName,
37267      isEditable: isEditable,
37268      isControlSizing: isControlSizing,
37269      isText: isText,
37270      isElement: isElement,
37271      isVoid: isVoid,
37272      isPara: isPara,
37273      isPurePara: isPurePara,
37274      isHeading: isHeading,
37275      isInline: isInline,
37276      isBlock: func.not(isInline),
37277      isBodyInline: isBodyInline,
37278      isBody: isBody,
37279      isParaInline: isParaInline,
37280      isPre: isPre,
37281      isList: isList,
37282      isTable: isTable,
37283      isData: isData,
37284      isCell: isCell,
37285      isBlockquote: isBlockquote,
37286      isBodyContainer: isBodyContainer,
37287      isAnchor: isAnchor,
37288      isDiv: makePredByNodeName('DIV'),
37289      isLi: isLi,
37290      isBR: makePredByNodeName('BR'),
37291      isSpan: makePredByNodeName('SPAN'),
37292      isB: makePredByNodeName('B'),
37293      isU: makePredByNodeName('U'),
37294      isS: makePredByNodeName('S'),
37295      isI: makePredByNodeName('I'),
37296      isImg: makePredByNodeName('IMG'),
37297      isTextarea: isTextarea,
37298      isEmpty: isEmpty$1,
37299      isEmptyAnchor: func.and(isAnchor, isEmpty$1),
37300      isClosestSibling: isClosestSibling,
37301      withClosestSiblings: withClosestSiblings,
37302      nodeLength: nodeLength,
37303      isLeftEdgePoint: isLeftEdgePoint,
37304      isRightEdgePoint: isRightEdgePoint,
37305      isEdgePoint: isEdgePoint,
37306      isLeftEdgeOf: isLeftEdgeOf,
37307      isRightEdgeOf: isRightEdgeOf,
37308      isLeftEdgePointOf: isLeftEdgePointOf,
37309      isRightEdgePointOf: isRightEdgePointOf,
37310      prevPoint: prevPoint,
37311      nextPoint: nextPoint,
37312      isSamePoint: isSamePoint,
37313      isVisiblePoint: isVisiblePoint,
37314      prevPointUntil: prevPointUntil,
37315      nextPointUntil: nextPointUntil,
37316      isCharPoint: isCharPoint,
37317      walkPoint: walkPoint,
37318      ancestor: ancestor,
37319      singleChildAncestor: singleChildAncestor,
37320      listAncestor: listAncestor,
37321      lastAncestor: lastAncestor,
37322      listNext: listNext,
37323      listPrev: listPrev,
37324      listDescendant: listDescendant,
37325      commonAncestor: commonAncestor,
37326      wrap: wrap,
37327      insertAfter: insertAfter,
37328      appendChildNodes: appendChildNodes,
37329      position: position,
37330      hasChildren: hasChildren,
37331      makeOffsetPath: makeOffsetPath,
37332      fromOffsetPath: fromOffsetPath,
37333      splitTree: splitTree,
37334      splitPoint: splitPoint,
37335      create: create,
37336      createText: createText,
37337      remove: remove,
37338      removeWhile: removeWhile,
37339      replace: replace,
37340      html: html,
37341      value: value,
37342      posFromPlaceholder: posFromPlaceholder,
37343      attachEvents: attachEvents,
37344      detachEvents: detachEvents,
37345      isCustomStyleTag: isCustomStyleTag
37346  };
37347
37348  /**
37349   * return boundaryPoint from TextRange, inspired by Andy Na's HuskyRange.js
37350   *
37351   * @param {TextRange} textRange
37352   * @param {Boolean} isStart
37353   * @return {BoundaryPoint}
37354   *
37355   * @see http://msdn.microsoft.com/en-us/library/ie/ms535872(v=vs.85).aspx
37356   */
37357  function textRangeToPoint(textRange, isStart) {
37358      var container = textRange.parentElement();
37359      var offset;
37360      var tester = document.body.createTextRange();
37361      var prevContainer;
37362      var childNodes = lists.from(container.childNodes);
37363      for (offset = 0; offset < childNodes.length; offset++) {
37364          if (dom.isText(childNodes[offset])) {
37365              continue;
37366          }
37367          tester.moveToElementText(childNodes[offset]);
37368          if (tester.compareEndPoints('StartToStart', textRange) >= 0) {
37369              break;
37370          }
37371          prevContainer = childNodes[offset];
37372      }
37373      if (offset !== 0 && dom.isText(childNodes[offset - 1])) {
37374          var textRangeStart = document.body.createTextRange();
37375          var curTextNode = null;
37376          textRangeStart.moveToElementText(prevContainer || container);
37377          textRangeStart.collapse(!prevContainer);
37378          curTextNode = prevContainer ? prevContainer.nextSibling : container.firstChild;
37379          var pointTester = textRange.duplicate();
37380          pointTester.setEndPoint('StartToStart', textRangeStart);
37381          var textCount = pointTester.text.replace(/[\r\n]/g, '').length;
37382          while (textCount > curTextNode.nodeValue.length && curTextNode.nextSibling) {
37383              textCount -= curTextNode.nodeValue.length;
37384              curTextNode = curTextNode.nextSibling;
37385          }
37386          // [workaround] enforce IE to re-reference curTextNode, hack
37387          var dummy = curTextNode.nodeValue; // eslint-disable-line
37388          if (isStart && curTextNode.nextSibling && dom.isText(curTextNode.nextSibling) &&
37389              textCount === curTextNode.nodeValue.length) {
37390              textCount -= curTextNode.nodeValue.length;
37391              curTextNode = curTextNode.nextSibling;
37392          }
37393          container = curTextNode;
37394          offset = textCount;
37395      }
37396      return {
37397          cont: container,
37398          offset: offset
37399      };
37400  }
37401  /**
37402   * return TextRange from boundary point (inspired by google closure-library)
37403   * @param {BoundaryPoint} point
37404   * @return {TextRange}
37405   */
37406  function pointToTextRange(point) {
37407      var textRangeInfo = function (container, offset) {
37408          var node, isCollapseToStart;
37409          if (dom.isText(container)) {
37410              var prevTextNodes = dom.listPrev(container, func.not(dom.isText));
37411              var prevContainer = lists.last(prevTextNodes).previousSibling;
37412              node = prevContainer || container.parentNode;
37413              offset += lists.sum(lists.tail(prevTextNodes), dom.nodeLength);
37414              isCollapseToStart = !prevContainer;
37415          }
37416          else {
37417              node = container.childNodes[offset] || container;
37418              if (dom.isText(node)) {
37419                  return textRangeInfo(node, 0);
37420              }
37421              offset = 0;
37422              isCollapseToStart = false;
37423          }
37424          return {
37425              node: node,
37426              collapseToStart: isCollapseToStart,
37427              offset: offset
37428          };
37429      };
37430      var textRange = document.body.createTextRange();
37431      var info = textRangeInfo(point.node, point.offset);
37432      textRange.moveToElementText(info.node);
37433      textRange.collapse(info.collapseToStart);
37434      textRange.moveStart('character', info.offset);
37435      return textRange;
37436  }
37437  /**
37438     * Wrapped Range
37439     *
37440     * @constructor
37441     * @param {Node} sc - start container
37442     * @param {Number} so - start offset
37443     * @param {Node} ec - end container
37444     * @param {Number} eo - end offset
37445     */
37446  var WrappedRange = /** @class */ (function () {
37447      function WrappedRange(sc, so, ec, eo) {
37448          this.sc = sc;
37449          this.so = so;
37450          this.ec = ec;
37451          this.eo = eo;
37452          // isOnEditable: judge whether range is on editable or not
37453          this.isOnEditable = this.makeIsOn(dom.isEditable);
37454          // isOnList: judge whether range is on list node or not
37455          this.isOnList = this.makeIsOn(dom.isList);
37456          // isOnAnchor: judge whether range is on anchor node or not
37457          this.isOnAnchor = this.makeIsOn(dom.isAnchor);
37458          // isOnCell: judge whether range is on cell node or not
37459          this.isOnCell = this.makeIsOn(dom.isCell);
37460          // isOnData: judge whether range is on data node or not
37461          this.isOnData = this.makeIsOn(dom.isData);
37462      }
37463      // nativeRange: get nativeRange from sc, so, ec, eo
37464      WrappedRange.prototype.nativeRange = function () {
37465          if (env.isW3CRangeSupport) {
37466              var w3cRange = document.createRange();
37467              w3cRange.setStart(this.sc, this.so);
37468              w3cRange.setEnd(this.ec, this.eo);
37469              return w3cRange;
37470          }
37471          else {
37472              var textRange = pointToTextRange({
37473                  node: this.sc,
37474                  offset: this.so
37475              });
37476              textRange.setEndPoint('EndToEnd', pointToTextRange({
37477                  node: this.ec,
37478                  offset: this.eo
37479              }));
37480              return textRange;
37481          }
37482      };
37483      WrappedRange.prototype.getPoints = function () {
37484          return {
37485              sc: this.sc,
37486              so: this.so,
37487              ec: this.ec,
37488              eo: this.eo
37489          };
37490      };
37491      WrappedRange.prototype.getStartPoint = function () {
37492          return {
37493              node: this.sc,
37494              offset: this.so
37495          };
37496      };
37497      WrappedRange.prototype.getEndPoint = function () {
37498          return {
37499              node: this.ec,
37500              offset: this.eo
37501          };
37502      };
37503      /**
37504       * select update visible range
37505       */
37506      WrappedRange.prototype.select = function () {
37507          var nativeRng = this.nativeRange();
37508          if (env.isW3CRangeSupport) {
37509              var selection = document.getSelection();
37510              if (selection.rangeCount > 0) {
37511                  selection.removeAllRanges();
37512              }
37513              selection.addRange(nativeRng);
37514          }
37515          else {
37516              nativeRng.select();
37517          }
37518          return this;
37519      };
37520      /**
37521       * Moves the scrollbar to start container(sc) of current range
37522       *
37523       * @return {WrappedRange}
37524       */
37525      WrappedRange.prototype.scrollIntoView = function (container) {
37526          var height = $$1(container).height();
37527          if (container.scrollTop + height < this.sc.offsetTop) {
37528              container.scrollTop += Math.abs(container.scrollTop + height - this.sc.offsetTop);
37529          }
37530          return this;
37531      };
37532      /**
37533       * @return {WrappedRange}
37534       */
37535      WrappedRange.prototype.normalize = function () {
37536          /**
37537           * @param {BoundaryPoint} point
37538           * @param {Boolean} isLeftToRight
37539           * @return {BoundaryPoint}
37540           */
37541          var getVisiblePoint = function (point, isLeftToRight) {
37542              if ((dom.isVisiblePoint(point) && !dom.isEdgePoint(point)) ||
37543                  (dom.isVisiblePoint(point) && dom.isRightEdgePoint(point) && !isLeftToRight) ||
37544                  (dom.isVisiblePoint(point) && dom.isLeftEdgePoint(point) && isLeftToRight) ||
37545                  (dom.isVisiblePoint(point) && dom.isBlock(point.node) && dom.isEmpty(point.node))) {
37546                  return point;
37547              }
37548              // point on block's edge
37549              var block = dom.ancestor(point.node, dom.isBlock);
37550              if (((dom.isLeftEdgePointOf(point, block) || dom.isVoid(dom.prevPoint(point).node)) && !isLeftToRight) ||
37551                  ((dom.isRightEdgePointOf(point, block) || dom.isVoid(dom.nextPoint(point).node)) && isLeftToRight)) {
37552                  // returns point already on visible point
37553                  if (dom.isVisiblePoint(point)) {
37554                      return point;
37555                  }
37556                  // reverse direction
37557                  isLeftToRight = !isLeftToRight;
37558              }
37559              var nextPoint = isLeftToRight ? dom.nextPointUntil(dom.nextPoint(point), dom.isVisiblePoint)
37560                  : dom.prevPointUntil(dom.prevPoint(point), dom.isVisiblePoint);
37561              return nextPoint || point;
37562          };
37563          var endPoint = getVisiblePoint(this.getEndPoint(), false);
37564          var startPoint = this.isCollapsed() ? endPoint : getVisiblePoint(this.getStartPoint(), true);
37565          return new WrappedRange(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset);
37566      };
37567      /**
37568       * returns matched nodes on range
37569       *
37570       * @param {Function} [pred] - predicate function
37571       * @param {Object} [options]
37572       * @param {Boolean} [options.includeAncestor]
37573       * @param {Boolean} [options.fullyContains]
37574       * @return {Node[]}
37575       */
37576      WrappedRange.prototype.nodes = function (pred, options) {
37577          pred = pred || func.ok;
37578          var includeAncestor = options && options.includeAncestor;
37579          var fullyContains = options && options.fullyContains;
vendor: 16,462 bytes, lines 37580-38043
37580          // TODO compare points and sort
37581          var startPoint = this.getStartPoint();
37582          var endPoint = this.getEndPoint();
37583          var nodes = [];
37584          var leftEdgeNodes = [];
37585          dom.walkPoint(startPoint, endPoint, function (point) {
37586              if (dom.isEditable(point.node)) {
37587                  return;
37588              }
37589              var node;
37590              if (fullyContains) {
37591                  if (dom.isLeftEdgePoint(point)) {
37592                      leftEdgeNodes.push(point.node);
37593                  }
37594                  if (dom.isRightEdgePoint(point) && lists.contains(leftEdgeNodes, point.node)) {
37595                      node = point.node;
37596                  }
37597              }
37598              else if (includeAncestor) {
37599                  node = dom.ancestor(point.node, pred);
37600              }
37601              else {
37602                  node = point.node;
37603              }
37604              if (node && pred(node)) {
37605                  nodes.push(node);
37606              }
37607          }, true);
37608          return lists.unique(nodes);
37609      };
37610      /**
37611       * returns commonAncestor of range
37612       * @return {Element} - commonAncestor
37613       */
37614      WrappedRange.prototype.commonAncestor = function () {
37615          return dom.commonAncestor(this.sc, this.ec);
37616      };
37617      /**
37618       * returns expanded range by pred
37619       *
37620       * @param {Function} pred - predicate function
37621       * @return {WrappedRange}
37622       */
37623      WrappedRange.prototype.expand = function (pred) {
37624          var startAncestor = dom.ancestor(this.sc, pred);
37625          var endAncestor = dom.ancestor(this.ec, pred);
37626          if (!startAncestor && !endAncestor) {
37627              return new WrappedRange(this.sc, this.so, this.ec, this.eo);
37628          }
37629          var boundaryPoints = this.getPoints();
37630          if (startAncestor) {
37631              boundaryPoints.sc = startAncestor;
37632              boundaryPoints.so = 0;
37633          }
37634          if (endAncestor) {
37635              boundaryPoints.ec = endAncestor;
37636              boundaryPoints.eo = dom.nodeLength(endAncestor);
37637          }
37638          return new WrappedRange(boundaryPoints.sc, boundaryPoints.so, boundaryPoints.ec, boundaryPoints.eo);
37639      };
37640      /**
37641       * @param {Boolean} isCollapseToStart
37642       * @return {WrappedRange}
37643       */
37644      WrappedRange.prototype.collapse = function (isCollapseToStart) {
37645          if (isCollapseToStart) {
37646              return new WrappedRange(this.sc, this.so, this.sc, this.so);
37647          }
37648          else {
37649              return new WrappedRange(this.ec, this.eo, this.ec, this.eo);
37650          }
37651      };
37652      /**
37653       * splitText on range
37654       */
37655      WrappedRange.prototype.splitText = function () {
37656          var isSameContainer = this.sc === this.ec;
37657          var boundaryPoints = this.getPoints();
37658          if (dom.isText(this.ec) && !dom.isEdgePoint(this.getEndPoint())) {
37659              this.ec.splitText(this.eo);
37660          }
37661          if (dom.isText(this.sc) && !dom.isEdgePoint(this.getStartPoint())) {
37662              boundaryPoints.sc = this.sc.splitText(this.so);
37663              boundaryPoints.so = 0;
37664              if (isSameContainer) {
37665                  boundaryPoints.ec = boundaryPoints.sc;
37666                  boundaryPoints.eo = this.eo - this.so;
37667              }
37668          }
37669          return new WrappedRange(boundaryPoints.sc, boundaryPoints.so, boundaryPoints.ec, boundaryPoints.eo);
37670      };
37671      /**
37672       * delete contents on range
37673       * @return {WrappedRange}
37674       */
37675      WrappedRange.prototype.deleteContents = function () {
37676          if (this.isCollapsed()) {
37677              return this;
37678          }
37679          var rng = this.splitText();
37680          var nodes = rng.nodes(null, {
37681              fullyContains: true
37682          });
37683          // find new cursor point
37684          var point = dom.prevPointUntil(rng.getStartPoint(), function (point) {
37685              return !lists.contains(nodes, point.node);
37686          });
37687          var emptyParents = [];
37688          $$1.each(nodes, function (idx, node) {
37689              // find empty parents
37690              var parent = node.parentNode;
37691              if (point.node !== parent && dom.nodeLength(parent) === 1) {
37692                  emptyParents.push(parent);
37693              }
37694              dom.remove(node, false);
37695          });
37696          // remove empty parents
37697          $$1.each(emptyParents, function (idx, node) {
37698              dom.remove(node, false);
37699          });
37700          return new WrappedRange(point.node, point.offset, point.node, point.offset).normalize();
37701      };
37702      /**
37703       * makeIsOn: return isOn(pred) function
37704       */
37705      WrappedRange.prototype.makeIsOn = function (pred) {
37706          return function () {
37707              var ancestor = dom.ancestor(this.sc, pred);
37708              return !!ancestor && (ancestor === dom.ancestor(this.ec, pred));
37709          };
37710      };
37711      /**
37712       * @param {Function} pred
37713       * @return {Boolean}
37714       */
37715      WrappedRange.prototype.isLeftEdgeOf = function (pred) {
37716          if (!dom.isLeftEdgePoint(this.getStartPoint())) {
37717              return false;
37718          }
37719          var node = dom.ancestor(this.sc, pred);
37720          return node && dom.isLeftEdgeOf(this.sc, node);
37721      };
37722      /**
37723       * returns whether range was collapsed or not
37724       */
37725      WrappedRange.prototype.isCollapsed = function () {
37726          return this.sc === this.ec && this.so === this.eo;
37727      };
37728      /**
37729       * wrap inline nodes which children of body with paragraph
37730       *
37731       * @return {WrappedRange}
37732       */
37733      WrappedRange.prototype.wrapBodyInlineWithPara = function () {
37734          if (dom.isBodyContainer(this.sc) && dom.isEmpty(this.sc)) {
37735              this.sc.innerHTML = dom.emptyPara;
37736              return new WrappedRange(this.sc.firstChild, 0, this.sc.firstChild, 0);
37737          }
37738          /**
37739           * [workaround] firefox often create range on not visible point. so normalize here.
37740           *  - firefox: |<p>text</p>|
37741           *  - chrome: <p>|text|</p>
37742           */
37743          var rng = this.normalize();
37744          if (dom.isParaInline(this.sc) || dom.isPara(this.sc)) {
37745              return rng;
37746          }
37747          // find inline top ancestor
37748          var topAncestor;
37749          if (dom.isInline(rng.sc)) {
37750              var ancestors = dom.listAncestor(rng.sc, func.not(dom.isInline));
37751              topAncestor = lists.last(ancestors);
37752              if (!dom.isInline(topAncestor)) {
37753                  topAncestor = ancestors[ancestors.length - 2] || rng.sc.childNodes[rng.so];
37754              }
37755          }
37756          else {
37757              topAncestor = rng.sc.childNodes[rng.so > 0 ? rng.so - 1 : 0];
37758          }
37759          // siblings not in paragraph
37760          var inlineSiblings = dom.listPrev(topAncestor, dom.isParaInline).reverse();
37761          inlineSiblings = inlineSiblings.concat(dom.listNext(topAncestor.nextSibling, dom.isParaInline));
37762          // wrap with paragraph
37763          if (inlineSiblings.length) {
37764              var para = dom.wrap(lists.head(inlineSiblings), 'p');
37765              dom.appendChildNodes(para, lists.tail(inlineSiblings));
37766          }
37767          return this.normalize();
37768      };
37769      /**
37770       * insert node at current cursor
37771       *
37772       * @param {Node} node
37773       * @return {Node}
37774       */
37775      WrappedRange.prototype.insertNode = function (node) {
37776          var rng = this.wrapBodyInlineWithPara().deleteContents();
37777          var info = dom.splitPoint(rng.getStartPoint(), dom.isInline(node));
37778          if (info.rightNode) {
37779              info.rightNode.parentNode.insertBefore(node, info.rightNode);
37780          }
37781          else {
37782              info.container.appendChild(node);
37783          }
37784          return node;
37785      };
37786      /**
37787       * insert html at current cursor
37788       */
37789      WrappedRange.prototype.pasteHTML = function (markup) {
37790          var contentsContainer = $$1('<div></div>').html(markup)[0];
37791          var childNodes = lists.from(contentsContainer.childNodes);
37792          var rng = this.wrapBodyInlineWithPara().deleteContents();
37793          if (rng.so > 0) {
37794              childNodes = childNodes.reverse();
37795          }
37796          childNodes = childNodes.map(function (childNode) {
37797              return rng.insertNode(childNode);
37798          });
37799          if (rng.so > 0) {
37800              childNodes = childNodes.reverse();
37801          }
37802          return childNodes;
37803      };
37804      /**
37805       * returns text in range
37806       *
37807       * @return {String}
37808       */
37809      WrappedRange.prototype.toString = function () {
37810          var nativeRng = this.nativeRange();
37811          return env.isW3CRangeSupport ? nativeRng.toString() : nativeRng.text;
37812      };
37813      /**
37814       * returns range for word before cursor
37815       *
37816       * @param {Boolean} [findAfter] - find after cursor, default: false
37817       * @return {WrappedRange}
37818       */
37819      WrappedRange.prototype.getWordRange = function (findAfter) {
37820          var endPoint = this.getEndPoint();
37821          if (!dom.isCharPoint(endPoint)) {
37822              return this;
37823          }
37824          var startPoint = dom.prevPointUntil(endPoint, function (point) {
37825              return !dom.isCharPoint(point);
37826          });
37827          if (findAfter) {
37828              endPoint = dom.nextPointUntil(endPoint, function (point) {
37829                  return !dom.isCharPoint(point);
37830              });
37831          }
37832          return new WrappedRange(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset);
37833      };
37834      /**
37835       * create offsetPath bookmark
37836       *
37837       * @param {Node} editable
37838       */
37839      WrappedRange.prototype.bookmark = function (editable) {
37840          return {
37841              s: {
37842                  path: dom.makeOffsetPath(editable, this.sc),
37843                  offset: this.so
37844              },
37845              e: {
37846                  path: dom.makeOffsetPath(editable, this.ec),
37847                  offset: this.eo
37848              }
37849          };
37850      };
37851      /**
37852       * create offsetPath bookmark base on paragraph
37853       *
37854       * @param {Node[]} paras
37855       */
37856      WrappedRange.prototype.paraBookmark = function (paras) {
37857          return {
37858              s: {
37859                  path: lists.tail(dom.makeOffsetPath(lists.head(paras), this.sc)),
37860                  offset: this.so
37861              },
37862              e: {
37863                  path: lists.tail(dom.makeOffsetPath(lists.last(paras), this.ec)),
37864                  offset: this.eo
37865              }
37866          };
37867      };
37868      /**
37869       * getClientRects
37870       * @return {Rect[]}
37871       */
37872      WrappedRange.prototype.getClientRects = function () {
37873          var nativeRng = this.nativeRange();
37874          return nativeRng.getClientRects();
37875      };
37876      return WrappedRange;
37877  }());
37878  /**
37879   * Data structure
37880   *  * BoundaryPoint: a point of dom tree
37881   *  * BoundaryPoints: two boundaryPoints corresponding to the start and the end of the Range
37882   *
37883   * See to http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Position
37884   */
37885  var range = {
37886      /**
37887       * create Range Object From arguments or Browser Selection
37888       *
37889       * @param {Node} sc - start container
37890       * @param {Number} so - start offset
37891       * @param {Node} ec - end container
37892       * @param {Number} eo - end offset
37893       * @return {WrappedRange}
37894       */
37895      create: function (sc, so, ec, eo) {
37896          if (arguments.length === 4) {
37897              return new WrappedRange(sc, so, ec, eo);
37898          }
37899          else if (arguments.length === 2) { // collapsed
37900              ec = sc;
37901              eo = so;
37902              return new WrappedRange(sc, so, ec, eo);
37903          }
37904          else {
37905              var wrappedRange = this.createFromSelection();
37906              if (!wrappedRange && arguments.length === 1) {
37907                  wrappedRange = this.createFromNode(arguments[0]);
37908                  return wrappedRange.collapse(dom.emptyPara === arguments[0].innerHTML);
37909              }
37910              return wrappedRange;
37911          }
37912      },
37913      createFromSelection: function () {
37914          var sc, so, ec, eo;
37915          if (env.isW3CRangeSupport) {
37916              var selection = document.getSelection();
37917              if (!selection || selection.rangeCount === 0) {
37918                  return null;
37919              }
37920              else if (dom.isBody(selection.anchorNode)) {
37921                  // Firefox: returns entire body as range on initialization.
37922                  // We won't never need it.
37923                  return null;
37924              }
37925              var nativeRng = selection.getRangeAt(0);
37926              sc = nativeRng.startContainer;
37927              so = nativeRng.startOffset;
37928              ec = nativeRng.endContainer;
37929              eo = nativeRng.endOffset;
37930          }
37931          else { // IE8: TextRange
37932              var textRange = document.selection.createRange();
37933              var textRangeEnd = textRange.duplicate();
37934              textRangeEnd.collapse(false);
37935              var textRangeStart = textRange;
37936              textRangeStart.collapse(true);
37937              var startPoint = textRangeToPoint(textRangeStart, true);
37938              var endPoint = textRangeToPoint(textRangeEnd, false);
37939              // same visible point case: range was collapsed.
37940              if (dom.isText(startPoint.node) && dom.isLeftEdgePoint(startPoint) &&
37941                  dom.isTextNode(endPoint.node) && dom.isRightEdgePoint(endPoint) &&
37942                  endPoint.node.nextSibling === startPoint.node) {
37943                  startPoint = endPoint;
37944              }
37945              sc = startPoint.cont;
37946              so = startPoint.offset;
37947              ec = endPoint.cont;
37948              eo = endPoint.offset;
37949          }
37950          return new WrappedRange(sc, so, ec, eo);
37951      },
37952      /**
37953       * @method
37954       *
37955       * create WrappedRange from node
37956       *
37957       * @param {Node} node
37958       * @return {WrappedRange}
37959       */
37960      createFromNode: function (node) {
37961          var sc = node;
37962          var so = 0;
37963          var ec = node;
37964          var eo = dom.nodeLength(ec);
37965          // browsers can't target a picture or void node
37966          if (dom.isVoid(sc)) {
37967              so = dom.listPrev(sc).length - 1;
37968              sc = sc.parentNode;
37969          }
37970          if (dom.isBR(ec)) {
37971              eo = dom.listPrev(ec).length - 1;
37972              ec = ec.parentNode;
37973          }
37974          else if (dom.isVoid(ec)) {
37975              eo = dom.listPrev(ec).length;
37976              ec = ec.parentNode;
37977          }
37978          return this.create(sc, so, ec, eo);
37979      },
37980      /**
37981       * create WrappedRange from node after position
37982       *
37983       * @param {Node} node
37984       * @return {WrappedRange}
37985       */
37986      createFromNodeBefore: function (node) {
37987          return this.createFromNode(node).collapse(true);
37988      },
37989      /**
37990       * create WrappedRange from node after position
37991       *
37992       * @param {Node} node
37993       * @return {WrappedRange}
37994       */
37995      createFromNodeAfter: function (node) {
37996          return this.createFromNode(node).collapse();
37997      },
37998      /**
37999       * @method
38000       *
38001       * create WrappedRange from bookmark
38002       *
38003       * @param {Node} editable
38004       * @param {Object} bookmark
38005       * @return {WrappedRange}
38006       */
38007      createFromBookmark: function (editable, bookmark) {
38008          var sc = dom.fromOffsetPath(editable, bookmark.s.path);
38009          var so = bookmark.s.offset;
38010          var ec = dom.fromOffsetPath(editable, bookmark.e.path);
38011          var eo = bookmark.e.offset;
38012          return new WrappedRange(sc, so, ec, eo);
38013      },
38014      /**
38015       * @method
38016       *
38017       * create WrappedRange from paraBookmark
38018       *
38019       * @param {Object} bookmark
38020       * @param {Node[]} paras
38021       * @return {WrappedRange}
38022       */
38023      createFromParaBookmark: function (bookmark, paras) {
38024          var so = bookmark.s.offset;
38025          var eo = bookmark.e.offset;
38026          var sc = dom.fromOffsetPath(lists.head(paras), bookmark.s.path);
38027          var ec = dom.fromOffsetPath(lists.last(paras), bookmark.e.path);
38028          return new WrappedRange(sc, so, ec, eo);
38029      }
38030  };
38031
38032  $$1.summernote = $$1.summernote || {
38033      lang: {}
38034  };
38035  $$1.extend($$1.summernote.lang, {
38036      'en-US': {
38037          font: {
38038              bold: 'Bold',
38039              italic: 'Italic',
38040              underline: 'Underline',
38041              clear: 'Remove Font Style',
38042              height: 'Line Height',
38043              name: 'Font Family',
38044              strikethrough: 'Strikethrough',
38045              subscript: 'Subscript',
38046              superscript: 'Superscript',
38047              size: 'Font Size'
38048          },
38049          image: {
38050              image: 'Picture',
38051              insert: 'Insert Image',
38052              resizeFull: 'Resize Full',
38053              resizeHalf: 'Resize Half',
38054              resizeQuarter: 'Resize Quarter',
38055              floatLeft: 'Float Left',
38056              floatRight: 'Float Right',
38057              floatNone: 'Float None',
38058              shapeRounded: 'Shape: Rounded',
38059              shapeCircle: 'Shape: Circle',
38060              shapeThumbnail: 'Shape: Thumbnail',
38061              shapeNone: 'Shape: None',
38062              dragImageHere: 'Drag image or text here',
38063              dropImage: 'Drop image or Text',
38064              selectFromFiles: 'Select from files',
38065              maximumFileSize: 'Maximum file size',
38066              maximumFileSizeError: 'Maximum file size exceeded.',
38067              url: 'Image URL',
38068              remove: 'Remove Image',
38069              original: 'Original'
38070          },
38071          video: {
38072              video: 'Video',
38073              videoLink: 'Video Link',
38074              insert: 'Insert Video',
38075              url: 'Video URL',
38076              providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion or Youku)'
38077          },
38078          link: {
38079              link: 'Link',
38080              insert: 'Insert Link',
38081              unlink: 'Unlink',
38082              edit: 'Edit',
38083              textToDisplay: 'Text to display',
38084              url: 'To what URL should this link go?',
38085              openInNewWindow: 'Open in new window'
38086          },
38087          table: {
38088              table: 'Table',
38089              addRowAbove: 'Add row above',
38090              addRowBelow: 'Add row below',
38091              addColLeft: 'Add column left',
38092              addColRight: 'Add column right',
38093              delRow: 'Delete row',
38094              delCol: 'Delete column',
38095              delTable: 'Delete table'
38096          },
38097          hr: {
38098              insert: 'Insert Horizontal Rule'
38099          },
38100          style: {
38101              style: 'Style',
38102              p: 'Normal',
38103              blockquote: 'Quote',
38104              pre: 'Code',
38105              h1: 'Header 1',
38106              h2: 'Header 2',
38107              h3: 'Header 3',
38108              h4: 'Header 4',
38109              h5: 'Header 5',
38110              h6: 'Header 6'
38111          },
38112          lists: {
38113              unordered: 'Unordered list',
38114              ordered: 'Ordered list'
38115          },
38116          options: {
38117              help: 'Help',
38118              fullscreen: 'Full Screen',
38119              codeview: 'Code View'
38120          },
38121          paragraph: {
38122              paragraph: 'Paragraph',
38123              outdent: 'Outdent',
38124              indent: 'Indent',
38125              left: 'Align left',
38126              center: 'Align center',
38127              right: 'Align right',
38128              justify: 'Justify full'
38129          },
38130          color: {
38131              recent: 'Recent Color',
38132              more: 'More Color',
38133              background: 'Background Color',
38134              foreground: 'Foreground Color',
38135              transparent: 'Transparent',
38136              setTransparent: 'Set transparent',
38137              reset: 'Reset',
38138              resetToDefault: 'Reset to default',
38139              cpSelect: 'Select'
38140          },
38141          shortcut: {
38142              shortcuts: 'Keyboard shortcuts',
38143              close: 'Close',
38144              textFormatting: 'Text formatting',
38145              action: 'Action',
38146              paragraphFormatting: 'Paragraph formatting',
38147              documentStyle: 'Document Style',
38148              extraKeys: 'Extra keys'
38149          },
38150          help: {
38151              'insertParagraph': 'Insert Paragraph',
38152              'undo': 'Undoes the last command',
38153              'redo': 'Redoes the last command',
38154              'tab': 'Tab',
38155              'untab': 'Untab',
38156              'bold': 'Set a bold style',
38157              'italic': 'Set a italic style',
38158              'underline': 'Set a underline style',
38159              'strikethrough': 'Set a strikethrough style',
38160              'removeFormat': 'Clean a style',
38161              'justifyLeft': 'Set left align',
38162              'justifyCenter': 'Set center align',
38163              'justifyRight': 'Set right align',
38164              'justifyFull': 'Set full align',
38165              'insertUnorderedList': 'Toggle unordered list',
38166              'insertOrderedList': 'Toggle ordered list',
38167              'outdent': 'Outdent on current paragraph',
38168              'indent': 'Indent on current paragraph',
38169              'formatPara': 'Change current block\'s format as a paragraph(P tag)',
38170              'formatH1': 'Change current block\'s format as H1',
38171              'formatH2': 'Change current block\'s format as H2',
38172              'formatH3': 'Change current block\'s format as H3',
38173              'formatH4': 'Change current block\'s format as H4',
38174              'formatH5': 'Change current block\'s format as H5',
38175              'formatH6': 'Change current block\'s format as H6',
38176              'insertHorizontalRule': 'Insert horizontal rule',
38177              'linkDialog.show': 'Show Link Dialog'
38178          },
38179          history: {
38180              undo: 'Undo',
38181              redo: 'Redo'
38182          },
38183          specialChar: {
38184              specialChar: 'SPECIAL CHARACTERS',
38185              select: 'Select Special characters'
38186          }
38187      }
38188  });
38189
38190  var KEY_MAP = {
38191      'BACKSPACE': 8,
38192      'TAB': 9,
38193      'ENTER': 13,
38194      'SPACE': 32,
38195      'DELETE': 46,
38196      // Arrow
38197      'LEFT': 37,
38198      'UP': 38,
38199      'RIGHT': 39,
38200      'DOWN': 40,
38201      // Number: 0-9
38202      'NUM0': 48,
38203      'NUM1': 49,
38204      'NUM2': 50,
38205      'NUM3': 51,
38206      'NUM4': 52,
38207      'NUM5': 53,
38208      'NUM6': 54,
38209      'NUM7': 55,
38210      'NUM8': 56,
38211      // Alphabet: a-z
38212      'B': 66,
38213      'E': 69,
38214      'I': 73,
38215      'J': 74,
38216      'K': 75,
38217      'L': 76,
38218      'R': 82,
38219      'S': 83,
38220      'U': 85,
38221      'V': 86,
38222      'Y': 89,
38223      'Z': 90,
38224      'SLASH': 191,
38225      'LEFTBRACKET': 219,
38226      'BACKSLASH': 220,
38227      'RIGHTBRACKET': 221
38228  };
38229  /**
38230   * @class core.key
38231   *
38232   * Object for keycodes.
38233   *
38234   * @singleton
38235   * @alternateClassName key
38236   */
38237  var key = {
38238      /**
38239       * @method isEdit
38240       *
38241       * @param {Number} keyCode
38242       * @return {Boolean}
38243       */
38244      isEdit: function (keyCode) {
38245          return lists.contains([
38246              KEY_MAP.BACKSPACE,
38247              KEY_MAP.TAB,
38248              KEY_MAP.ENTER,
38249              KEY_MAP.SPACE,
38250              KEY_MAP.DELETE
38251          ], keyCode);
38252      },
38253      /**
38254       * @method isMove
38255       *
38256       * @param {Number} keyCode
38257       * @return {Boolean}
38258       */
38259      isMove: function (keyCode) {
38260          return lists.contains([
38261              KEY_MAP.LEFT,
38262              KEY_MAP.UP,
38263              KEY_MAP.RIGHT,
38264              KEY_MAP.DOWN
38265          ], keyCode);
38266      },
38267      /**
38268       * @property {Object} nameFromCode
38269       * @property {String} nameFromCode.8 "BACKSPACE"
38270       */
38271      nameFromCode: func.invertObject(KEY_MAP),
38272      code: KEY_MAP
38273  };
38274
38275  /**
38276   * @method readFileAsDataURL
38277   *
38278   * read contents of file as representing URL
38279   *
38280   * @param {File} file
38281   * @return {Promise} - then: dataUrl
38282   */
38283  function readFileAsDataURL(file) {
38284      return $$1.Deferred(function (deferred) {
38285          $$1.extend(new FileReader(), {
38286              onload: function (e) {
38287                  var dataURL = e.target.result;
38288                  deferred.resolve(dataURL);
38289              },
38290              onerror: function (err) {
38291                  deferred.reject(err);
38292              }
38293          }).readAsDataURL(file);
38294      }).promise();
38295  }
38296  /**
38297   * @method createImage
38298   *
38299   * create `<image>` from url string
38300   *
38301   * @param {String} url
38302   * @return {Promise} - then: $image
38303   */
38304  function createImage(url) {
38305      return $$1.Deferred(function (deferred) {
38306          var $img = $$1('<img>');
38307          $img.one('load', function () {
38308              $img.off('error abort');
38309              deferred.resolve($img);
38310          }).one('error abort', function () {
38311              $img.off('load').detach();
38312              deferred.reject($img);
38313          }).css({
38314              display: 'none'
38315          }).appendTo(document.body).attr('src', url);
38316      }).promise();
38317  }
38318
38319  var History = /** @class */ (function () {
38320      function History($editable) {
38321          this.stack = [];
38322          this.stackOffset = -1;
38323          this.$editable = $editable;
38324          this.editable = $editable[0];
38325      }
38326      History.prototype.makeSnapshot = function () {
38327          var rng = range.create(this.editable);
38328          var emptyBookmark = { s: { path: [], offset: 0 }, e: { path: [], offset: 0 } };
38329          return {
38330              contents: this.$editable.html(),
38331              bookmark: (rng ? rng.bookmark(this.editable) : emptyBookmark)
38332          };
38333      };
38334      History.prototype.applySnapshot = function (snapshot) {
38335          if (snapshot.contents !== null) {
38336              this.$editable.html(snapshot.contents);
38337          }
38338          if (snapshot.bookmark !== null) {
38339              range.createFromBookmark(this.editable, snapshot.bookmark).select();
38340          }
38341      };
38342      /**
38343      * @method rewind
38344      * Rewinds the history stack back to the first snapshot taken.
38345      * Leaves the stack intact, so that "Redo" can still be used.
38346      */
38347      History.prototype.rewind = function () {
38348          // Create snap shot if not yet recorded
38349          if (this.$editable.html() !== this.stack[this.stackOffset].contents) {
38350              this.recordUndo();
38351          }
38352          // Return to the first available snapshot.
38353          this.stackOffset = 0;
38354          // Apply that snapshot.
38355          this.applySnapshot(this.stack[this.stackOffset]);
38356      };
38357      /**
38358      *  @method commit
38359      *  Resets history stack, but keeps current editor's content.
38360      */
38361      History.prototype.commit = function () {
38362          // Clear the stack.
38363          this.stack = [];
38364          // Restore stackOffset to its original value.
38365          this.stackOffset = -1;
38366          // Record our first snapshot (of nothing).
38367          this.recordUndo();
38368      };
38369      /**
38370      * @method reset
38371      * Resets the history stack completely; reverting to an empty editor.
38372      */
38373      History.prototype.reset = function () {
38374          // Clear the stack.
38375          this.stack = [];
38376          // Restore stackOffset to its original value.
38377          this.stackOffset = -1;
38378          // Clear the editable area.
38379          this.$editable.html('');
38380          // Record our first snapshot (of nothing).
38381          this.recordUndo();
38382      };
38383      /**
38384       * undo
38385       */
38386      History.prototype.undo = function () {
38387          // Create snap shot if not yet recorded
38388          if (this.$editable.html() !== this.stack[this.stackOffset].contents) {
38389              this.recordUndo();
38390          }
38391          if (this.stackOffset > 0) {
38392              this.stackOffset--;
38393              this.applySnapshot(this.stack[this.stackOffset]);
38394          }
38395      };
38396      /**
38397       * redo
38398       */
38399      History.prototype.redo = function () {
38400          if (this.stack.length - 1 > this.stackOffset) {
38401              this.stackOffset++;
38402              this.applySnapshot(this.stack[this.stackOffset]);
38403          }
38404      };
38405      /**
38406       * recorded undo
38407       */
38408      History.prototype.recordUndo = function () {
38409          this.stackOffset++;
38410          // Wash out stack after stackOffset
38411          if (this.stack.length > this.stackOffset) {
38412              this.stack = this.stack.slice(0, this.stackOffset);
38413          }
38414          // Create new snapshot and push it to the end
38415          this.stack.push(this.makeSnapshot());
38416      };
38417      return History;
38418  }());
38419
38420  var Style = /** @class */ (function () {
38421      function Style() {
38422      }
38423      /**
38424       * @method jQueryCSS
38425       *
38426       * [workaround] for old jQuery
38427       * passing an array of style properties to .css()
38428       * will result in an object of property-value pairs.
38429       * (compability with version < 1.9)
38430       *
38431       * @private
38432       * @param  {jQuery} $obj
38433       * @param  {Array} propertyNames - An array of one or more CSS properties.
38434       * @return {Object}
38435       */
38436      Style.prototype.jQueryCSS = function ($obj, propertyNames) {
38437          if (env.jqueryVersion < 1.9) {
38438              var result_1 = {};
38439              $$1.each(propertyNames, function (idx, propertyName) {
38440                  result_1[propertyName] = $obj.css(propertyName);
38441              });
38442              return result_1;
38443          }
38444          return $obj.css(propertyNames);
38445      };
38446      /**
38447       * returns style object from node
38448       *
38449       * @param {jQuery} $node
38450       * @return {Object}
38451       */
38452      Style.prototype.fromNode = function ($node) {
38453          var properties = ['font-family', 'font-size', 'text-align', 'list-style-type', 'line-height'];
38454          var styleInfo = this.jQueryCSS($node, properties) || {};
38455          styleInfo['font-size'] = parseInt(styleInfo['font-size'], 10);
38456          return styleInfo;
38457      };
38458      /**
38459       * paragraph level style
38460       *
38461       * @param {WrappedRange} rng
38462       * @param {Object} styleInfo
38463       */
38464      Style.prototype.stylePara = function (rng, styleInfo) {
vendor: 4,333 bytes, lines 38465-38557
38465          $$1.each(rng.nodes(dom.isPara, {
38466              includeAncestor: true
38467          }), function (idx, para) {
38468              $$1(para).css(styleInfo);
38469          });
38470      };
38471      /**
38472       * insert and returns styleNodes on range.
38473       *
38474       * @param {WrappedRange} rng
38475       * @param {Object} [options] - options for styleNodes
38476       * @param {String} [options.nodeName] - default: `SPAN`
38477       * @param {Boolean} [options.expandClosestSibling] - default: `false`
38478       * @param {Boolean} [options.onlyPartialContains] - default: `false`
38479       * @return {Node[]}
38480       */
38481      Style.prototype.styleNodes = function (rng, options) {
38482          rng = rng.splitText();
38483          var nodeName = (options && options.nodeName) || 'SPAN';
38484          var expandClosestSibling = !!(options && options.expandClosestSibling);
38485          var onlyPartialContains = !!(options && options.onlyPartialContains);
38486          if (rng.isCollapsed()) {
38487              return [rng.insertNode(dom.create(nodeName))];
38488          }
38489          var pred = dom.makePredByNodeName(nodeName);
38490          var nodes = rng.nodes(dom.isText, {
38491              fullyContains: true
38492          }).map(function (text) {
38493              return dom.singleChildAncestor(text, pred) || dom.wrap(text, nodeName);
38494          });
38495          if (expandClosestSibling) {
38496              if (onlyPartialContains) {
38497                  var nodesInRange_1 = rng.nodes();
38498                  // compose with partial contains predication
38499                  pred = func.and(pred, function (node) {
38500                      return lists.contains(nodesInRange_1, node);
38501                  });
38502              }
38503              return nodes.map(function (node) {
38504                  var siblings = dom.withClosestSiblings(node, pred);
38505                  var head = lists.head(siblings);
38506                  var tails = lists.tail(siblings);
38507                  $$1.each(tails, function (idx, elem) {
38508                      dom.appendChildNodes(head, elem.childNodes);
38509                      dom.remove(elem);
38510                  });
38511                  return lists.head(siblings);
38512              });
38513          }
38514          else {
38515              return nodes;
38516          }
38517      };
38518      /**
38519       * get current style on cursor
38520       *
38521       * @param {WrappedRange} rng
38522       * @return {Object} - object contains style properties.
38523       */
38524      Style.prototype.current = function (rng) {
38525          var $cont = $$1(!dom.isElement(rng.sc) ? rng.sc.parentNode : rng.sc);
38526          var styleInfo = this.fromNode($cont);
38527          // document.queryCommandState for toggle state
38528          // [workaround] prevent Firefox nsresult: "0x80004005 (NS_ERROR_FAILURE)"
38529          try {
38530              styleInfo = $$1.extend(styleInfo, {
38531                  'font-bold': document.queryCommandState('bold') ? 'bold' : 'normal',
38532                  'font-italic': document.queryCommandState('italic') ? 'italic' : 'normal',
38533                  'font-underline': document.queryCommandState('underline') ? 'underline' : 'normal',
38534                  'font-subscript': document.queryCommandState('subscript') ? 'subscript' : 'normal',
38535                  'font-superscript': document.queryCommandState('superscript') ? 'superscript' : 'normal',
38536                  'font-strikethrough': document.queryCommandState('strikethrough') ? 'strikethrough' : 'normal',
38537                  'font-family': document.queryCommandValue('fontname') || styleInfo['font-family']
38538              });
38539          }
38540          catch (e) { }
38541          // list-style-type to list-style(unordered, ordered)
38542          if (!rng.isOnList()) {
38543              styleInfo['list-style'] = 'none';
38544          }
38545          else {
38546              var orderedTypes = ['circle', 'disc', 'disc-leading-zero', 'square'];
38547              var isUnordered = $$1.inArray(styleInfo['list-style-type'], orderedTypes) > -1;
38548              styleInfo['list-style'] = isUnordered ? 'unordered' : 'ordered';
38549          }
38550          var para = dom.ancestor(rng.sc, dom.isPara);
38551          if (para && para.style['line-height']) {
38552              styleInfo['line-height'] = para.style.lineHeight;
38553          }
38554          else {
38555              var lineHeight = parseInt(styleInfo['line-height'], 10) / parseInt(styleInfo['font-size'], 10);
38556              styleInfo['line-height'] = lineHeight.toFixed(1);
38557          }
38558          styleInfo.anchor = rng.isOnAnchor() && dom.ancestor(rng.sc, dom.isAnchor);
38559          styleInfo.ancestors = dom.listAncestor(rng.sc, dom.isEditable);
38560          styleInfo.range = rng;
38561          return styleInfo;
38562      };
38563      return Style;
38564  }());
38565
38566  var Bullet = /** @class */ (function () {
38567      function Bullet() {
38568      }
38569      /**
38570       * toggle ordered list
38571       */
38572      Bullet.prototype.insertOrderedList = function (editable) {
38573          this.toggleList('OL', editable);
38574      };
38575      /**
38576       * toggle unordered list
38577       */
38578      Bullet.prototype.insertUnorderedList = function (editable) {
38579          this.toggleList('UL', editable);
38580      };
38581      /**
38582       * indent
38583       */
38584      Bullet.prototype.indent = function (editable) {
38585          var _this = this;
38586          var rng = range.create(editable).wrapBodyInlineWithPara();
38587          var paras = rng.nodes(dom.isPara, { includeAncestor: true });
38588          var clustereds = lists.clusterBy(paras, func.peq2('parentNode'));
38589          $$1.each(clustereds, function (idx, paras) {
38590              var head = lists.head(paras);
38591              if (dom.isLi(head)) {
38592                  var previousList_1 = _this.findList(head.previousSibling);
38593                  if (previousList_1) {
38594                      paras
38595                          .map(function (para) { return previousList_1.appendChild(para); });
38596                  }
38597                  else {
38598                      _this.wrapList(paras, head.parentNode.nodeName);
38599                      paras
38600                          .map(function (para) { return para.parentNode; })
38601                          .map(function (para) { return _this.appendToPrevious(para); });
38602                  }
38603              }
38604              else {
38605                  $$1.each(paras, function (idx, para) {
38606                      $$1(para).css('marginLeft', function (idx, val) {
38607                          return (parseInt(val, 10) || 0) + 25;
38608                      });
38609                  });
38610              }
38611          });
38612          rng.select();
38613      };
38614      /**
38615       * outdent
38616       */
38617      Bullet.prototype.outdent = function (editable) {
38618          var _this = this;
38619          var rng = range.create(editable).wrapBodyInlineWithPara();
38620          var paras = rng.nodes(dom.isPara, { includeAncestor: true });
38621          var clustereds = lists.clusterBy(paras, func.peq2('parentNode'));
38622          $$1.each(clustereds, function (idx, paras) {
38623              var head = lists.head(paras);
38624              if (dom.isLi(head)) {
38625                  _this.releaseList([paras]);
38626              }
38627              else {
38628                  $$1.each(paras, function (idx, para) {
38629                      $$1(para).css('marginLeft', function (idx, val) {
38630                          val = (parseInt(val, 10) || 0);
38631                          return val > 25 ? val - 25 : '';
38632                      });
38633                  });
38634              }
38635          });
38636          rng.select();
38637      };
38638      /**
38639       * toggle list
38640       *
38641       * @param {String} listName - OL or UL
38642       */
38643      Bullet.prototype.toggleList = function (listName, editable) {
38644          var _this = this;
38645          var rng = range.create(editable).wrapBodyInlineWithPara();
38646          var paras = rng.nodes(dom.isPara, { includeAncestor: true });
38647          var bookmark = rng.paraBookmark(paras);
38648          var clustereds = lists.clusterBy(paras, func.peq2('parentNode'));
38649          // paragraph to list
38650          if (lists.find(paras, dom.isPurePara)) {
38651              var wrappedParas_1 = [];
38652              $$1.each(clustereds, function (idx, paras) {
38653                  wrappedParas_1 = wrappedParas_1.concat(_this.wrapList(paras, listName));
38654              });
38655              paras = wrappedParas_1;
38656              // list to paragraph or change list style
38657          }
38658          else {
38659              var diffLists = rng.nodes(dom.isList, {
38660                  includeAncestor: true
38661              }).filter(function (listNode) {
38662                  return !$$1.nodeName(listNode, listName);
38663              });
38664              if (diffLists.length) {
38665                  $$1.each(diffLists, function (idx, listNode) {
38666                      dom.replace(listNode, listName);
38667                  });
38668              }
38669              else {
38670                  paras = this.releaseList(clustereds, true);
38671              }
38672          }
38673          range.createFromParaBookmark(bookmark, paras).select();
38674      };
38675      /**
38676       * @param {Node[]} paras
38677       * @param {String} listName
38678       * @return {Node[]}
38679       */
38680      Bullet.prototype.wrapList = function (paras, listName) {
38681          var head = lists.head(paras);
38682          var last = lists.last(paras);
38683          var prevList = dom.isList(head.previousSibling) && head.previousSibling;
38684          var nextList = dom.isList(last.nextSibling) && last.nextSibling;
vendor: 26,548 bytes, lines 38685-39324
38685          var listNode = prevList || dom.insertAfter(dom.create(listName || 'UL'), last);
38686          // P to LI
38687          paras = paras.map(function (para) {
38688              return dom.isPurePara(para) ? dom.replace(para, 'LI') : para;
38689          });
38690          // append to list(<ul>, <ol>)
38691          dom.appendChildNodes(listNode, paras);
38692          if (nextList) {
38693              dom.appendChildNodes(listNode, lists.from(nextList.childNodes));
38694              dom.remove(nextList);
38695          }
38696          return paras;
38697      };
38698      /**
38699       * @method releaseList
38700       *
38701       * @param {Array[]} clustereds
38702       * @param {Boolean} isEscapseToBody
38703       * @return {Node[]}
38704       */
38705      Bullet.prototype.releaseList = function (clustereds, isEscapseToBody) {
38706          var _this = this;
38707          var releasedParas = [];
38708          $$1.each(clustereds, function (idx, paras) {
38709              var head = lists.head(paras);
38710              var last = lists.last(paras);
38711              var headList = isEscapseToBody ? dom.lastAncestor(head, dom.isList) : head.parentNode;
38712              var parentItem = headList.parentNode;
38713              if (headList.parentNode.nodeName === 'LI') {
38714                  paras.map(function (para) {
38715                      var newList = _this.findNextSiblings(para);
38716                      if (parentItem.nextSibling) {
38717                          parentItem.parentNode.insertBefore(para, parentItem.nextSibling);
38718                      }
38719                      else {
38720                          parentItem.parentNode.appendChild(para);
38721                      }
38722                      if (newList.length) {
38723                          _this.wrapList(newList, headList.nodeName);
38724                          para.appendChild(newList[0].parentNode);
38725                      }
38726                  });
38727                  if (headList.children.length === 0) {
38728                      parentItem.removeChild(headList);
38729                  }
38730                  if (parentItem.childNodes.length === 0) {
38731                      parentItem.parentNode.removeChild(parentItem);
38732                  }
38733              }
38734              else {
38735                  var lastList = headList.childNodes.length > 1 ? dom.splitTree(headList, {
38736                      node: last.parentNode,
38737                      offset: dom.position(last) + 1
38738                  }, {
38739                      isSkipPaddingBlankHTML: true
38740                  }) : null;
38741                  var middleList = dom.splitTree(headList, {
38742                      node: head.parentNode,
38743                      offset: dom.position(head)
38744                  }, {
38745                      isSkipPaddingBlankHTML: true
38746                  });
38747                  paras = isEscapseToBody ? dom.listDescendant(middleList, dom.isLi)
38748                      : lists.from(middleList.childNodes).filter(dom.isLi);
38749                  // LI to P
38750                  if (isEscapseToBody || !dom.isList(headList.parentNode)) {
38751                      paras = paras.map(function (para) {
38752                          return dom.replace(para, 'P');
38753                      });
38754                  }
38755                  $$1.each(lists.from(paras).reverse(), function (idx, para) {
38756                      dom.insertAfter(para, headList);
38757                  });
38758                  // remove empty lists
38759                  var rootLists = lists.compact([headList, middleList, lastList]);
38760                  $$1.each(rootLists, function (idx, rootList) {
38761                      var listNodes = [rootList].concat(dom.listDescendant(rootList, dom.isList));
38762                      $$1.each(listNodes.reverse(), function (idx, listNode) {
38763                          if (!dom.nodeLength(listNode)) {
38764                              dom.remove(listNode, true);
38765                          }
38766                      });
38767                  });
38768              }
38769              releasedParas = releasedParas.concat(paras);
38770          });
38771          return releasedParas;
38772      };
38773      /**
38774       * @method appendToPrevious
38775       *
38776       * Appends list to previous list item, if
38777       * none exist it wraps the list in a new list item.
38778       *
38779       * @param {HTMLNode} ListItem
38780       * @return {HTMLNode}
38781       */
38782      Bullet.prototype.appendToPrevious = function (node) {
38783          return node.previousSibling
38784              ? dom.appendChildNodes(node.previousSibling, [node])
38785              : this.wrapList([node], 'LI');
38786      };
38787      /**
38788       * @method findList
38789       *
38790       * Finds an existing list in list item
38791       *
38792       * @param {HTMLNode} ListItem
38793       * @return {Array[]}
38794       */
38795      Bullet.prototype.findList = function (node) {
38796          return node
38797              ? lists.find(node.children, function (child) { return ['OL', 'UL'].indexOf(child.nodeName) > -1; })
38798              : null;
38799      };
38800      /**
38801       * @method findNextSiblings
38802       *
38803       * Finds all list item siblings that follow it
38804       *
38805       * @param {HTMLNode} ListItem
38806       * @return {HTMLNode}
38807       */
38808      Bullet.prototype.findNextSiblings = function (node) {
38809          var siblings = [];
38810          while (node.nextSibling) {
38811              siblings.push(node.nextSibling);
38812              node = node.nextSibling;
38813          }
38814          return siblings;
38815      };
38816      return Bullet;
38817  }());
38818
38819  /**
38820   * @class editing.Typing
38821   *
38822   * Typing
38823   *
38824   */
38825  var Typing = /** @class */ (function () {
38826      function Typing(context) {
38827          // a Bullet instance to toggle lists off
38828          this.bullet = new Bullet();
38829          this.options = context.options;
38830      }
38831      /**
38832       * insert tab
38833       *
38834       * @param {WrappedRange} rng
38835       * @param {Number} tabsize
38836       */
38837      Typing.prototype.insertTab = function (rng, tabsize) {
38838          var tab = dom.createText(new Array(tabsize + 1).join(dom.NBSP_CHAR));
38839          rng = rng.deleteContents();
38840          rng.insertNode(tab, true);
38841          rng = range.create(tab, tabsize);
38842          rng.select();
38843      };
38844      /**
38845       * insert paragraph
38846       *
38847       * @param {jQuery} $editable
38848       * @param {WrappedRange} rng Can be used in unit tests to "mock" the range
38849       *
38850       * blockquoteBreakingLevel
38851       *   0 - No break, the new paragraph remains inside the quote
38852       *   1 - Break the first blockquote in the ancestors list
38853       *   2 - Break all blockquotes, so that the new paragraph is not quoted (this is the default)
38854       */
38855      Typing.prototype.insertParagraph = function (editable, rng) {
38856          rng = rng || range.create(editable);
38857          // deleteContents on range.
38858          rng = rng.deleteContents();
38859          // Wrap range if it needs to be wrapped by paragraph
38860          rng = rng.wrapBodyInlineWithPara();
38861          // finding paragraph
38862          var splitRoot = dom.ancestor(rng.sc, dom.isPara);
38863          var nextPara;
38864          // on paragraph: split paragraph
38865          if (splitRoot) {
38866              // if it is an empty line with li
38867              if (dom.isEmpty(splitRoot) && dom.isLi(splitRoot)) {
38868                  // toogle UL/OL and escape
38869                  this.bullet.toggleList(splitRoot.parentNode.nodeName);
38870                  return;
38871              }
38872              else {
38873                  var blockquote = null;
38874                  if (this.options.blockquoteBreakingLevel === 1) {
38875                      blockquote = dom.ancestor(splitRoot, dom.isBlockquote);
38876                  }
38877                  else if (this.options.blockquoteBreakingLevel === 2) {
38878                      blockquote = dom.lastAncestor(splitRoot, dom.isBlockquote);
38879                  }
38880                  if (blockquote) {
38881                      // We're inside a blockquote and options ask us to break it
38882                      nextPara = $$1(dom.emptyPara)[0];
38883                      // If the split is right before a <br>, remove it so that there's no "empty line"
38884                      // after the split in the new blockquote created
38885                      if (dom.isRightEdgePoint(rng.getStartPoint()) && dom.isBR(rng.sc.nextSibling)) {
38886                          $$1(rng.sc.nextSibling).remove();
38887                      }
38888                      var split = dom.splitTree(blockquote, rng.getStartPoint(), { isDiscardEmptySplits: true });
38889                      if (split) {
38890                          split.parentNode.insertBefore(nextPara, split);
38891                      }
38892                      else {
38893                          dom.insertAfter(nextPara, blockquote); // There's no split if we were at the end of the blockquote
38894                      }
38895                  }
38896                  else {
38897                      nextPara = dom.splitTree(splitRoot, rng.getStartPoint());
38898                      // not a blockquote, just insert the paragraph
38899                      var emptyAnchors = dom.listDescendant(splitRoot, dom.isEmptyAnchor);
38900                      emptyAnchors = emptyAnchors.concat(dom.listDescendant(nextPara, dom.isEmptyAnchor));
38901                      $$1.each(emptyAnchors, function (idx, anchor) {
38902                          dom.remove(anchor);
38903                      });
38904                      // replace empty heading, pre or custom-made styleTag with P tag
38905                      if ((dom.isHeading(nextPara) || dom.isPre(nextPara) || dom.isCustomStyleTag(nextPara)) && dom.isEmpty(nextPara)) {
38906                          nextPara = dom.replace(nextPara, 'p');
38907                      }
38908                  }
38909              }
38910              // no paragraph: insert empty paragraph
38911          }
38912          else {
38913              var next = rng.sc.childNodes[rng.so];
38914              nextPara = $$1(dom.emptyPara)[0];
38915              if (next) {
38916                  rng.sc.insertBefore(nextPara, next);
38917              }
38918              else {
38919                  rng.sc.appendChild(nextPara);
38920              }
38921          }
38922          range.create(nextPara, 0).normalize().select().scrollIntoView(editable);
38923      };
38924      return Typing;
38925  }());
38926
38927  /**
38928   * @class Create a virtual table to create what actions to do in change.
38929   * @param {object} startPoint Cell selected to apply change.
38930   * @param {enum} where  Where change will be applied Row or Col. Use enum: TableResultAction.where
38931   * @param {enum} action Action to be applied. Use enum: TableResultAction.requestAction
38932   * @param {object} domTable Dom element of table to make changes.
38933   */
38934  var TableResultAction = function (startPoint, where, action, domTable) {
38935      var _startPoint = { 'colPos': 0, 'rowPos': 0 };
38936      var _virtualTable = [];
38937      var _actionCellList = [];
38938      /// ///////////////////////////////////////////
38939      // Private functions
38940      /// ///////////////////////////////////////////
38941      /**
38942       * Set the startPoint of action.
38943       */
38944      function setStartPoint() {
38945          if (!startPoint || !startPoint.tagName || (startPoint.tagName.toLowerCase() !== 'td' && startPoint.tagName.toLowerCase() !== 'th')) {
38946              console.error('Impossible to identify start Cell point.', startPoint);
38947              return;
38948          }
38949          _startPoint.colPos = startPoint.cellIndex;
38950          if (!startPoint.parentElement || !startPoint.parentElement.tagName || startPoint.parentElement.tagName.toLowerCase() !== 'tr') {
38951              console.error('Impossible to identify start Row point.', startPoint);
38952              return;
38953          }
38954          _startPoint.rowPos = startPoint.parentElement.rowIndex;
38955      }
38956      /**
38957       * Define virtual table position info object.
38958       *
38959       * @param {int} rowIndex Index position in line of virtual table.
38960       * @param {int} cellIndex Index position in column of virtual table.
38961       * @param {object} baseRow Row affected by this position.
38962       * @param {object} baseCell Cell affected by this position.
38963       * @param {bool} isSpan Inform if it is an span cell/row.
38964       */
38965      function setVirtualTablePosition(rowIndex, cellIndex, baseRow, baseCell, isRowSpan, isColSpan, isVirtualCell) {
38966          var objPosition = {
38967              'baseRow': baseRow,
38968              'baseCell': baseCell,
38969              'isRowSpan': isRowSpan,
38970              'isColSpan': isColSpan,
38971              'isVirtual': isVirtualCell
38972          };
38973          if (!_virtualTable[rowIndex]) {
38974              _virtualTable[rowIndex] = [];
38975          }
38976          _virtualTable[rowIndex][cellIndex] = objPosition;
38977      }
38978      /**
38979       * Create action cell object.
38980       *
38981       * @param {object} virtualTableCellObj Object of specific position on virtual table.
38982       * @param {enum} resultAction Action to be applied in that item.
38983       */
38984      function getActionCell(virtualTableCellObj, resultAction, virtualRowPosition, virtualColPosition) {
38985          return {
38986              'baseCell': virtualTableCellObj.baseCell,
38987              'action': resultAction,
38988              'virtualTable': {
38989                  'rowIndex': virtualRowPosition,
38990                  'cellIndex': virtualColPosition
38991              }
38992          };
38993      }
38994      /**
38995       * Recover free index of row to append Cell.
38996       *
38997       * @param {int} rowIndex Index of row to find free space.
38998       * @param {int} cellIndex Index of cell to find free space in table.
38999       */
39000      function recoverCellIndex(rowIndex, cellIndex) {
39001          if (!_virtualTable[rowIndex]) {
39002              return cellIndex;
39003          }
39004          if (!_virtualTable[rowIndex][cellIndex]) {
39005              return cellIndex;
39006          }
39007          var newCellIndex = cellIndex;
39008          while (_virtualTable[rowIndex][newCellIndex]) {
39009              newCellIndex++;
39010              if (!_virtualTable[rowIndex][newCellIndex]) {
39011                  return newCellIndex;
39012              }
39013          }
39014      }
39015      /**
39016       * Recover info about row and cell and add information to virtual table.
39017       *
39018       * @param {object} row Row to recover information.
39019       * @param {object} cell Cell to recover information.
39020       */
39021      function addCellInfoToVirtual(row, cell) {
39022          var cellIndex = recoverCellIndex(row.rowIndex, cell.cellIndex);
39023          var cellHasColspan = (cell.colSpan > 1);
39024          var cellHasRowspan = (cell.rowSpan > 1);
39025          var isThisSelectedCell = (row.rowIndex === _startPoint.rowPos && cell.cellIndex === _startPoint.colPos);
39026          setVirtualTablePosition(row.rowIndex, cellIndex, row, cell, cellHasRowspan, cellHasColspan, false);
39027          // Add span rows to virtual Table.
39028          var rowspanNumber = cell.attributes.rowSpan ? parseInt(cell.attributes.rowSpan.value, 10) : 0;
39029          if (rowspanNumber > 1) {
39030              for (var rp = 1; rp < rowspanNumber; rp++) {
39031                  var rowspanIndex = row.rowIndex + rp;
39032                  adjustStartPoint(rowspanIndex, cellIndex, cell, isThisSelectedCell);
39033                  setVirtualTablePosition(rowspanIndex, cellIndex, row, cell, true, cellHasColspan, true);
39034              }
39035          }
39036          // Add span cols to virtual table.
39037          var colspanNumber = cell.attributes.colSpan ? parseInt(cell.attributes.colSpan.value, 10) : 0;
39038          if (colspanNumber > 1) {
39039              for (var cp = 1; cp < colspanNumber; cp++) {
39040                  var cellspanIndex = recoverCellIndex(row.rowIndex, (cellIndex + cp));
39041                  adjustStartPoint(row.rowIndex, cellspanIndex, cell, isThisSelectedCell);
39042                  setVirtualTablePosition(row.rowIndex, cellspanIndex, row, cell, cellHasRowspan, true, true);
39043              }
39044          }
39045      }
39046      /**
39047       * Process validation and adjust of start point if needed
39048       *
39049       * @param {int} rowIndex
39050       * @param {int} cellIndex
39051       * @param {object} cell
39052       * @param {bool} isSelectedCell
39053       */
39054      function adjustStartPoint(rowIndex, cellIndex, cell, isSelectedCell) {
39055          if (rowIndex === _startPoint.rowPos && _startPoint.colPos >= cell.cellIndex && cell.cellIndex <= cellIndex && !isSelectedCell) {
39056              _startPoint.colPos++;
39057          }
39058      }
39059      /**
39060       * Create virtual table of cells with all cells, including span cells.
39061       */
39062      function createVirtualTable() {
39063          var rows = domTable.rows;
39064          for (var rowIndex = 0; rowIndex < rows.length; rowIndex++) {
39065              var cells = rows[rowIndex].cells;
39066              for (var cellIndex = 0; cellIndex < cells.length; cellIndex++) {
39067                  addCellInfoToVirtual(rows[rowIndex], cells[cellIndex]);
39068              }
39069          }
39070      }
39071      /**
39072       * Get action to be applied on the cell.
39073       *
39074       * @param {object} cell virtual table cell to apply action
39075       */
39076      function getDeleteResultActionToCell(cell) {
39077          switch (where) {
39078              case TableResultAction.where.Column:
39079                  if (cell.isColSpan) {
39080                      return TableResultAction.resultAction.SubtractSpanCount;
39081                  }
39082                  break;
39083              case TableResultAction.where.Row:
39084                  if (!cell.isVirtual && cell.isRowSpan) {
39085                      return TableResultAction.resultAction.AddCell;
39086                  }
39087                  else if (cell.isRowSpan) {
39088                      return TableResultAction.resultAction.SubtractSpanCount;
39089                  }
39090                  break;
39091          }
39092          return TableResultAction.resultAction.RemoveCell;
39093      }
39094      /**
39095       * Get action to be applied on the cell.
39096       *
39097       * @param {object} cell virtual table cell to apply action
39098       */
39099      function getAddResultActionToCell(cell) {
39100          switch (where) {
39101              case TableResultAction.where.Column:
39102                  if (cell.isColSpan) {
39103                      return TableResultAction.resultAction.SumSpanCount;
39104                  }
39105                  else if (cell.isRowSpan && cell.isVirtual) {
39106                      return TableResultAction.resultAction.Ignore;
39107                  }
39108                  break;
39109              case TableResultAction.where.Row:
39110                  if (cell.isRowSpan) {
39111                      return TableResultAction.resultAction.SumSpanCount;
39112                  }
39113                  else if (cell.isColSpan && cell.isVirtual) {
39114                      return TableResultAction.resultAction.Ignore;
39115                  }
39116                  break;
39117          }
39118          return TableResultAction.resultAction.AddCell;
39119      }
39120      function init() {
39121          setStartPoint();
39122          createVirtualTable();
39123      }
39124      /// ///////////////////////////////////////////
39125      // Public functions
39126      /// ///////////////////////////////////////////
39127      /**
39128       * Recover array os what to do in table.
39129       */
39130      this.getActionList = function () {
39131          var fixedRow = (where === TableResultAction.where.Row) ? _startPoint.rowPos : -1;
39132          var fixedCol = (where === TableResultAction.where.Column) ? _startPoint.colPos : -1;
39133          var actualPosition = 0;
39134          var canContinue = true;
39135          while (canContinue) {
39136              var rowPosition = (fixedRow >= 0) ? fixedRow : actualPosition;
39137              var colPosition = (fixedCol >= 0) ? fixedCol : actualPosition;
39138              var row = _virtualTable[rowPosition];
39139              if (!row) {
39140                  canContinue = false;
39141                  return _actionCellList;
39142              }
39143              var cell = row[colPosition];
39144              if (!cell) {
39145                  canContinue = false;
39146                  return _actionCellList;
39147              }
39148              // Define action to be applied in this cell
39149              var resultAction = TableResultAction.resultAction.Ignore;
39150              switch (action) {
39151                  case TableResultAction.requestAction.Add:
39152                      resultAction = getAddResultActionToCell(cell);
39153                      break;
39154                  case TableResultAction.requestAction.Delete:
39155                      resultAction = getDeleteResultActionToCell(cell);
39156                      break;
39157              }
39158              _actionCellList.push(getActionCell(cell, resultAction, rowPosition, colPosition));
39159              actualPosition++;
39160          }
39161          return _actionCellList;
39162      };
39163      init();
39164  };
39165  /**
39166  *
39167  * Where action occours enum.
39168  */
39169  TableResultAction.where = { 'Row': 0, 'Column': 1 };
39170  /**
39171  *
39172  * Requested action to apply enum.
39173  */
39174  TableResultAction.requestAction = { 'Add': 0, 'Delete': 1 };
39175  /**
39176  *
39177  * Result action to be executed enum.
39178  */
39179  TableResultAction.resultAction = { 'Ignore': 0, 'SubtractSpanCount': 1, 'RemoveCell': 2, 'AddCell': 3, 'SumSpanCount': 4 };
39180  /**
39181   *
39182   * @class editing.Table
39183   *
39184   * Table
39185   *
39186   */
39187  var Table = /** @class */ (function () {
39188      function Table() {
39189      }
39190      /**
39191       * handle tab key
39192       *
39193       * @param {WrappedRange} rng
39194       * @param {Boolean} isShift
39195       */
39196      Table.prototype.tab = function (rng, isShift) {
39197          var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
39198          var table = dom.ancestor(cell, dom.isTable);
39199          var cells = dom.listDescendant(table, dom.isCell);
39200          var nextCell = lists[isShift ? 'prev' : 'next'](cells, cell);
39201          if (nextCell) {
39202              range.create(nextCell, 0).select();
39203          }
39204      };
39205      /**
39206       * Add a new row
39207       *
39208       * @param {WrappedRange} rng
39209       * @param {String} position (top/bottom)
39210       * @return {Node}
39211       */
39212      Table.prototype.addRow = function (rng, position) {
39213          var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
39214          var currentTr = $$1(cell).closest('tr');
39215          var trAttributes = this.recoverAttributes(currentTr);
39216          var html = $$1('<tr' + trAttributes + '></tr>');
39217          var vTable = new TableResultAction(cell, TableResultAction.where.Row, TableResultAction.requestAction.Add, $$1(currentTr).closest('table')[0]);
39218          var actions = vTable.getActionList();
39219          for (var idCell = 0; idCell < actions.length; idCell++) {
39220              var currentCell = actions[idCell];
39221              var tdAttributes = this.recoverAttributes(currentCell.baseCell);
39222              switch (currentCell.action) {
39223                  case TableResultAction.resultAction.AddCell:
39224                      html.append('<td' + tdAttributes + '>' + dom.blank + '</td>');
39225                      break;
39226                  case TableResultAction.resultAction.SumSpanCount:
39227                      if (position === 'top') {
39228                          var baseCellTr = currentCell.baseCell.parent;
39229                          var isTopFromRowSpan = (!baseCellTr ? 0 : currentCell.baseCell.closest('tr').rowIndex) <= currentTr[0].rowIndex;
39230                          if (isTopFromRowSpan) {
39231                              var newTd = $$1('<div></div>').append($$1('<td' + tdAttributes + '>' + dom.blank + '</td>').removeAttr('rowspan')).html();
39232                              html.append(newTd);
39233                              break;
39234                          }
39235                      }
39236                      var rowspanNumber = parseInt(currentCell.baseCell.rowSpan, 10);
39237                      rowspanNumber++;
39238                      currentCell.baseCell.setAttribute('rowSpan', rowspanNumber);
39239                      break;
39240              }
39241          }
39242          if (position === 'top') {
39243              currentTr.before(html);
39244          }
39245          else {
39246              var cellHasRowspan = (cell.rowSpan > 1);
39247              if (cellHasRowspan) {
39248                  var lastTrIndex = currentTr[0].rowIndex + (cell.rowSpan - 2);
39249                  $$1($$1(currentTr).parent().find('tr')[lastTrIndex]).after($$1(html));
39250                  return;
39251              }
39252              currentTr.after(html);
39253          }
39254      };
39255      /**
39256       * Add a new col
39257       *
39258       * @param {WrappedRange} rng
39259       * @param {String} position (left/right)
39260       * @return {Node}
39261       */
39262      Table.prototype.addCol = function (rng, position) {
39263          var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
39264          var row = $$1(cell).closest('tr');
39265          var rowsGroup = $$1(row).siblings();
39266          rowsGroup.push(row);
39267          var vTable = new TableResultAction(cell, TableResultAction.where.Column, TableResultAction.requestAction.Add, $$1(row).closest('table')[0]);
39268          var actions = vTable.getActionList();
39269          for (var actionIndex = 0; actionIndex < actions.length; actionIndex++) {
39270              var currentCell = actions[actionIndex];
39271              var tdAttributes = this.recoverAttributes(currentCell.baseCell);
39272              switch (currentCell.action) {
39273                  case TableResultAction.resultAction.AddCell:
39274                      if (position === 'right') {
39275                          $$1(currentCell.baseCell).after('<td' + tdAttributes + '>' + dom.blank + '</td>');
39276                      }
39277                      else {
39278                          $$1(currentCell.baseCell).before('<td' + tdAttributes + '>' + dom.blank + '</td>');
39279                      }
39280                      break;
39281                  case TableResultAction.resultAction.SumSpanCount:
39282                      if (position === 'right') {
39283                          var colspanNumber = parseInt(currentCell.baseCell.colSpan, 10);
39284                          colspanNumber++;
39285                          currentCell.baseCell.setAttribute('colSpan', colspanNumber);
39286                      }
39287                      else {
39288                          $$1(currentCell.baseCell).before('<td' + tdAttributes + '>' + dom.blank + '</td>');
39289                      }
39290                      break;
39291              }
39292          }
39293      };
39294      /*
39295      * Copy attributes from element.
39296      *
39297      * @param {object} Element to recover attributes.
39298      * @return {string} Copied string elements.
39299      */
39300      Table.prototype.recoverAttributes = function (el) {
39301          var resultStr = '';
39302          if (!el) {
39303              return resultStr;
39304          }
39305          var attrList = el.attributes || [];
39306          for (var i = 0; i < attrList.length; i++) {
39307              if (attrList[i].name.toLowerCase() === 'id') {
39308                  continue;
39309              }
39310              if (attrList[i].specified) {
39311                  resultStr += ' ' + attrList[i].name + '=\'' + attrList[i].value + '\'';
39312              }
39313          }
39314          return resultStr;
39315      };
39316      /**
39317       * Delete current row
39318       *
39319       * @param {WrappedRange} rng
39320       * @return {Node}
39321       */
39322      Table.prototype.deleteRow = function (rng) {
39323          var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
39324          var row = $$1(cell).closest('tr');
39325          var cellPos = row.children('td, th').index($$1(cell));
39326          var rowPos = row[0].rowIndex;
39327          var vTable = new TableResultAction(cell, TableResultAction.where.Row, TableResultAction.requestAction.Delete, $$1(row).closest('table')[0]);
39328          var actions = vTable.getActionList();
39329          for (var actionIndex = 0; actionIndex < actions.length; actionIndex++) {
39330              if (!actions[actionIndex]) {
39331                  continue;
39332              }
39333              var baseCell = actions[actionIndex].baseCell;
39334              var virtualPosition = actions[actionIndex].virtualTable;
39335              var hasRowspan = (baseCell.rowSpan && baseCell.rowSpan > 1);
39336              var rowspanNumber = (hasRowspan) ? parseInt(baseCell.rowSpan, 10) : 0;
39337              switch (actions[actionIndex].action) {
39338                  case TableResultAction.resultAction.Ignore:
39339                      continue;
39340                  case TableResultAction.resultAction.AddCell:
39341                      var nextRow = row.next('tr')[0];
39342                      if (!nextRow) {
39343                          continue;
39344                      }
39345                      var cloneRow = row[0].cells[cellPos];
39346                      if (hasRowspan) {
39347                          if (rowspanNumber > 2) {
39348                              rowspanNumber--;
39349                              nextRow.insertBefore(cloneRow, nextRow.cells[cellPos]);
39350                              nextRow.cells[cellPos].setAttribute('rowSpan', rowspanNumber);
39351                              nextRow.cells[cellPos].innerHTML = '';
39352                          }
39353                          else if (rowspanNumber === 2) {
39354                              nextRow.insertBefore(cloneRow, nextRow.cells[cellPos]);
39355                              nextRow.cells[cellPos].removeAttribute('rowSpan');
39356                              nextRow.cells[cellPos].innerHTML = '';
39357                          }
39358                      }
39359                      continue;
39360                  case TableResultAction.resultAction.SubtractSpanCount:
39361                      if (hasRowspan) {
39362                          if (rowspanNumber > 2) {
39363                              rowspanNumber--;
39364                              baseCell.setAttribute('rowSpan', rowspanNumber);
39365                              if (virtualPosition.rowIndex !== rowPos && baseCell.cellIndex === cellPos) {
39366                                  baseCell.innerHTML = '';
39367                              }
39368                          }
39369                          else if (rowspanNumber === 2) {
39370                              baseCell.removeAttribute('rowSpan');
39371                              if (virtualPosition.rowIndex !== rowPos && baseCell.cellIndex === cellPos) {
39372                                  baseCell.innerHTML = '';
39373                              }
39374                          }
39375                      }
39376                      continue;
39377                  case TableResultAction.resultAction.RemoveCell:
39378                      // Do not need remove cell because row will be deleted.
39379                      continue;
39380              }
39381          }
39382          row.remove();
39383      };
39384      /**
39385       * Delete current col
39386       *
39387       * @param {WrappedRange} rng
39388       * @return {Node}
39389       */
39390      Table.prototype.deleteCol = function (rng) {
39391          var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
39392          var row = $$1(cell).closest('tr');
39393          var cellPos = row.children('td, th').index($$1(cell));
39394          var vTable = new TableResultAction(cell, TableResultAction.where.Column, TableResultAction.requestAction.Delete, $$1(row).closest('table')[0]);
39395          var actions = vTable.getActionList();
39396          for (var actionIndex = 0; actionIndex < actions.length; actionIndex++) {
39397              if (!actions[actionIndex]) {
39398                  continue;
39399              }
39400              switch (actions[actionIndex].action) {
39401                  case TableResultAction.resultAction.Ignore:
39402                      continue;
39403                  case TableResultAction.resultAction.SubtractSpanCount:
39404                      var baseCell = actions[actionIndex].baseCell;
39405                      var hasColspan = (baseCell.colSpan && baseCell.colSpan > 1);
39406                      if (hasColspan) {
39407                          var colspanNumber = (baseCell.colSpan) ? parseInt(baseCell.colSpan, 10) : 0;
39408                          if (colspanNumber > 2) {
39409                              colspanNumber--;
39410                              baseCell.setAttribute('colSpan', colspanNumber);
39411                              if (baseCell.cellIndex === cellPos) {
39412                                  baseCell.innerHTML = '';
39413                              }
39414                          }
39415                          else if (colspanNumber === 2) {
39416                              baseCell.removeAttribute('colSpan');
39417                              if (baseCell.cellIndex === cellPos) {
39418                                  baseCell.innerHTML = '';
39419                              }
39420                          }
39421                      }
39422                      continue;
39423                  case TableResultAction.resultAction.RemoveCell:
39424                      dom.remove(actions[actionIndex].baseCell, true);
39425                      continue;
39426              }
39427          }
39428      };
39429      /**
39430       * create empty table element
39431       *
39432       * @param {Number} rowCount
39433       * @param {Number} colCount
39434       * @return {Node}
39435       */
39436      Table.prototype.createTable = function (colCount, rowCount, options) {
39437          var tds = [];
39438          var tdHTML;
39439          for (var idxCol = 0; idxCol < colCount; idxCol++) {
39440              tds.push('<td>' + dom.blank + '</td>');
39441          }
39442          tdHTML = tds.join('');
39443          var trs = [];
39444          var trHTML;
39445          for (var idxRow = 0; idxRow < rowCount; idxRow++) {
39446              trs.push('<tr>' + tdHTML + '</tr>');
39447          }
39448          trHTML = trs.join('');
39449          var $table = $$1('<table>' + trHTML + '</table>');
39450          if (options && options.tableClassName) {
39451              $table.addClass(options.tableClassName);
39452          }
39453          return $table[0];
39454      };
39455      /**
39456       * Delete current table
39457       *
39458       * @param {WrappedRange} rng
39459       * @return {Node}
39460       */
39461      Table.prototype.deleteTable = function (rng) {
39462          var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
39463          $$1(cell).closest('table').remove();
39464      };
39465      return Table;
39466  }());
39467
39468  var KEY_BOGUS = 'bogus';
39469  /**
39470   * @class Editor
39471   */
39472  var Editor = /** @class */ (function () {
39473      function Editor(context) {
39474          var _this = this;
39475          this.context = context;
39476          this.$note = context.layoutInfo.note;
39477          this.$editor = context.layoutInfo.editor;
39478          this.$editable = context.layoutInfo.editable;
39479          this.options = context.options;
39480          this.lang = this.options.langInfo;
39481          this.editable = this.$editable[0];
39482          this.lastRange = null;
39483          this.style = new Style();
39484          this.table = new Table();
39485          this.typing = new Typing(context);
39486          this.bullet = new Bullet();
39487          this.history = new History(this.$editable);
39488          this.context.memo('help.undo', this.lang.help.undo);
39489          this.context.memo('help.redo', this.lang.help.redo);
39490          this.context.memo('help.tab', this.lang.help.tab);
39491          this.context.memo('help.untab', this.lang.help.untab);
39492          this.context.memo('help.insertParagraph', this.lang.help.insertParagraph);
39493          this.context.memo('help.insertOrderedList', this.lang.help.insertOrderedList);
39494          this.context.memo('help.insertUnorderedList', this.lang.help.insertUnorderedList);
39495          this.context.memo('help.indent', this.lang.help.indent);
39496          this.context.memo('help.outdent', this.lang.help.outdent);
39497          this.context.memo('help.formatPara', this.lang.help.formatPara);
39498          this.context.memo('help.insertHorizontalRule', this.lang.help.insertHorizontalRule);
39499          this.context.memo('help.fontName', this.lang.help.fontName);
39500          // native commands(with execCommand), generate function for execCommand
39501          var commands = [
39502              'bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript',
39503              'justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull',
39504              'formatBlock', 'removeFormat', 'backColor'
39505          ];
39506          for (var idx = 0, len = commands.length; idx < len; idx++) {
39507              this[commands[idx]] = (function (sCmd) {
39508                  return function (value) {
39509                      _this.beforeCommand();
39510                      document.execCommand(sCmd, false, value);
39511                      _this.afterCommand(true);
39512                  };
39513              })(commands[idx]);
39514              this.context.memo('help.' + commands[idx], this.lang.help[commands[idx]]);
39515          }
39516          this.fontName = this.wrapCommand(function (value) {
39517              return _this.fontStyling('font-family', "\'" + value + "\'");
39518          });
39519          this.fontSize = this.wrapCommand(function (value) {
39520              return _this.fontStyling('font-size', value + 'px');
39521          });
39522          for (var idx = 1; idx <= 6; idx++) {
39523              this['formatH' + idx] = (function (idx) {
39524                  return function () {
39525                      _this.formatBlock('H' + idx);
39526                  };
39527              })(idx);
39528              this.context.memo('help.formatH' + idx, this.lang.help['formatH' + idx]);
39529          }
39530          this.insertParagraph = this.wrapCommand(function () {
39531              _this.typing.insertParagraph(_this.editable);
39532          });
39533          this.insertOrderedList = this.wrapCommand(function () {
39534              _this.bullet.insertOrderedList(_this.editable);
39535          });
39536          this.insertUnorderedList = this.wrapCommand(function () {
39537              _this.bullet.insertUnorderedList(_this.editable);
39538          });
39539          this.indent = this.wrapCommand(function () {
39540              _this.bullet.indent(_this.editable);
39541          });
39542          this.outdent = this.wrapCommand(function () {
39543              _this.bullet.outdent(_this.editable);
39544          });
39545          /**
39546           * insertNode
39547           * insert node
39548           * @param {Node} node
39549           */
39550          this.insertNode = this.wrapCommand(function (node) {
39551              if (_this.isLimited($$1(node).text().length)) {
39552                  return;
39553              }
39554              var rng = _this.createRange();
39555              rng.insertNode(node);
39556              range.createFromNodeAfter(node).select();
39557          });
39558          /**
39559           * insert text
39560           * @param {String} text
39561           */
39562          this.insertText = this.wrapCommand(function (text) {
39563              if (_this.isLimited(text.length)) {
39564                  return;
39565              }
39566              var rng = _this.createRange();
39567              var textNode = rng.insertNode(dom.createText(text));
39568              range.create(textNode, dom.nodeLength(textNode)).select();
39569          });
39570          /**
39571           * paste HTML
39572           * @param {String} markup
39573           */
39574          this.pasteHTML = this.wrapCommand(function (markup) {
39575              if (_this.isLimited(markup.length)) {
39576                  return;
39577              }
39578              var contents = _this.createRange().pasteHTML(markup);
39579              range.createFromNodeAfter(lists.last(contents)).select();
39580          });
39581          /**
39582           * formatBlock
39583           *
39584           * @param {String} tagName
39585           */
39586          this.formatBlock = this.wrapCommand(function (tagName, $target) {
39587              var onApplyCustomStyle = _this.options.callbacks.onApplyCustomStyle;
39588              if (onApplyCustomStyle) {
39589                  onApplyCustomStyle.call(_this, $target, _this.context, _this.onFormatBlock);
39590              }
39591              else {
39592                  _this.onFormatBlock(tagName, $target);
39593              }
39594          });
39595          /**
39596           * insert horizontal rule
39597           */
39598          this.insertHorizontalRule = this.wrapCommand(function () {
39599              var hrNode = _this.createRange().insertNode(dom.create('HR'));
39600              if (hrNode.nextSibling) {
39601                  range.create(hrNode.nextSibling, 0).normalize().select();
39602              }
39603          });
39604          /**
39605           * lineHeight
39606           * @param {String} value
39607           */
39608          this.lineHeight = this.wrapCommand(function (value) {
39609              _this.style.stylePara(_this.createRange(), {
39610                  lineHeight: value
39611              });
39612          });
39613          /**
39614           * create link (command)
39615           *
39616           * @param {Object} linkInfo
39617           */
39618          this.createLink = this.wrapCommand(function (linkInfo) {
39619              var linkUrl = linkInfo.url;
39620              var linkText = linkInfo.text;
39621              var isNewWindow = linkInfo.isNewWindow;
39622              var rng = linkInfo.range || _this.createRange();
39623              var additionalTextLength = linkText.length - rng.toString().length;
39624              if (additionalTextLength > 0 && _this.isLimited(additionalTextLength)) {
39625                  return;
39626              }
39627              var isTextChanged = rng.toString() !== linkText;
39628              // handle spaced urls from input
39629              if (typeof linkUrl === 'string') {
39630                  linkUrl = linkUrl.trim();
39631              }
39632              if (_this.options.onCreateLink) {
39633                  linkUrl = _this.options.onCreateLink(linkUrl);
39634              }
39635              else {
39636                  // if url is not relative,
39637                  if (!/^\.?\/(.*)/.test(linkUrl)) {
39638                      // if url doesn't match an URL schema, set http:// as default
39639                      linkUrl = /^[A-Za-z][A-Za-z0-9+-.]*\:[\/\/]?/.test(linkUrl)
39640                          ? linkUrl : 'http://' + linkUrl;
39641                  }
39642              }
39643              var anchors = [];
39644              if (isTextChanged) {
39645                  rng = rng.deleteContents();
39646                  var anchor = rng.insertNode($$1('<A>' + linkText + '</A>')[0]);
39647                  anchors.push(anchor);
39648              }
39649              else {
39650                  anchors = _this.style.styleNodes(rng, {
39651                      nodeName: 'A',
39652                      expandClosestSibling: true,
39653                      onlyPartialContains: true
39654                  });
39655              }
39656              $$1.each(anchors, function (idx, anchor) {
39657                  $$1(anchor).attr('href', linkUrl);
39658                  if (isNewWindow) {
39659                      $$1(anchor).attr('target', '_blank');
39660                  }
39661                  else {
39662                      $$1(anchor).removeAttr('target');
39663                  }
39664              });
39665              var startRange = range.createFromNodeBefore(lists.head(anchors));
39666              var startPoint = startRange.getStartPoint();
39667              var endRange = range.createFromNodeAfter(lists.last(anchors));
39668              var endPoint = endRange.getEndPoint();
39669              range.create(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset).select();
39670          });
39671          /**
39672           * setting color
39673           *
39674           * @param {Object} sObjColor  color code
39675           * @param {String} sObjColor.foreColor foreground color
39676           * @param {String} sObjColor.backColor background color
39677           */
39678          this.color = this.wrapCommand(function (colorInfo) {
39679              var foreColor = colorInfo.foreColor;
39680              var backColor = colorInfo.backColor;
39681              if (foreColor) {
39682                  document.execCommand('foreColor', false, foreColor);
39683              }
39684              if (backColor) {
39685                  document.execCommand('backColor', false, backColor);
39686              }
39687          });
39688          /**
39689           * Set foreground color
39690           *
39691           * @param {String} colorCode foreground color code
39692           */
39693          this.foreColor = this.wrapCommand(function (colorInfo) {
39694              document.execCommand('styleWithCSS', false, true);
39695              document.execCommand('foreColor', false, colorInfo);
39696          });
39697          /**
39698           * insert Table
39699           *
39700           * @param {String} dimension of table (ex : "5x5")
39701           */
39702          this.insertTable = this.wrapCommand(function (dim) {
39703              var dimension = dim.split('x');
39704              var rng = _this.createRange().deleteContents();
39705              rng.insertNode(_this.table.createTable(dimension[0], dimension[1], _this.options));
39706          });
39707          /**
39708           * remove media object and Figure Elements if media object is img with Figure.
39709           */
39710          this.removeMedia = this.wrapCommand(function () {
39711              var $target = $$1(_this.restoreTarget()).parent();
39712              if ($target.parent('figure').length) {
39713                  $target.parent('figure').remove();
39714              }
39715              else {
39716                  $target = $$1(_this.restoreTarget()).detach();
39717              }
39718              _this.context.triggerEvent('media.delete', $target, _this.$editable);
39719          });
39720          /**
39721           * float me
39722           *
39723           * @param {String} value
39724           */
39725          this.floatMe = this.wrapCommand(function (value) {
39726              var $target = $$1(_this.restoreTarget());
39727              $target.toggleClass('note-float-left', value === 'left');
39728              $target.toggleClass('note-float-right', value === 'right');
39729              $target.css('float', value);
39730          });
39731          /**
39732           * resize overlay element
39733           * @param {String} value
39734           */
39735          this.resize = this.wrapCommand(function (value) {
39736              var $target = $$1(_this.restoreTarget());
39737              $target.css({
39738                  width: value * 100 + '%',
39739                  height: ''
39740              });
39741          });
39742      }
39743      Editor.prototype.initialize = function () {
39744          var _this = this;
39745          // bind custom events
39746          this.$editable.on('keydown', function (event) {
39747              if (event.keyCode === key.code.ENTER) {
39748                  _this.context.triggerEvent('enter', event);
39749              }
39750              _this.context.triggerEvent('keydown', event);
39751              if (!event.isDefaultPrevented()) {
39752                  if (_this.options.shortcuts) {
39753                      _this.handleKeyMap(event);
39754                  }
39755                  else {
39756                      _this.preventDefaultEditableShortCuts(event);
39757                  }
39758              }
39759              if (_this.isLimited(1, event)) {
39760                  return false;
39761              }
39762          }).on('keyup', function (event) {
39763              _this.context.triggerEvent('keyup', event);
39764          }).on('focus', function (event) {
39765              _this.context.triggerEvent('focus', event);
39766          }).on('blur', function (event) {
39767              _this.context.triggerEvent('blur', event);
39768          }).on('mousedown', function (event) {
39769              _this.context.triggerEvent('mousedown', event);
39770          }).on('mouseup', function (event) {
39771              _this.context.triggerEvent('mouseup', event);
39772          }).on('scroll', function (event) {
39773              _this.context.triggerEvent('scroll', event);
39774          }).on('paste', function (event) {
39775              _this.context.triggerEvent('paste', event);
39776          });
39777          // init content before set event
39778          this.$editable.html(dom.html(this.$note) || dom.emptyPara);
39779          this.$editable.on(env.inputEventName, func.debounce(function () {
39780              _this.context.triggerEvent('change', _this.$editable.html());
39781          }, 10));
39782          this.$editor.on('focusin', function (event) {
39783              _this.context.triggerEvent('focusin', event);
39784          }).on('focusout', function (event) {
39785              _this.context.triggerEvent('focusout', event);
39786          });
39787          if (!this.options.airMode) {
39788              if (this.options.width) {
39789                  this.$editor.outerWidth(this.options.width);
39790              }
39791              if (this.options.height) {
39792                  this.$editable.outerHeight(this.options.height);
39793              }
39794              if (this.options.maxHeight) {
39795                  this.$editable.css('max-height', this.options.maxHeight);
39796              }
39797              if (this.options.minHeight) {
39798                  this.$editable.css('min-height', this.options.minHeight);
39799              }
39800          }
39801          this.history.recordUndo();
39802      };
39803      Editor.prototype.destroy = function () {
39804          this.$editable.off();
39805      };
39806      Editor.prototype.handleKeyMap = function (event) {
39807          var keyMap = this.options.keyMap[env.isMac ? 'mac' : 'pc'];
39808          var keys = [];
39809          if (event.metaKey) {
39810              keys.push('CMD');
39811          }
39812          if (event.ctrlKey && !event.altKey) {
39813              keys.push('CTRL');
39814          }
39815          if (event.shiftKey) {
39816              keys.push('SHIFT');
39817          }
39818          var keyName = key.nameFromCode[event.keyCode];
39819          if (keyName) {
39820              keys.push(keyName);
39821          }
39822          var eventName = keyMap[keys.join('+')];
39823          if (eventName) {
39824              if (this.context.invoke(eventName) !== false) {
39825                  event.preventDefault();
39826              }
39827          }
39828          else if (key.isEdit(event.keyCode)) {
39829              this.afterCommand();
39830          }
39831      };
39832      Editor.prototype.preventDefaultEditableShortCuts = function (event) {
39833          // B(Bold, 66) / I(Italic, 73) / U(Underline, 85)
39834          if ((event.ctrlKey || event.metaKey) &&
39835              lists.contains([66, 73, 85], event.keyCode)) {
39836              event.preventDefault();
39837          }
39838      };
39839      Editor.prototype.isLimited = function (pad, event) {
39840          pad = pad || 0;
39841          if (typeof event !== 'undefined') {
39842              if (key.isMove(event.keyCode) ||
39843                  (event.ctrlKey || event.metaKey) ||
39844                  lists.contains([key.code.BACKSPACE, key.code.DELETE], event.keyCode)) {
39845                  return false;
39846              }
39847          }
39848          if (this.options.maxTextLength > 0) {
39849              if ((this.$editable.text().length + pad) >= this.options.maxTextLength) {
39850                  return true;
39851              }
39852          }
39853          return false;
39854      };
39855      /**
39856       * create range
39857       * @return {WrappedRange}
39858       */
39859      Editor.prototype.createRange = function () {
39860          this.focus();
39861          return range.create(this.editable);
39862      };
39863      /**
39864       * saveRange
39865       *
39866       * save current range
39867       *
39868       * @param {Boolean} [thenCollapse=false]
39869       */
39870      Editor.prototype.saveRange = function (thenCollapse) {
39871          this.lastRange = this.createRange();
39872          if (thenCollapse) {
39873              this.lastRange.collapse().select();
39874          }
39875      };
39876      /**
39877       * restoreRange
39878       *
39879       * restore lately range
39880       */
39881      Editor.prototype.restoreRange = function () {
39882          if (this.lastRange) {
39883              this.lastRange.select();
39884              this.focus();
39885          }
39886      };
39887      Editor.prototype.saveTarget = function (node) {
39888          this.$editable.data('target', node);
39889      };
39890      Editor.prototype.clearTarget = function () {
39891          this.$editable.removeData('target');
39892      };
39893      Editor.prototype.restoreTarget = function () {
39894          return this.$editable.data('target');
39895      };
39896      /**
39897       * currentStyle
39898       *
39899       * current style
39900       * @return {Object|Boolean} unfocus
39901       */
39902      Editor.prototype.currentStyle = function () {
39903          var rng = range.create();
39904          if (rng) {
39905              rng = rng.normalize();
39906          }
39907          return rng ? this.style.current(rng) : this.style.fromNode(this.$editable);
39908      };
39909      /**
39910       * style from node
39911       *
39912       * @param {jQuery} $node
39913       * @return {Object}
39914       */
39915      Editor.prototype.styleFromNode = function ($node) {
39916          return this.style.fromNode($node);
39917      };
39918      /**
39919       * undo
39920       */
39921      Editor.prototype.undo = function () {
39922          this.context.triggerEvent('before.command', this.$editable.html());
39923          this.history.undo();
39924          this.context.triggerEvent('change', this.$editable.html());
39925      };
39926      /*
39927      * commit
39928      */
39929      Editor.prototype.commit = function () {
39930          this.context.triggerEvent('before.command', this.$editable.html());
39931          this.history.commit();
39932          this.context.triggerEvent('change', this.$editable.html());
39933      };
39934      /**
39935       * redo
39936       */
39937      Editor.prototype.redo = function () {
39938          this.context.triggerEvent('before.command', this.$editable.html());
39939          this.history.redo();
39940          this.context.triggerEvent('change', this.$editable.html());
39941      };
39942      /**
39943       * before command
39944       */
39945      Editor.prototype.beforeCommand = function () {
39946          this.context.triggerEvent('before.command', this.$editable.html());
39947          // keep focus on editable before command execution
39948          this.focus();
39949      };
39950      /**
39951       * after command
39952       * @param {Boolean} isPreventTrigger
39953       */
39954      Editor.prototype.afterCommand = function (isPreventTrigger) {
39955          this.normalizeContent();
39956          this.history.recordUndo();
39957          if (!isPreventTrigger) {
39958              this.context.triggerEvent('change', this.$editable.html());
39959          }
39960      };
39961      /**
39962       * handle tab key
39963       */
39964      Editor.prototype.tab = function () {
39965          var rng = this.createRange();
39966          if (rng.isCollapsed() && rng.isOnCell()) {
39967              this.table.tab(rng);
39968          }
39969          else {
39970              if (this.options.tabSize === 0) {
39971                  return false;
39972              }
39973              if (!this.isLimited(this.options.tabSize)) {
39974                  this.beforeCommand();
39975                  this.typing.insertTab(rng, this.options.tabSize);
39976                  this.afterCommand();
39977              }
39978          }
39979      };
39980      /**
39981       * handle shift+tab key
39982       */
39983      Editor.prototype.untab = function () {
39984          var rng = this.createRange();
39985          if (rng.isCollapsed() && rng.isOnCell()) {
39986              this.table.tab(rng, true);
39987          }
39988          else {
39989              if (this.options.tabSize === 0) {
39990                  return false;
39991              }
39992          }
39993      };
39994      /**
39995       * run given function between beforeCommand and afterCommand
39996       */
39997      Editor.prototype.wrapCommand = function (fn) {
39998          return function () {
39999              this.beforeCommand();
40000              fn.apply(this, arguments);
40001              this.afterCommand();
40002          };
40003      };
40004      /**
40005       * insert image
40006       *
40007       * @param {String} src
40008       * @param {String|Function} param
40009       * @return {Promise}
40010       */
40011      Editor.prototype.insertImage = function (src, param) {
40012          var _this = this;
40013          return createImage(src, param).then(function ($image) {
40014              _this.beforeCommand();
40015              if (typeof param === 'function') {
40016                  param($image);
40017              }
40018              else {
40019                  if (typeof param === 'string') {
40020                      $image.attr('data-filename', param);
40021                  }
40022                  $image.css('width', Math.min(_this.$editable.width(), $image.width()));
40023              }
40024              $image.show();
40025              range.create(_this.editable).insertNode($image[0]);
40026              range.createFromNodeAfter($image[0]).select();
40027              _this.afterCommand();
40028          }).fail(function (e) {
40029              _this.context.triggerEvent('image.upload.error', e);
40030          });
40031      };
40032      /**
40033       * insertImages
40034       * @param {File[]} files
40035       */
40036      Editor.prototype.insertImagesAsDataURL = function (files) {
40037          var _this = this;
40038          $$1.each(files, function (idx, file) {
40039              var filename = file.name;
40040              if (_this.options.maximumImageFileSize && _this.options.maximumImageFileSize < file.size) {
40041                  _this.context.triggerEvent('image.upload.error', _this.lang.image.maximumFileSizeError);
40042              }
40043              else {
40044                  readFileAsDataURL(file).then(function (dataURL) {
40045                      return _this.insertImage(dataURL, filename);
40046                  }).fail(function () {
40047                      _this.context.triggerEvent('image.upload.error');
40048                  });
40049              }
40050          });
40051      };
40052      /**
40053       * return selected plain text
40054       * @return {String} text
40055       */
40056      Editor.prototype.getSelectedText = function () {
40057          var rng = this.createRange();
40058          // if range on anchor, expand range with anchor
40059          if (rng.isOnAnchor()) {
40060              rng = range.createFromNode(dom.ancestor(rng.sc, dom.isAnchor));
40061          }
40062          return rng.toString();
40063      };
40064      Editor.prototype.onFormatBlock = function (tagName, $target) {
40065          // [workaround] for MSIE, IE need `<`
40066          tagName = env.isMSIE ? '<' + tagName + '>' : tagName;
40067          document.execCommand('FormatBlock', false, tagName);
40068          // support custom class
40069          if ($target && $target.length) {
40070              var className = $target[0].className || '';
40071              if (className) {
40072                  var currentRange = this.createRange();
40073                  var $parent = $$1([currentRange.sc, currentRange.ec]).closest(tagName);
40074                  $parent.addClass(className);
40075              }
40076          }
40077      };
40078      Editor.prototype.formatPara = function () {
40079          this.formatBlock('P');
40080      };
40081      Editor.prototype.fontStyling = function (target, value) {
40082          var rng = this.createRange();
40083          if (rng) {
40084              var spans = this.style.styleNodes(rng);
40085              $$1(spans).css(target, value);
40086              // [workaround] added styled bogus span for style
40087              //  - also bogus character needed for cursor position
40088              if (rng.isCollapsed()) {
40089                  var firstSpan = lists.head(spans);
40090                  if (firstSpan && !dom.nodeLength(firstSpan)) {
40091                      firstSpan.innerHTML = dom.ZERO_WIDTH_NBSP_CHAR;
40092                      range.createFromNodeAfter(firstSpan.firstChild).select();
40093                      this.$editable.data(KEY_BOGUS, firstSpan);
40094                  }
40095              }
40096          }
40097      };
40098      /**
40099       * unlink
40100       *
40101       * @type command
40102       */
40103      Editor.prototype.unlink = function () {
40104          var rng = this.createRange();
40105          if (rng.isOnAnchor()) {
40106              var anchor = dom.ancestor(rng.sc, dom.isAnchor);
40107              rng = range.createFromNode(anchor);
40108              rng.select();
40109              this.beforeCommand();
40110              document.execCommand('unlink');
40111              this.afterCommand();
40112          }
40113      };
40114      /**
40115       * returns link info
40116       *
40117       * @return {Object}
40118       * @return {WrappedRange} return.range
40119       * @return {String} return.text
40120       * @return {Boolean} [return.isNewWindow=true]
40121       * @return {String} [return.url=""]
40122       */
40123      Editor.prototype.getLinkInfo = function () {
40124          var rng = this.createRange().expand(dom.isAnchor);
40125          // Get the first anchor on range(for edit).
40126          var $anchor = $$1(lists.head(rng.nodes(dom.isAnchor)));
40127          var linkInfo = {
40128              range: rng,
40129              text: rng.toString(),
40130              url: $anchor.length ? $anchor.attr('href') : ''
40131          };
40132          // When anchor exists,
40133          if ($anchor.length) {
40134              // Set isNewWindow by checking its target.
40135              linkInfo.isNewWindow = $anchor.attr('target') === '_blank';
40136          }
40137          return linkInfo;
40138      };
40139      Editor.prototype.addRow = function (position) {
40140          var rng = this.createRange(this.$editable);
40141          if (rng.isCollapsed() && rng.isOnCell()) {
40142              this.beforeCommand();
40143              this.table.addRow(rng, position);
40144              this.afterCommand();
40145          }
40146      };
40147      Editor.prototype.addCol = function (position) {
40148          var rng = this.createRange(this.$editable);
40149          if (rng.isCollapsed() && rng.isOnCell()) {
40150              this.beforeCommand();
40151              this.table.addCol(rng, position);
40152              this.afterCommand();
40153          }
40154      };
40155      Editor.prototype.deleteRow = function () {
40156          var rng = this.createRange(this.$editable);
40157          if (rng.isCollapsed() && rng.isOnCell()) {
40158              this.beforeCommand();
40159              this.table.deleteRow(rng);
40160              this.afterCommand();
40161          }
40162      };
40163      Editor.prototype.deleteCol = function () {
40164          var rng = this.createRange(this.$editable);
40165          if (rng.isCollapsed() && rng.isOnCell()) {
40166              this.beforeCommand();
40167              this.table.deleteCol(rng);
40168              this.afterCommand();
40169          }
40170      };
40171      Editor.prototype.deleteTable = function () {
40172          var rng = this.createRange(this.$editable);
40173          if (rng.isCollapsed() && rng.isOnCell()) {
40174              this.beforeCommand();
40175              this.table.deleteTable(rng);
40176              this.afterCommand();
40177          }
40178      };
40179      /**
40180       * @param {Position} pos
40181       * @param {jQuery} $target - target element
40182       * @param {Boolean} [bKeepRatio] - keep ratio
40183       */
40184      Editor.prototype.resizeTo = function (pos, $target, bKeepRatio) {
40185          var imageSize;
40186          if (bKeepRatio) {
40187              var newRatio = pos.y / pos.x;
40188              var ratio = $target.data('ratio');
40189              imageSize = {
40190                  width: ratio > newRatio ? pos.x : pos.y / ratio,
40191                  height: ratio > newRatio ? pos.x * ratio : pos.y
40192              };
40193          }
40194          else {
40195              imageSize = {
40196                  width: pos.x,
40197                  height: pos.y
40198              };
40199          }
40200          $target.css(imageSize);
40201      };
40202      /**
40203       * returns whether editable area has focus or not.
40204       */
40205      Editor.prototype.hasFocus = function () {
40206          return this.$editable.is(':focus');
40207      };
40208      /**
40209       * set focus
40210       */
40211      Editor.prototype.focus = function () {
40212          // [workaround] Screen will move when page is scolled in IE.
40213          //  - do focus when not focused
40214          if (!this.hasFocus()) {
40215              this.$editable.focus();
40216          }
40217      };
40218      /**
40219       * returns whether contents is empty or not.
40220       * @return {Boolean}
40221       */
40222      Editor.prototype.isEmpty = function () {
40223          return dom.isEmpty(this.$editable[0]) || dom.emptyPara === this.$editable.html();
40224      };
40225      /**
40226       * Removes all contents and restores the editable instance to an _emptyPara_.
40227       */
40228      Editor.prototype.empty = function () {
40229          this.context.invoke('code', dom.emptyPara);
40230      };
40231      /**
40232       * normalize content
40233       */
40234      Editor.prototype.normalizeContent = function () {
40235          this.$editable[0].normalize();
40236      };
40237      return Editor;
40238  }());
40239
40240  var Clipboard = /** @class */ (function () {
40241      function Clipboard(context) {
40242          this.context = context;
40243          this.$editable = context.layoutInfo.editable;
40244      }
40245      Clipboard.prototype.initialize = function () {
40246          this.$editable.on('paste', this.pasteByEvent.bind(this));
40247      };
40248      /**
40249       * paste by clipboard event
40250       *
40251       * @param {Event} event
40252       */
40253      Clipboard.prototype.pasteByEvent = function (event) {
40254          var clipboardData = event.originalEvent.clipboardData;
40255          if (clipboardData && clipboardData.items && clipboardData.items.length) {
40256              // paste img file
40257              var item = clipboardData.items.length > 1 ? clipboardData.items[1] : lists.head(clipboardData.items);
40258              if (item.kind === 'file' && item.type.indexOf('image/') !== -1) {
40259                  this.context.invoke('editor.insertImagesOrCallback', [item.getAsFile()]);
40260              }
40261              this.context.invoke('editor.afterCommand');
40262          }
40263      };
40264      return Clipboard;
40265  }());
40266
40267  var Dropzone = /** @class */ (function () {
40268      function Dropzone(context) {
40269          this.context = context;
40270          this.$eventListener = $$1(document);
40271          this.$editor = context.layoutInfo.editor;
40272          this.$editable = context.layoutInfo.editable;
40273          this.options = context.options;
40274          this.lang = this.options.langInfo;
40275          this.documentEventHandlers = {};
40276          this.$dropzone = $$1([
40277              '<div class="note-dropzone">',
40278              '  <div class="note-dropzone-message"/>',
40279              '</div>'
40280          ].join('')).prependTo(this.$editor);
40281      }
40282      /**
40283       * attach Drag and Drop Events
40284       */
40285      Dropzone.prototype.initialize = function () {
40286          if (this.options.disableDragAndDrop) {
40287              // prevent default drop event
40288              this.documentEventHandlers.onDrop = function (e) {
40289                  e.preventDefault();
40290              };
40291              // do not consider outside of dropzone
40292              this.$eventListener = this.$dropzone;
40293              this.$eventListener.on('drop', this.documentEventHandlers.onDrop);
40294          }
40295          else {
40296              this.attachDragAndDropEvent();
40297          }
40298      };
40299      /**
40300       * attach Drag and Drop Events
40301       */
40302      Dropzone.prototype.attachDragAndDropEvent = function () {
40303          var _this = this;
40304          var collection = $$1();
40305          var $dropzoneMessage = this.$dropzone.find('.note-dropzone-message');
40306          this.documentEventHandlers.onDragenter = function (e) {
40307              var isCodeview = _this.context.invoke('codeview.isActivated');
40308              var hasEditorSize = _this.$editor.width() > 0 && _this.$editor.height() > 0;
40309              if (!isCodeview && !collection.length && hasEditorSize) {
40310                  _this.$editor.addClass('dragover');
40311                  _this.$dropzone.width(_this.$editor.width());
40312                  _this.$dropzone.height(_this.$editor.height());
40313                  $dropzoneMessage.text(_this.lang.image.dragImageHere);
40314              }
40315              collection = collection.add(e.target);
40316          };
40317          this.documentEventHandlers.onDragleave = function (e) {
40318              collection = collection.not(e.target);
40319              if (!collection.length) {
40320                  _this.$editor.removeClass('dragover');
40321              }
40322          };
40323          this.documentEventHandlers.onDrop = function () {
40324              collection = $$1();
40325              _this.$editor.removeClass('dragover');
40326          };
40327          // show dropzone on dragenter when dragging a object to document
40328          // -but only if the editor is visible, i.e. has a positive width and height
40329          this.$eventListener.on('dragenter', this.documentEventHandlers.onDragenter)
40330              .on('dragleave', this.documentEventHandlers.onDragleave)
40331              .on('drop', this.documentEventHandlers.onDrop);
40332          // change dropzone's message on hover.
40333          this.$dropzone.on('dragenter', function () {
40334              _this.$dropzone.addClass('hover');
40335              $dropzoneMessage.text(_this.lang.image.dropImage);
40336          }).on('dragleave', function () {
40337              _this.$dropzone.removeClass('hover');
40338              $dropzoneMessage.text(_this.lang.image.dragImageHere);
40339          });
40340          // attach dropImage
40341          this.$dropzone.on('drop', function (event) {
40342              var dataTransfer = event.originalEvent.dataTransfer;
40343              // stop the browser from opening the dropped content
40344              event.preventDefault();
40345              if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
40346                  _this.$editable.focus();
40347                  _this.context.invoke('editor.insertImagesOrCallback', dataTransfer.files);
40348              }
40349              else {
40350                  $$1.each(dataTransfer.types, function (idx, type) {
40351                      var content = dataTransfer.getData(type);
40352                      if (type.toLowerCase().indexOf('text') > -1) {
40353                          _this.context.invoke('editor.pasteHTML', content);
40354                      }
40355                      else {
40356                          $$1(content).each(function (idx, item) {
40357                              _this.context.invoke('editor.insertNode', item);
40358                          });
40359                      }
40360                  });
40361              }
40362          }).on('dragover', false); // prevent default dragover event
40363      };
40364      Dropzone.prototype.destroy = function () {
40365          var _this = this;
40366          Object.keys(this.documentEventHandlers).forEach(function (key) {
40367              _this.$eventListener.off(key.substr(2).toLowerCase(), _this.documentEventHandlers[key]);
40368          });
40369          this.documentEventHandlers = {};
40370      };
40371      return Dropzone;
40372  }());
40373
40374  var CodeMirror;
40375  if (env.hasCodeMirror) {
40376      if (env.isSupportAmd) {
40377          require(['codemirror'], function (cm) {
40378              CodeMirror = cm;
40379          });
40380      }
40381      else {
40382          CodeMirror = window.CodeMirror;
40383      }
40384  }
40385  /**
40386   * @class Codeview
40387   */
40388  var CodeView = /** @class */ (function () {
40389      function CodeView(context) {
40390          this.context = context;
40391          this.$editor = context.layoutInfo.editor;
40392          this.$editable = context.layoutInfo.editable;
40393          this.$codable = context.layoutInfo.codable;
40394          this.options = context.options;
40395      }
40396      CodeView.prototype.sync = function () {
40397          var isCodeview = this.isActivated();
40398          if (isCodeview && env.hasCodeMirror) {
40399              this.$codable.data('cmEditor').save();
40400          }
40401      };
40402      /**
40403       * @return {Boolean}
40404       */
40405      CodeView.prototype.isActivated = function () {
40406          return this.$editor.hasClass('codeview');
40407      };
40408      /**
40409       * toggle codeview
40410       */
40411      CodeView.prototype.toggle = function () {
40412          if (this.isActivated()) {
40413              this.deactivate();
40414          }
40415          else {
40416              this.activate();
40417          }
40418          this.context.triggerEvent('codeview.toggled');
40419      };
40420      /**
40421       * activate code view
40422       */
40423      CodeView.prototype.activate = function () {
40424          var _this = this;
40425          this.$codable.val(dom.html(this.$editable, this.options.prettifyHtml));
40426          this.$codable.height(this.$editable.height());
40427          this.context.invoke('toolbar.updateCodeview', true);
40428          this.$editor.addClass('codeview');
40429          this.$codable.focus();
40430          // activate CodeMirror as codable
40431          if (env.hasCodeMirror) {
40432              var cmEditor_1 = CodeMirror.fromTextArea(this.$codable[0], this.options.codemirror);
40433              // CodeMirror TernServer
40434              if (this.options.codemirror.tern) {
40435                  var server_1 = new CodeMirror.TernServer(this.options.codemirror.tern);
40436                  cmEditor_1.ternServer = server_1;
40437                  cmEditor_1.on('cursorActivity', function (cm) {
40438                      server_1.updateArgHints(cm);
40439                  });
40440              }
40441              cmEditor_1.on('blur', function (event) {
40442                  _this.context.triggerEvent('blur.codeview', cmEditor_1.getValue(), event);
40443              });
40444              // CodeMirror hasn't Padding.
40445              cmEditor_1.setSize(null, this.$editable.outerHeight());
40446              this.$codable.data('cmEditor', cmEditor_1);
40447          }
40448          else {
40449              this.$codable.on('blur', function (event) {
40450                  _this.context.triggerEvent('blur.codeview', _this.$codable.val(), event);
40451              });
40452          }
40453      };
40454      /**
40455       * deactivate code view
40456       */
40457      CodeView.prototype.deactivate = function () {
40458          // deactivate CodeMirror as codable
40459          if (env.hasCodeMirror) {
40460              var cmEditor = this.$codable.data('cmEditor');
40461              this.$codable.val(cmEditor.getValue());
40462              cmEditor.toTextArea();
40463          }
40464          var value = dom.value(this.$codable, this.options.prettifyHtml) || dom.emptyPara;
40465          var isChange = this.$editable.html() !== value;
40466          this.$editable.html(value);
40467          this.$editable.height(this.options.height ? this.$codable.height() : 'auto');
40468          this.$editor.removeClass('codeview');
40469          if (isChange) {
40470              this.context.triggerEvent('change', this.$editable.html(), this.$editable);
40471          }
40472          this.$editable.focus();
40473          this.context.invoke('toolbar.updateCodeview', false);
40474      };
40475      CodeView.prototype.destroy = function () {
40476          if (this.isActivated()) {
40477              this.deactivate();
40478          }
40479      };
40480      return CodeView;
40481  }());
40482
40483  var EDITABLE_PADDING = 24;
40484  var Statusbar = /** @class */ (function () {
40485      function Statusbar(context) {
40486          this.$document = $$1(document);
40487          this.$statusbar = context.layoutInfo.statusbar;
40488          this.$editable = context.layoutInfo.editable;
40489          this.options = context.options;
40490      }
40491      Statusbar.prototype.initialize = function () {
40492          var _this = this;
40493          if (this.options.airMode || this.options.disableResizeEditor) {
40494              this.destroy();
40495              return;
40496          }
40497          this.$statusbar.on('mousedown', function (event) {
40498              event.preventDefault();
40499              event.stopPropagation();
40500              var editableTop = _this.$editable.offset().top - _this.$document.scrollTop();
40501              var onMouseMove = function (event) {
40502                  var height = event.clientY - (editableTop + EDITABLE_PADDING);
40503                  height = (_this.options.minheight > 0) ? Math.max(height, _this.options.minheight) : height;
40504                  height = (_this.options.maxHeight > 0) ? Math.min(height, _this.options.maxHeight) : height;
40505                  _this.$editable.height(height);
40506              };
40507              _this.$document.on('mousemove', onMouseMove).one('mouseup', function () {
40508                  _this.$document.off('mousemove', onMouseMove);
40509              });
40510          });
40511      };
40512      Statusbar.prototype.destroy = function () {
40513          this.$statusbar.off();
40514          this.$statusbar.addClass('locked');
40515      };
40516      return Statusbar;
40517  }());
40518
40519  var Fullscreen = /** @class */ (function () {
40520      function Fullscreen(context) {
40521          var _this = this;
40522          this.context = context;
40523          this.$editor = context.layoutInfo.editor;
40524          this.$toolbar = context.layoutInfo.toolbar;
40525          this.$editable = context.layoutInfo.editable;
40526          this.$codable = context.layoutInfo.codable;
40527          this.$window = $$1(window);
40528          this.$scrollbar = $$1('html, body');
40529          this.onResize = function () {
40530              _this.resizeTo({
40531                  h: _this.$window.height() - _this.$toolbar.outerHeight()
40532              });
40533          };
40534      }
40535      Fullscreen.prototype.resizeTo = function (size) {
40536          this.$editable.css('height', size.h);
40537          this.$codable.css('height', size.h);
40538          if (this.$codable.data('cmeditor')) {
40539              this.$codable.data('cmeditor').setsize(null, size.h);
40540          }
40541      };
40542      /**
40543       * toggle fullscreen
40544       */
40545      Fullscreen.prototype.toggle = function () {
40546          this.$editor.toggleClass('fullscreen');
40547          if (this.isFullscreen()) {
40548              this.$editable.data('orgHeight', this.$editable.css('height'));
40549              this.$editable.data('orgMaxHeight', this.$editable.css('maxHeight'));
40550              this.$editable.css('maxHeight', '');
40551              this.$window.on('resize', this.onResize).trigger('resize');
40552              this.$scrollbar.css('overflow', 'hidden');
40553          }
40554          else {
40555              this.$window.off('resize', this.onResize);
40556              this.resizeTo({ h: this.$editable.data('orgHeight') });
40557              this.$editable.css('maxHeight', this.$editable.css('orgMaxHeight'));
40558              this.$scrollbar.css('overflow', 'visible');
40559          }
40560          this.context.invoke('toolbar.updateFullscreen', this.isFullscreen());
40561      };
40562      Fullscreen.prototype.isFullscreen = function () {
40563          return this.$editor.hasClass('fullscreen');
40564      };
40565      return Fullscreen;
40566  }());
40567
40568  var Handle = /** @class */ (function () {
40569      function Handle(context) {
40570          var _this = this;
40571          this.context = context;
40572          this.$document = $$1(document);
40573          this.$editingArea = context.layoutInfo.editingArea;
40574          this.options = context.options;
40575          this.lang = this.options.langInfo;
40576          this.events = {
40577              'summernote.mousedown': function (we, e) {
40578                  if (_this.update(e.target)) {
40579                      e.preventDefault();
40580                  }
40581              },
40582              'summernote.keyup summernote.scroll summernote.change summernote.dialog.shown': function () {
40583                  _this.update();
40584              },
40585              'summernote.disable': function () {
40586                  _this.hide();
40587              },
40588              'summernote.codeview.toggled': function () {
40589                  _this.update();
40590              }
40591          };
40592      }
40593      Handle.prototype.initialize = function () {
40594          var _this = this;
40595          this.$handle = $$1([
40596              '<div class="note-handle">',
40597              '<div class="note-control-selection">',
40598              '<div class="note-control-selection-bg"></div>',
40599              '<div class="note-control-holder note-control-nw"></div>',
40600              '<div class="note-control-holder note-control-ne"></div>',
40601              '<div class="note-control-holder note-control-sw"></div>',
40602              '<div class="',
40603              (this.options.disableResizeImage ? 'note-control-holder' : 'note-control-sizing'),
40604              ' note-control-se"></div>',
40605              (this.options.disableResizeImage ? '' : '<div class="note-control-selection-info"></div>'),
40606              '</div>',
40607              '</div>'
40608          ].join('')).prependTo(this.$editingArea);
40609          this.$handle.on('mousedown', function (event) {
40610              if (dom.isControlSizing(event.target)) {
40611                  event.preventDefault();
40612                  event.stopPropagation();
40613                  var $target_1 = _this.$handle.find('.note-control-selection').data('target');
40614                  var posStart_1 = $target_1.offset();
40615                  var scrollTop_1 = _this.$document.scrollTop();
40616                  var onMouseMove_1 = function (event) {
40617                      _this.context.invoke('editor.resizeTo', {
40618                          x: event.clientX - posStart_1.left,
40619                          y: event.clientY - (posStart_1.top - scrollTop_1)
40620                      }, $target_1, !event.shiftKey);
40621                      _this.update($target_1[0]);
40622                  };
40623                  _this.$document
40624                      .on('mousemove', onMouseMove_1)
40625                      .one('mouseup', function (e) {
40626                      e.preventDefault();
40627                      _this.$document.off('mousemove', onMouseMove_1);
40628                      _this.context.invoke('editor.afterCommand');
40629                  });
40630                  if (!$target_1.data('ratio')) { // original ratio.
40631                      $target_1.data('ratio', $target_1.height() / $target_1.width());
40632                  }
40633              }
40634          });
40635          // Listen for scrolling on the handle overlay.
40636          this.$handle.on('wheel', function (e) {
40637              e.preventDefault();
40638              _this.update();
40639          });
40640      };
40641      Handle.prototype.destroy = function () {
40642          this.$handle.remove();
40643      };
40644      Handle.prototype.update = function (target) {
40645          if (this.context.isDisabled()) {
40646              return false;
40647          }
40648          var isImage = dom.isImg(target);
40649          var $selection = this.$handle.find('.note-control-selection');
40650          this.context.invoke('imagePopover.update', target);
40651          if (isImage) {
40652              var $image = $$1(target);
40653              var position = $image.position();
40654              var pos = {
40655                  left: position.left + parseInt($image.css('marginLeft'), 10),
40656                  top: position.top + parseInt($image.css('marginTop'), 10)
40657              };
40658              // exclude margin
40659              var imageSize = {
40660                  w: $image.outerWidth(false),
40661                  h: $image.outerHeight(false)
40662              };
40663              $selection.css({
40664                  display: 'block',
40665                  left: pos.left,
40666                  top: pos.top,
40667                  width: imageSize.w,
40668                  height: imageSize.h
40669              }).data('target', $image); // save current image element.
40670              var origImageObj = new Image();
40671              origImageObj.src = $image.attr('src');
40672              var sizingText = imageSize.w + 'x' + imageSize.h + ' (' + this.lang.image.original + ': ' + origImageObj.width + 'x' + origImageObj.height + ')';
40673              $selection.find('.note-control-selection-info').text(sizingText);
40674              this.context.invoke('editor.saveTarget', target);
40675          }
40676          else {
40677              this.hide();
40678          }
40679          return isImage;
40680      };
40681      /**
40682       * hide
40683       *
40684       * @param {jQuery} $handle
40685       */
40686      Handle.prototype.hide = function () {
40687          this.context.invoke('editor.clearTarget');
40688          this.$handle.children().hide();
40689      };
40690      return Handle;
40691  }());
40692
40693  var defaultScheme = 'http://';
40694  var linkPattern = /^([A-Za-z][A-Za-z0-9+-.]*\:[\/]{2}|mailto:[A-Z0-9._%+-]+@)?(www\.)?(.+)$/i;
40695  var AutoLink = /** @class */ (function () {
40696      function AutoLink(context) {
40697          var _this = this;
40698          this.context = context;
40699          this.events = {
40700              'summernote.keyup': function (we, e) {
40701                  if (!e.isDefaultPrevented()) {
40702                      _this.handleKeyup(e);
40703                  }
40704              },
40705              'summernote.keydown': function (we, e) {
40706                  _this.handleKeydown(e);
40707              }
40708          };
40709      }
40710      AutoLink.prototype.initialize = function () {
40711          this.lastWordRange = null;
40712      };
40713      AutoLink.prototype.destroy = function () {
40714          this.lastWordRange = null;
40715      };
40716      AutoLink.prototype.replace = function () {
40717          if (!this.lastWordRange) {
40718              return;
40719          }
40720          var keyword = this.lastWordRange.toString();
40721          var match = keyword.match(linkPattern);
40722          if (match && (match[1] || match[2])) {
40723              var link = match[1] ? keyword : defaultScheme + keyword;
40724              var node = $$1('<a />').html(keyword).attr('href', link)[0];
40725              if (this.context.options.linkTargetBlank) {
40726                  $$1(node).attr('target', '_blank');
40727              }
40728              this.lastWordRange.insertNode(node);
40729              this.lastWordRange = null;
40730              this.context.invoke('editor.focus');
40731          }
40732      };
40733      AutoLink.prototype.handleKeydown = function (e) {
40734          if (lists.contains([key.code.ENTER, key.code.SPACE], e.keyCode)) {
40735              var wordRange = this.context.invoke('editor.createRange').getWordRange();
40736              this.lastWordRange = wordRange;
40737          }
40738      };
40739      AutoLink.prototype.handleKeyup = function (e) {
40740          if (lists.contains([key.code.ENTER, key.code.SPACE], e.keyCode)) {
40741              this.replace();
40742          }
40743      };
40744      return AutoLink;
40745  }());
40746
40747  /**
40748   * textarea auto sync.
40749   */
40750  var AutoSync = /** @class */ (function () {
40751      function AutoSync(context) {
40752          var _this = this;
40753          this.$note = context.layoutInfo.note;
40754          this.events = {
40755              'summernote.change': function () {
40756                  _this.$note.val(context.invoke('code'));
40757              }
40758          };
40759      }
40760      AutoSync.prototype.shouldInitialize = function () {
40761          return dom.isTextarea(this.$note[0]);
40762      };
40763      return AutoSync;
40764  }());
40765
40766  var Placeholder = /** @class */ (function () {
40767      function Placeholder(context) {
40768          var _this = this;
40769          this.context = context;
40770          this.$editingArea = context.layoutInfo.editingArea;
40771          this.options = context.options;
40772          this.events = {
40773              'summernote.init summernote.change': function () {
40774                  _this.update();
40775              },
40776              'summernote.codeview.toggled': function () {
40777                  _this.update();
40778              }
40779          };
40780      }
40781      Placeholder.prototype.shouldInitialize = function () {
40782          return !!this.options.placeholder;
40783      };
40784      Placeholder.prototype.initialize = function () {
40785          var _this = this;
40786          this.$placeholder = $$1('<div class="note-placeholder">');
40787          this.$placeholder.on('click', function () {
40788              _this.context.invoke('focus');
40789          }).html(this.options.placeholder).prependTo(this.$editingArea);
40790          this.update();
40791      };
40792      Placeholder.prototype.destroy = function () {
40793          this.$placeholder.remove();
40794      };
40795      Placeholder.prototype.update = function () {
40796          var isShow = !this.context.invoke('codeview.isActivated') && this.context.invoke('editor.isEmpty');
40797          this.$placeholder.toggle(isShow);
40798      };
40799      return Placeholder;
40800  }());
40801
40802  var Buttons = /** @class */ (function () {
40803      function Buttons(context) {
40804          this.ui = $$1.summernote.ui;
40805          this.context = context;
40806          this.$toolbar = context.layoutInfo.toolbar;
40807          this.options = context.options;
40808          this.lang = this.options.langInfo;
40809          this.invertedKeyMap = func.invertObject(this.options.keyMap[env.isMac ? 'mac' : 'pc']);
40810      }
40811      Buttons.prototype.representShortcut = function (editorMethod) {
40812          var shortcut = this.invertedKeyMap[editorMethod];
40813          if (!this.options.shortcuts || !shortcut) {
40814              return '';
40815          }
40816          if (env.isMac) {
40817              shortcut = shortcut.replace('CMD', '⌘').replace('SHIFT', '⇧');
40818          }
40819          shortcut = shortcut.replace('BACKSLASH', '\\')
40820              .replace('SLASH', '/')
40821              .replace('LEFTBRACKET', '[')
40822              .replace('RIGHTBRACKET', ']');
40823          return ' (' + shortcut + ')';
40824      };
40825      Buttons.prototype.button = function (o) {
40826          if (!this.options.tooltip && o.tooltip) {
40827              delete o.tooltip;
40828          }
40829          o.container = this.options.container;
40830          return this.ui.button(o);
40831      };
40832      Buttons.prototype.initialize = function () {
40833          this.addToolbarButtons();
40834          this.addImagePopoverButtons();
40835          this.addLinkPopoverButtons();
40836          this.addTablePopoverButtons();
40837          this.fontInstalledMap = {};
40838      };
40839      Buttons.prototype.destroy = function () {
40840          delete this.fontInstalledMap;
40841      };
40842      Buttons.prototype.isFontInstalled = function (name) {
40843          if (!this.fontInstalledMap.hasOwnProperty(name)) {
40844              this.fontInstalledMap[name] = env.isFontInstalled(name) ||
40845                  lists.contains(this.options.fontNamesIgnoreCheck, name);
40846          }
40847          return this.fontInstalledMap[name];
40848      };
40849      Buttons.prototype.isFontDeservedToAdd = function (name) {
40850          var genericFamilies = ['sans-serif', 'serif', 'monospace', 'cursive', 'fantasy'];
40851          name = name.toLowerCase();
40852          return ((name !== '') && this.isFontInstalled(name) && ($$1.inArray(name, genericFamilies
vendor: 35,494 bytes, lines 40852-41523
40852) === -1));
40853      };
40854      Buttons.prototype.colorPalette = function (className, tooltip, backColor, foreColor) {
40855          var _this = this;
40856          return this.ui.buttonGroup({
40857              className: 'note-color ' + className,
40858              children: [
40859                  this.button({
40860                      className: 'note-current-color-button',
40861                      contents: this.ui.icon(this.options.icons.font + ' note-recent-color'),
40862                      tooltip: tooltip,
40863                      click: function (e) {
40864                          var $button = $$1(e.currentTarget);
40865                          if (backColor && foreColor) {
40866                              _this.context.invoke('editor.color', {
40867                                  backColor: $button.attr('data-backColor'),
40868                                  foreColor: $button.attr('data-foreColor')
40869                              });
40870                          }
40871                          else if (backColor) {
40872                              _this.context.invoke('editor.color', {
40873                                  backColor: $button.attr('data-backColor')
40874                              });
40875                          }
40876                          else if (foreColor) {
40877                              _this.context.invoke('editor.color', {
40878                                  foreColor: $button.attr('data-foreColor')
40879                              });
40880                          }
40881                      },
40882                      callback: function ($button) {
40883                          var $recentColor = $button.find('.note-recent-color');
40884                          if (backColor) {
40885                              $recentColor.css('background-color', '#FFFF00');
40886                              $button.attr('data-backColor', '#FFFF00');
40887                          }
40888                          if (!foreColor) {
40889                              $recentColor.css('color', 'transparent');
40890                          }
40891                      }
40892                  }),
40893                  this.button({
40894                      className: 'dropdown-toggle',
40895                      contents: this.ui.dropdownButtonContents('', this.options),
40896                      tooltip: this.lang.color.more,
40897                      data: {
40898                          toggle: 'dropdown'
40899                      }
40900                  }),
40901                  this.ui.dropdown({
40902                      items: (backColor ? [
40903                          '<div class="note-palette">',
40904                          '  <div class="note-palette-title">' + this.lang.color.background + '</div>',
40905                          '  <div>',
40906                          '    <button type="button" class="note-color-reset btn btn-light" data-event="backColor" data-value="inherit">',
40907                          this.lang.color.transparent,
40908                          '    </button>',
40909                          '  </div>',
40910                          '  <div class="note-holder" data-event="backColor"/>',
40911                          '  <div>',
40912                          '    <button type="button" class="note-color-select btn" data-event="openPalette" data-value="backColorPicker">',
40913                          this.lang.color.cpSelect,
40914                          '    </button>',
40915                          '    <input type="color" id="backColorPicker" class="note-btn note-color-select-btn" value="#FFFF00" data-event="backColorPalette">',
40916                          '  </div>',
40917                          '  <div class="note-holder-custom" id="backColorPalette" data-event="backColor"/>',
40918                          '</div>'
40919                      ].join('') : '') +
40920                          (foreColor ? [
40921                              '<div class="note-palette">',
40922                              '  <div class="note-palette-title">' + this.lang.color.foreground + '</div>',
40923                              '  <div>',
40924                              '    <button type="button" class="note-color-reset btn btn-light" data-event="removeFormat" data-value="foreColor">',
40925                              this.lang.color.resetToDefault,
40926                              '    </button>',
40927                              '  </div>',
40928                              '  <div class="note-holder" data-event="foreColor"/>',
40929                              '  <div>',
40930                              '    <button type="button" class="note-color-select btn" data-event="openPalette" data-value="foreColorPicker">',
40931                              this.lang.color.cpSelect,
40932                              '    </button>',
40933                              '    <input type="color" id="foreColorPicker" class="note-btn note-color-select-btn" value="#000000" data-event="foreColorPalette">',
40934                              '  <div class="note-holder-custom" id="foreColorPalette" data-event="foreColor"/>',
40935                              '</div>'
40936                          ].join('') : ''),
40937                      callback: function ($dropdown) {
40938                          $dropdown.find('.note-holder').each(function (idx, item) {
40939                              var $holder = $$1(item);
40940                              $holder.append(_this.ui.palette({
40941                                  colors: _this.options.colors,
40942                                  colorsName: _this.options.colorsName,
40943                                  eventName: $holder.data('event'),
40944                                  container: _this.options.container,
40945                                  tooltip: _this.options.tooltip
40946                              }).render());
40947                          });
40948                          /* TODO: do we have to record recent custom colors within cookies? */
40949                          var customColors = [
40950                              ['#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF']
40951                          ];
40952                          $dropdown.find('.note-holder-custom').each(function (idx, item) {
40953                              var $holder = $$1(item);
40954                              $holder.append(_this.ui.palette({
40955                                  colors: customColors,
40956                                  colorsName: customColors,
40957                                  eventName: $holder.data('event'),
40958                                  container: _this.options.container,
40959                                  tooltip: _this.options.tooltip
40960                              }).render());
40961                          });
40962                          $dropdown.find('input[type=color]').each(function (idx, item) {
40963                              $$1(item).change(function () {
40964                                  var $chip = $dropdown.find('#' + $$1(this).data('event')).find('.note-color-btn').first();
40965                                  var color = this.value.toUpperCase();
40966                                  $chip.css('background-color', color)
40967                                      .attr('aria-label', color)
40968                                      .attr('data-value', color)
40969                                      .attr('data-original-title', color);
40970                                  $chip.click();
40971                              });
40972                          });
40973                      },
40974                      click: function (event) {
40975                          event.stopPropagation();
40976                          var $parent = $$1('.' + className);
40977                          var $button = $$1(event.target);
40978                          var eventName = $button.data('event');
40979                          var value = $button.attr('data-value');
40980                          if (eventName === 'openPalette') {
40981                              var $picker = $parent.find('#' + value);
40982                              var $palette = $$1($parent.find('#' + $picker.data('event')).find('.note-color-row')[0]);
40983                              // Shift palette chips
40984                              var $chip = $palette.find('.note-color-btn').last().detach();
40985                              // Set chip attributes
40986                              var color = $picker.val();
40987                              $chip.css('background-color', color)
40988                                  .attr('aria-label', color)
40989                                  .attr('data-value', color)
40990                                  .attr('data-original-title', color);
40991                              $palette.prepend($chip);
40992                              $picker.click();
40993                          }
40994                          else if (lists.contains(['backColor', 'foreColor'], eventName)) {
40995                              var key = eventName === 'backColor' ? 'background-color' : 'color';
40996                              var $color = $button.closest('.note-color').find('.note-recent-color');
40997                              var $currentButton = $button.closest('.note-color').find('.note-current-color-button');
40998                              $color.css(key, value);
40999                              $currentButton.attr('data-' + eventName, value);
41000                              _this.context.invoke('editor.' + eventName, value);
41001                          }
41002                      }
41003                  })
41004              ]
41005          }).render();
41006      };
41007      Buttons.prototype.addToolbarButtons = function () {
41008          var _this = this;
41009          this.context.memo('button.style', function () {
41010              return _this.ui.buttonGroup([
41011                  _this.button({
41012                      className: 'dropdown-toggle',
41013                      contents: _this.ui.dropdownButtonContents(_this.ui.icon(_this.options.icons.magic), _this.options),
41014                      tooltip: _this.lang.style.style,
41015                      data: {
41016                          toggle: 'dropdown'
41017                      }
41018                  }),
41019                  _this.ui.dropdown({
41020                      className: 'dropdown-style',
41021                      items: _this.options.styleTags,
41022                      title: _this.lang.style.style,
41023                      template: function (item) {
41024                          if (typeof item === 'string') {
41025                              item = { tag: item, title: (_this.lang.style.hasOwnProperty(item) ? _this.lang.style[item] : item) };
41026                          }
41027                          var tag = item.tag;
41028                          var title = item.title;
41029                          var style = item.style ? ' style="' + item.style + '" ' : '';
41030                          var className = item.className ? ' class="' + item.className + '"' : '';
41031                          return '<' + tag + style + className + '>' + title + '</' + tag + '>';
41032                      },
41033                      click: _this.context.createInvokeHandler('editor.formatBlock')
41034                  })
41035              ]).render();
41036          });
41037          var _loop_1 = function (styleIdx, styleLen) {
41038              var item = this_1.options.styleTags[styleIdx];
41039              this_1.context.memo('button.style.' + item, function () {
41040                  return _this.button({
41041                      className: 'note-btn-style-' + item,
41042                      contents: '<div data-value="' + item + '">' + item.toUpperCase() + '</div>',
41043                      tooltip: _this.lang.style[item],
41044                      click: _this.context.createInvokeHandler('editor.formatBlock')
41045                  }).render();
41046              });
41047          };
41048          var this_1 = this;
41049          for (var styleIdx = 0, styleLen = this.options.styleTags.length; styleIdx < styleLen; styleIdx++) {
41050              _loop_1(styleIdx, styleLen);
41051          }
41052          this.context.memo('button.bold', function () {
41053              return _this.button({
41054                  className: 'note-btn-bold',
41055                  contents: _this.ui.icon(_this.options.icons.bold),
41056                  tooltip: _this.lang.font.bold + _this.representShortcut('bold'),
41057                  click: _this.context.createInvokeHandlerAndUpdateState('editor.bold')
41058              }).render();
41059          });
41060          this.context.memo('button.italic', function () {
41061              return _this.button({
41062                  className: 'note-btn-italic',
41063                  contents: _this.ui.icon(_this.options.icons.italic),
41064                  tooltip: _this.lang.font.italic + _this.representShortcut('italic'),
41065                  click: _this.context.createInvokeHandlerAndUpdateState('editor.italic')
41066              }).render();
41067          });
41068          this.context.memo('button.underline', function () {
41069              return _this.button({
41070                  className: 'note-btn-underline',
41071                  contents: _this.ui.icon(_this.options.icons.underline),
41072                  tooltip: _this.lang.font.underline + _this.representShortcut('underline'),
41073                  click: _this.context.createInvokeHandlerAndUpdateState('editor.underline')
41074              }).render();
41075          });
41076          this.context.memo('button.clear', function () {
41077              return _this.button({
41078                  contents: _this.ui.icon(_this.options.icons.eraser),
41079                  tooltip: _this.lang.font.clear + _this.representShortcut('removeFormat'),
41080                  click: _this.context.createInvokeHandler('editor.removeFormat')
41081              }).render();
41082          });
41083          this.context.memo('button.strikethrough', function () {
41084              return _this.button({
41085                  className: 'note-btn-strikethrough',
41086                  contents: _this.ui.icon(_this.options.icons.strikethrough),
41087                  tooltip: _this.lang.font.strikethrough + _this.representShortcut('strikethrough'),
41088                  click: _this.context.createInvokeHandlerAndUpdateState('editor.strikethrough')
41089              }).render();
41090          });
41091          this.context.memo('button.superscript', function () {
41092              return _this.button({
41093                  className: 'note-btn-superscript',
41094                  contents: _this.ui.icon(_this.options.icons.superscript),
41095                  tooltip: _this.lang.font.superscript,
41096                  click: _this.context.createInvokeHandlerAndUpdateState('editor.superscript')
41097              }).render();
41098          });
41099          this.context.memo('button.subscript', function () {
41100              return _this.button({
41101                  className: 'note-btn-subscript',
41102                  contents: _this.ui.icon(_this.options.icons.subscript),
41103                  tooltip: _this.lang.font.subscript,
41104                  click: _this.context.createInvokeHandlerAndUpdateState('editor.subscript')
41105              }).render();
41106          });
41107          this.context.memo('button.fontname', function () {
41108              var styleInfo = _this.context.invoke('editor.currentStyle');
41109              // Add 'default' fonts into the fontnames array if not exist
41110              $$1.each(styleInfo['font-family'].split(','), function (idx, fontname) {
41111                  fontname = fontname.trim().replace(/['"]+/g, '');
41112                  if (_this.isFontDeservedToAdd(fontname)) {
41113                      if ($$1.inArray(fontname, _this.options.fontNames) === -1) {
41114                          _this.options.fontNames.push(fontname);
41115                      }
41116                  }
41117              });
41118              return _this.ui.buttonGroup([
41119                  _this.button({
41120                      className: 'dropdown-toggle',
41121                      contents: _this.ui.dropdownButtonContents('<span class="note-current-fontname"/>', _this.options),
41122                      tooltip: _this.lang.font.name,
41123                      data: {
41124                          toggle: 'dropdown'
41125                      }
41126                  }),
41127                  _this.ui.dropdownCheck({
41128                      className: 'dropdown-fontname',
41129                      checkClassName: _this.options.icons.menuCheck,
41130                      items: _this.options.fontNames.filter(_this.isFontInstalled.bind(_this)),
41131                      title: _this.lang.font.name,
41132                      template: function (item) {
41133                          return '<span style="font-family: \'' + item + '\'">' + item + '</span>';
41134                      },
41135                      click: _this.context.createInvokeHandlerAndUpdateState('editor.fontName')
41136                  })
41137              ]).render();
41138          });
41139          this.context.memo('button.fontsize', function () {
41140              return _this.ui.buttonGroup([
41141                  _this.button({
41142                      className: 'dropdown-toggle',
41143                      contents: _this.ui.dropdownButtonContents('<span class="note-current-fontsize"/>', _this.options),
41144                      tooltip: _this.lang.font.size,
41145                      data: {
41146                          toggle: 'dropdown'
41147                      }
41148                  }),
41149                  _this.ui.dropdownCheck({
41150                      className: 'dropdown-fontsize',
41151                      checkClassName: _this.options.icons.menuCheck,
41152                      items: _this.options.fontSizes,
41153                      title: _this.lang.font.size,
41154                      click: _this.context.createInvokeHandlerAndUpdateState('editor.fontSize')
41155                  })
41156              ]).render();
41157          });
41158          this.context.memo('button.color', function () {
41159              return _this.colorPalette('note-color-all', _this.lang.color.recent, true, true);
41160          });
41161          this.context.memo('button.forecolor', function () {
41162              return _this.colorPalette('note-color-fore', _this.lang.color.foreground, false, true);
41163          });
41164          this.context.memo('button.backcolor', function () {
41165              return _this.colorPalette('note-color-back', _this.lang.color.background, true, false);
41166          });
41167          this.context.memo('button.ul', function () {
41168              return _this.button({
41169                  contents: _this.ui.icon(_this.options.icons.unorderedlist),
41170                  tooltip: _this.lang.lists.unordered + _this.representShortcut('insertUnorderedList'),
41171                  click: _this.context.createInvokeHandler('editor.insertUnorderedList')
41172              }).render();
41173          });
41174          this.context.memo('button.ol', function () {
41175              return _this.button({
41176                  contents: _this.ui.icon(_this.options.icons.orderedlist),
41177                  tooltip: _this.lang.lists.ordered + _this.representShortcut('insertOrderedList'),
41178                  click: _this.context.createInvokeHandler('editor.insertOrderedList')
41179              }).render();
41180          });
41181          var justifyLeft = this.button({
41182              contents: this.ui.icon(this.options.icons.alignLeft),
41183              tooltip: this.lang.paragraph.left + this.representShortcut('justifyLeft'),
41184              click: this.context.createInvokeHandler('editor.justifyLeft')
41185          });
41186          var justifyCenter = this.button({
41187              contents: this.ui.icon(this.options.icons.alignCenter),
41188              tooltip: this.lang.paragraph.center + this.representShortcut('justifyCenter'),
41189              click: this.context.createInvokeHandler('editor.justifyCenter')
41190          });
41191          var justifyRight = this.button({
41192              contents: this.ui.icon(this.options.icons.alignRight),
41193              tooltip: this.lang.paragraph.right + this.representShortcut('justifyRight'),
41194              click: this.context.createInvokeHandler('editor.justifyRight')
41195          });
41196          var justifyFull = this.button({
41197              contents: this.ui.icon(this.options.icons.alignJustify),
41198              tooltip: this.lang.paragraph.justify + this.representShortcut('justifyFull'),
41199              click: this.context.createInvokeHandler('editor.justifyFull')
41200          });
41201          var outdent = this.button({
41202              contents: this.ui.icon(this.options.icons.outdent),
41203              tooltip: this.lang.paragraph.outdent + this.representShortcut('outdent'),
41204              click: this.context.createInvokeHandler('editor.outdent')
41205          });
41206          var indent = this.button({
41207              contents: this.ui.icon(this.options.icons.indent),
41208              tooltip: this.lang.paragraph.indent + this.representShortcut('indent'),
41209              click: this.context.createInvokeHandler('editor.indent')
41210          });
41211          this.context.memo('button.justifyLeft', func.invoke(justifyLeft, 'render'));
41212          this.context.memo('button.justifyCenter', func.invoke(justifyCenter, 'render'));
41213          this.context.memo('button.justifyRight', func.invoke(justifyRight, 'render'));
41214          this.context.memo('button.justifyFull', func.invoke(justifyFull, 'render'));
41215          this.context.memo('button.outdent', func.invoke(outdent, 'render'));
41216          this.context.memo('button.indent', func.invoke(indent, 'render'));
41217          this.context.memo('button.paragraph', function () {
41218              return _this.ui.buttonGroup([
41219                  _this.button({
41220                      className: 'dropdown-toggle',
41221                      contents: _this.ui.dropdownButtonContents(_this.ui.icon(_this.options.icons.alignLeft), _this.options),
41222                      tooltip: _this.lang.paragraph.paragraph,
41223                      data: {
41224                          toggle: 'dropdown'
41225                      }
41226                  }),
41227                  _this.ui.dropdown([
41228                      _this.ui.buttonGroup({
41229                          className: 'note-align',
41230                          children: [justifyLeft, justifyCenter, justifyRight, justifyFull]
41231                      }),
41232                      _this.ui.buttonGroup({
41233                          className: 'note-list',
41234                          children: [outdent, indent]
41235                      })
41236                  ])
41237              ]).render();
41238          });
41239          this.context.memo('button.height', function () {
41240              return _this.ui.buttonGroup([
41241                  _this.button({
41242                      className: 'dropdown-toggle',
41243                      contents: _this.ui.dropdownButtonContents(_this.ui.icon(_this.options.icons.textHeight), _this.options),
41244                      tooltip: _this.lang.font.height,
41245                      data: {
41246                          toggle: 'dropdown'
41247                      }
41248                  }),
41249                  _this.ui.dropdownCheck({
41250                      items: _this.options.lineHeights,
41251                      checkClassName: _this.options.icons.menuCheck,
41252                      className: 'dropdown-line-height',
41253                      title: _this.lang.font.height,
41254                      click: _this.context.createInvokeHandler('editor.lineHeight')
41255                  })
41256              ]).render();
41257          });
41258          this.context.memo('button.table', function () {
41259              return _this.ui.buttonGroup([
41260                  _this.button({
41261                      className: 'dropdown-toggle',
41262                      contents: _this.ui.dropdownButtonContents(_this.ui.icon(_this.options.icons.table), _this.options),
41263                      tooltip: _this.lang.table.table,
41264                      data: {
41265                          toggle: 'dropdown'
41266                      }
41267                  }),
41268                  _this.ui.dropdown({
41269                      title: _this.lang.table.table,
41270                      className: 'note-table',
41271                      items: [
41272                          '<div class="note-dimension-picker">',
41273                          '  <div class="note-dimension-picker-mousecatcher" data-event="insertTable" data-value="1x1"/>',
41274                          '  <div class="note-dimension-picker-highlighted"/>',
41275                          '  <div class="note-dimension-picker-unhighlighted"/>',
41276                          '</div>',
41277                          '<div class="note-dimension-display">1 x 1</div>'
41278                      ].join('')
41279                  })
41280              ], {
41281                  callback: function ($node) {
41282                      var $catcher = $node.find('.note-dimension-picker-mousecatcher');
41283                      $catcher.css({
41284                          width: _this.options.insertTableMaxSize.col + 'em',
41285                          height: _this.options.insertTableMaxSize.row + 'em'
41286                      }).mousedown(_this.context.createInvokeHandler('editor.insertTable'))
41287                          .on('mousemove', _this.tableMoveHandler.bind(_this));
41288                  }
41289              }).render();
41290          });
41291          this.context.memo('button.link', function () {
41292              return _this.button({
41293                  contents: _this.ui.icon(_this.options.icons.link),
41294                  tooltip: _this.lang.link.link + _this.representShortcut('linkDialog.show'),
41295                  click: _this.context.createInvokeHandler('linkDialog.show')
41296              }).render();
41297          });
41298          this.context.memo('button.picture', function () {
41299              return _this.button({
41300                  contents: _this.ui.icon(_this.options.icons.picture),
41301                  tooltip: _this.lang.image.image,
41302                  click: _this.context.createInvokeHandler('imageDialog.show')
41303              }).render();
41304          });
41305          this.context.memo('button.video', function () {
41306              return _this.button({
41307                  contents: _this.ui.icon(_this.options.icons.video),
41308                  tooltip: _this.lang.video.video,
41309                  click: _this.context.createInvokeHandler('videoDialog.show')
41310              }).render();
41311          });
41312          this.context.memo('button.hr', function () {
41313              return _this.button({
41314                  contents: _this.ui.icon(_this.options.icons.minus),
41315                  tooltip: _this.lang.hr.insert + _this.representShortcut('insertHorizontalRule'),
41316                  click: _this.context.createInvokeHandler('editor.insertHorizontalRule')
41317              }).render();
41318          });
41319          this.context.memo('button.fullscreen', function () {
41320              return _this.button({
41321                  className: 'btn-fullscreen',
41322                  contents: _this.ui.icon(_this.options.icons.arrowsAlt),
41323                  tooltip: _this.lang.options.fullscreen,
41324                  click: _this.context.createInvokeHandler('fullscreen.toggle')
41325              }).render();
41326          });
41327          this.context.memo('button.codeview', function () {
41328              return _this.button({
41329                  className: 'btn-codeview',
41330                  contents: _this.ui.icon(_this.options.icons.code),
41331                  tooltip: _this.lang.options.codeview,
41332                  click: _this.context.createInvokeHandler('codeview.toggle')
41333              }).render();
41334          });
41335          this.context.memo('button.redo', function () {
41336              return _this.button({
41337                  contents: _this.ui.icon(_this.options.icons.redo),
41338                  tooltip: _this.lang.history.redo + _this.representShortcut('redo'),
41339                  click: _this.context.createInvokeHandler('editor.redo')
41340              }).render();
41341          });
41342          this.context.memo('button.undo', function () {
41343              return _this.button({
41344                  contents: _this.ui.icon(_this.options.icons.undo),
41345                  tooltip: _this.lang.history.undo + _this.representShortcut('undo'),
41346                  click: _this.context.createInvokeHandler('editor.undo')
41347              }).render();
41348          });
41349          this.context.memo('button.help', function () {
41350              return _this.button({
41351                  contents: _this.ui.icon(_this.options.icons.question),
41352                  tooltip: _this.lang.options.help,
41353                  click: _this.context.createInvokeHandler('helpDialog.show')
41354              }).render();
41355          });
41356      };
41357      /**
41358       * image : [
41359       *   ['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']],
41360       *   ['float', ['floatLeft', 'floatRight', 'floatNone' ]],
41361       *   ['remove', ['removeMedia']]
41362       * ],
41363       */
41364      Buttons.prototype.addImagePopoverButtons = function () {
41365          var _this = this;
41366          // Image Size Buttons
41367          this.context.memo('button.imageSize100', function () {
41368              return _this.button({
41369                  contents: '<span class="note-fontsize-10">100%</span>',
41370                  tooltip: _this.lang.image.resizeFull,
41371                  click: _this.context.createInvokeHandler('editor.resize', '1')
41372              }).render();
41373          });
41374          this.context.memo('button.imageSize50', function () {
41375              return _this.button({
41376                  contents: '<span class="note-fontsize-10">50%</span>',
41377                  tooltip: _this.lang.image.resizeHalf,
41378                  click: _this.context.createInvokeHandler('editor.resize', '0.5')
41379              }).render();
41380          });
41381          this.context.memo('button.imageSize25', function () {
41382              return _this.button({
41383                  contents: '<span class="note-fontsize-10">25%</span>',
41384                  tooltip: _this.lang.image.resizeQuarter,
41385                  click: _this.context.createInvokeHandler('editor.resize', '0.25')
41386              }).render();
41387          });
41388          // Float Buttons
41389          this.context.memo('button.floatLeft', function () {
41390              return _this.button({
41391                  contents: _this.ui.icon(_this.options.icons.alignLeft),
41392                  tooltip: _this.lang.image.floatLeft,
41393                  click: _this.context.createInvokeHandler('editor.floatMe', 'left')
41394              }).render();
41395          });
41396          this.context.memo('button.floatRight', function () {
41397              return _this.button({
41398                  contents: _this.ui.icon(_this.options.icons.alignRight),
41399                  tooltip: _this.lang.image.floatRight,
41400                  click: _this.context.createInvokeHandler('editor.floatMe', 'right')
41401              }).render();
41402          });
41403          this.context.memo('button.floatNone', function () {
41404              return _this.button({
41405                  contents: _this.ui.icon(_this.options.icons.alignJustify),
41406                  tooltip: _this.lang.image.floatNone,
41407                  click: _this.context.createInvokeHandler('editor.floatMe', 'none')
41408              }).render();
41409          });
41410          // Remove Buttons
41411          this.context.memo('button.removeMedia', function () {
41412              return _this.button({
41413                  contents: _this.ui.icon(_this.options.icons.trash),
41414                  tooltip: _this.lang.image.remove,
41415                  click: _this.context.createInvokeHandler('editor.removeMedia')
41416              }).render();
41417          });
41418      };
41419      Buttons.prototype.addLinkPopoverButtons = function () {
41420          var _this = this;
41421          this.context.memo('button.linkDialogShow', function () {
41422              return _this.button({
41423                  contents: _this.ui.icon(_this.options.icons.link),
41424                  tooltip: _this.lang.link.edit,
41425                  click: _this.context.createInvokeHandler('linkDialog.show')
41426              }).render();
41427          });
41428          this.context.memo('button.unlink', function () {
41429              return _this.button({
41430                  contents: _this.ui.icon(_this.options.icons.unlink),
41431                  tooltip: _this.lang.link.unlink,
41432                  click: _this.context.createInvokeHandler('editor.unlink')
41433              }).render();
41434          });
41435      };
41436      /**
41437       * table : [
41438       *  ['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],
41439       *  ['delete', ['deleteRow', 'deleteCol', 'deleteTable']]
41440       * ],
41441       */
41442      Buttons.prototype.addTablePopoverButtons = function () {
41443          var _this = this;
41444          this.context.memo('button.addRowUp', function () {
41445              return _this.button({
41446                  className: 'btn-md',
41447                  contents: _this.ui.icon(_this.options.icons.rowAbove),
41448                  tooltip: _this.lang.table.addRowAbove,
41449                  click: _this.context.createInvokeHandler('editor.addRow', 'top')
41450              }).render();
41451          });
41452          this.context.memo('button.addRowDown', function () {
41453              return _this.button({
41454                  className: 'btn-md',
41455                  contents: _this.ui.icon(_this.options.icons.rowBelow),
41456                  tooltip: _this.lang.table.addRowBelow,
41457                  click: _this.context.createInvokeHandler('editor.addRow', 'bottom')
41458              }).render();
41459          });
41460          this.context.memo('button.addColLeft', function () {
41461              return _this.button({
41462                  className: 'btn-md',
41463                  contents: _this.ui.icon(_this.options.icons.colBefore),
41464                  tooltip: _this.lang.table.addColLeft,
41465                  click: _this.context.createInvokeHandler('editor.addCol', 'left')
41466              }).render();
41467          });
41468          this.context.memo('button.addColRight', function () {
41469              return _this.button({
41470                  className: 'btn-md',
41471                  contents: _this.ui.icon(_this.options.icons.colAfter),
41472                  tooltip: _this.lang.table.addColRight,
41473                  click: _this.context.createInvokeHandler('editor.addCol', 'right')
41474              }).render();
41475          });
41476          this.context.memo('button.deleteRow', function () {
41477              return _this.button({
41478                  className: 'btn-md',
41479                  contents: _this.ui.icon(_this.options.icons.rowRemove),
41480                  tooltip: _this.lang.table.delRow,
41481                  click: _this.context.createInvokeHandler('editor.deleteRow')
41482              }).render();
41483          });
41484          this.context.memo('button.deleteCol', function () {
41485              return _this.button({
41486                  className: 'btn-md',
41487                  contents: _this.ui.icon(_this.options.icons.colRemove),
41488                  tooltip: _this.lang.table.delCol,
41489                  click: _this.context.createInvokeHandler('editor.deleteCol')
41490              }).render();
41491          });
41492          this.context.memo('button.deleteTable', function () {
41493              return _this.button({
41494                  className: 'btn-md',
41495                  contents: _this.ui.icon(_this.options.icons.trash),
41496                  tooltip: _this.lang.table.delTable,
41497                  click: _this.context.createInvokeHandler('editor.deleteTable')
41498              }).render();
41499          });
41500      };
41501      Buttons.prototype.build = function ($container, groups) {
41502          for (var groupIdx = 0, groupLen = groups.length; groupIdx < groupLen; groupIdx++) {
41503              var group = groups[groupIdx];
41504              var groupName = $$1.isArray(group) ? group[0] : group;
41505              var buttons = $$1.isArray(group) ? ((group.length === 1) ? [group[0]] : group[1]) : [group];
41506              var $group = this.ui.buttonGroup({
41507                  className: 'note-' + groupName
41508              }).render();
41509              for (var idx = 0, len = buttons.length; idx < len; idx++) {
41510                  var btn = this.context.memo('button.' + buttons[idx]);
41511                  if (btn) {
41512                      $group.append(typeof btn === 'function' ? btn(this.context) : btn);
41513                  }
41514              }
41515              $group.appendTo($container);
41516          }
41517      };
41518      /**
41519       * @param {jQuery} [$container]
41520       */
41521      Buttons.prototype.updateCurrentStyle = function ($container) {
41522          var _this = this;
41523          var $cont = $container || this.$toolbar;
41524          var styleInfo = this.context.invoke('editor.currentStyle');
41525          this.updateBtnStates($cont, {
41526              '.note-btn-bold': function () {
41527                  return styleInfo['font-bold'] === 'bold';
41528              },
41529              '.note-btn-italic': function () {
41530                  return styleInfo['font-italic'] === 'italic';
41531              },
41532              '.note-btn-underline': function () {
41533                  return styleInfo['font-underline'] === 'underline';
41534              },
41535              '.note-btn-subscript': function () {
41536                  return styleInfo['font-subscript'] === 'subscript';
41537              },
41538              '.note-btn-superscript': function () {
41539                  return styleInfo['font-superscript'] === 'superscript';
41540              },
41541              '.note-btn-strikethrough': function () {
41542                  return styleInfo['font-strikethrough'] === 'strikethrough';
41543              }
41544          });
41545          if (styleInfo['font-family']) {
41546              var fontNames = styleInfo['font-family'].split(',').map(function (name) {
41547                  return name.replace(/[\'\"]/g, '')
41548                      .replace(/\s+$/, '')
41549                      .replace(/^\s+/, '');
41550              });
41551              var fontName_1 = lists.find(fontNames, this.isFontInstalled.bind(this));
41552              $cont.find('.dropdown-fontname a').each(function (idx, item) {
41553                  var $item = $$1(item);
41554                  // always compare string to avoid creating another func.
41555                  var isChecked = ($item.data('value') + '') === (fontName_1 + '');
41556                  $item.toggleClass('checked', isChecked);
41557              });
41558              $cont.find('.note-current-fontname').text(fontName_1).css('font-family', fontName_1);
41559          }
41560          if (styleInfo['font-size']) {
41561              var fontSize_1 = styleInfo['font-size'];
41562              $cont.find('.dropdown-fontsize a').each(function (idx, item) {
41563                  var $item = $$1(item);
41564                  // always compare with string to avoid creating another func.
41565                  var isChecked = ($item.data('value') + '') === (fontSize_1 + '');
41566                  $item.toggleClass('checked', isChecked);
41567              });
41568              $cont.find('.note-current-fontsize').text(fontSize_1);
41569          }
41570          if (styleInfo['line-height']) {
41571              var lineHeight_1 = styleInfo['line-height'];
41572              $cont.find('.dropdown-line-height li a').each(function (idx, item) {
41573                  // always compare with string to avoid creating another func.
41574                  var isChecked = ($$1(item).data('value') + '') === (lineHeight_1 + '');
41575                  _this.className = isChecked ? 'checked' : '';
41576              });
41577          }
41578      };
41579      Buttons.prototype.updateBtnStates = function ($container, infos) {
41580          var _this = this;
41581          $$1.each(infos, function (selector, pred) {
41582              _this.ui.toggleBtnActive($container.find(selector), pred());
41583          });
41584      };
41585      Buttons.prototype.tableMoveHandler = function (event) {
41586          var PX_PER_EM = 18;
41587          var $picker = $$1(event.target.parentNode); // target is mousecatcher
41588          var $dimensionDisplay = $picker.next();
41589          var $catcher = $picker.find('.note-dimension-picker-mousecatcher');
41590          var $highlighted = $picker.find('.note-dimension-picker-highlighted');
41591          var $unhighlighted = $picker.find('.note-dimension-picker-unhighlighted');
41592          var posOffset;
41593          // HTML5 with jQuery - e.offsetX is undefined in Firefox
41594          if (event.offsetX === undefined) {
41595              var posCatcher = $$1(event.target).offset();
41596              posOffset = {
41597                  x: event.pageX - posCatcher.left,
41598                  y: event.pageY - posCatcher.top
41599              };
41600          }
41601          else {
41602              posOffset = {
41603                  x: event.offsetX,
41604                  y: event.offsetY
41605              };
41606          }
41607          var dim = {
41608              c: Math.ceil(posOffset.x / PX_PER_EM) || 1,
41609              r: Math.ceil(posOffset.y / PX_PER_EM) || 1
41610          };
41611          $highlighted.css({ width: dim.c + 'em', height: dim.r + 'em' });
41612          $catcher.data('value', dim.c + 'x' + dim.r);
41613          if (dim.c > 3 && dim.c < this.options.insertTableMaxSize.col) {
41614              $unhighlighted.css({ width: dim.c + 1 + 'em' });
41615          }
41616          if (dim.r > 3 && dim.r < this.options.insertTableMaxSize.row) {
41617              $unhighlighted.css({ height: dim.r + 1 + 'em' });
41618          }
41619          $dimensionDisplay.html(dim.c + ' x ' + dim.r);
41620      };
41621      return Buttons;
41622  }());
41623
41624  var Toolbar = /** @class */ (function () {
41625      function Toolbar(context) {
41626          this.context = context;
41627          this.$window = $$1(window);
41628          this.$document = $$1(document);
41629          this.ui = $$1.summernote.ui;
41630          this.$note = context.layoutInfo.note;
41631          this.$editor = context.layoutInfo.editor;
41632          this.$toolbar = context.layoutInfo.toolbar;
41633          this.options = context.options;
41634          this.followScroll = this.followScroll.bind(this);
41635      }
41636      Toolbar.prototype.shouldInitialize = function () {
41637          return !this.options.airMode;
41638      };
41639      Toolbar.prototype.initialize = function () {
41640          var _this = this;
41641          this.options.toolbar = this.options.toolbar || [];
41642          if (!this.options.toolbar.length) {
41643              this.$toolbar.hide();
41644          }
41645          else {
41646              this.context.invoke('buttons.build', this.$toolbar, this.options.toolbar);
41647          }
41648          if (this.options.toolbarContainer) {
41649              this.$toolbar.appendTo(this.options.toolbarContainer);
41650          }
41651          this.changeContainer(false);
41652          this.$note.on('summernote.keyup summernote.mouseup summernote.change', function () {
41653              _this.context.invoke('buttons.updateCurrentStyle');
41654          });
41655          this.context.invoke('buttons.updateCurrentStyle');
41656          if (this.options.followingToolbar) {
41657              this.$window.on('scroll resize', this.followScroll);
41658          }
41659      };
41660      Toolbar.prototype.destroy = function () {
41661          this.$toolbar.children().remove();
41662          if (this.options.followingToolbar) {
41663              this.$window.off('scroll resize', this.followScroll);
41664          }
41665      };
41666      Toolbar.prototype.followScroll = function () {
41667          if (this.$editor.hasClass('fullscreen')) {
41668              return false;
41669          }
41670          var $toolbarWrapper = this.$toolbar.parent('.note-toolbar-wrapper');
41671          var editorHeight = this.$editor.outerHeight();
41672          var editorWidth = this.$editor.width();
41673          var toolbarHeight = this.$toolbar.height();
41674          $toolbarWrapper.css({
41675              height: toolbarHeight
41676          });
41677          // check if the web app is currently using another static bar
41678          var otherBarHeight = 0;
41679          if (this.options.otherStaticBar) {
41680              otherBarHeight = $$1(this.options.otherStaticBar).outerHeight();
41681          }
41682          var currentOffset = this.$document.scrollTop();
41683          var editorOffsetTop = this.$editor.offset().top;
41684          var editorOffsetBottom = editorOffsetTop + editorHeight;
41685          var activateOffset = editorOffsetTop - otherBarHeight;
41686          var deactivateOffsetBottom = editorOffsetBottom - otherBarHeight - toolbarHeight;
41687          if ((currentOffset > activateOffset) && (currentOffset < deactivateOffsetBottom)) {
41688              this.$toolbar.css({
41689                  position: 'fixed',
41690                  top: otherBarHeight,
41691                  width: editorWidth
41692              });
41693          }
41694          else {
41695              this.$toolbar.css({
41696                  position: 'relative',
41697                  top: 0,
41698                  width: '100%'
41699              });
41700          }
41701      };
41702      Toolbar.prototype.changeContainer = function (isFullscreen) {
41703          if (isFullscreen) {
41704              this.$toolbar.prependTo(this.$editor);
41705          }
41706          else {
41707              if (this.options.toolbarContainer) {
41708                  this.$toolbar.appendTo(this.options.toolbarContainer);
41709              }
41710          }
41711      };
41712      Toolbar.prototype.updateFullscreen = function (isFullscreen) {
41713          this.ui.toggleBtnActive(this.$toolbar.find('.btn-fullscreen'), isFullscreen);
41714          this.changeContainer(isFullscreen);
41715      };
41716      Toolbar.prototype.updateCodeview = function (isCodeview) {
41717          this.ui.toggleBtnActive(this.$toolbar.find('.btn-codeview'), isCodeview);
41718          if (isCodeview) {
41719              this.deactivate();
41720          }
41721          else {
41722              this.activate();
41723          }
41724      };
41725      Toolbar.prototype.activate = function (isIncludeCodeview) {
41726          var $btn = this.$toolbar.find('button');
41727          if (!isIncludeCodeview) {
41728              $btn = $btn.not('.btn-codeview');
41729          }
41730          this.ui.toggleBtn($btn, true);
41731      };
41732      Toolbar.prototype.deactivate = function (isIncludeCodeview) {
41733          var $btn = this.$toolbar.find('button');
41734          if (!isIncludeCodeview) {
41735              $btn = $btn.not('.btn-codeview');
41736          }
41737          this.ui.toggleBtn($btn, false);
41738      };
41739      return Toolbar;
41740  }());
41741
41742  var LinkDialog = /** @class */ (function () {
41743      function LinkDialog(context) {
41744          this.context = context;
41745          this.ui = $$1.summernote.ui;
41746          this.$body = $$1(document.body);
41747          this.$editor = context.layoutInfo.editor;
41748          this.options = context.options;
41749          this.lang = this.options.langInfo;
41750          context.memo('help.linkDialog.show', this.options.langInfo.help['linkDialog.show']);
41751      }
41752      LinkDialog.prototype.initialize = function () {
41753          var $container = this.options.dialogsInBody ? this.$body : this.$editor;
41754          var body = [
41755              '<div class="form-group note-form-group">',
41756              "<label class=\"note-form-label\">" + this.lang.link.textToDisplay + "</label>",
41757              '<input class="note-link-text form-control note-form-control note-input" type="text" />',
41758              '</div>',
41759              '<div class="form-group note-form-group">',
41760              "<label class=\"note-form-label\">" + this.lang.link.url + "</label>",
41761              '<input class="note-link-url form-control note-form-control note-input" type="text" value="http://" />',
41762              '</div>',
41763              !this.options.disableLinkTarget
41764                  ? $$1('<div/>').append(this.ui.checkbox({
41765                      className: 'sn-checkbox-open-in-new-window',
41766                      text: this.lang.link.openInNewWindow,
41767                      checked: true
41768                  }).render()).html()
41769                  : ''
41770          ].join('');
41771          var buttonClass = 'btn btn-primary note-btn note-btn-primary note-link-btn';
41772          var footer = "<input type=\"button\" href=\"#\" class=\"" + buttonClass + "\" value=\"" + this.lang.link.insert + "\" disabled>";
41773          this.$dialog = this.ui.dialog({
41774              className: 'link-dialog',
41775              title: this.lang.link.insert,
41776              fade: this.options.dialogsFade,
41777              body: body,
41778              footer: footer
41779          }).render().appendTo($container);
41780      };
41781      LinkDialog.prototype.destroy = function () {
41782          this.ui.hideDialog(this.$dialog);
41783          this.$dialog.remove();
41784      };
41785      LinkDialog.prototype.bindEnterKey = function ($input, $btn) {
41786          $input.on('keypress', function (event) {
41787              if (event.keyCode === key.code.ENTER) {
41788                  event.preventDefault();
41789                  $btn.trigger('click');
41790              }
41791          });
41792      };
41793      /**
41794       * toggle update button
41795       */
41796      LinkDialog.prototype.toggleLinkBtn = function ($linkBtn, $linkText, $linkUrl) {
41797          this.ui.toggleBtn($linkBtn, $linkText.val() && $linkUrl.val());
41798      };
41799      /**
41800       * Show link dialog and set event handlers on dialog controls.
41801       *
41802       * @param {Object} linkInfo
41803       * @return {Promise}
41804       */
41805      LinkDialog.prototype.showLinkDialog = function (linkInfo) {
41806          var _this = this;
41807          return $$1.Deferred(function (deferred) {
41808              var $linkText = _this.$dialog.find('.note-link-text');
41809              var $linkUrl = _this.$dialog.find('.note-link-url');
41810              var $linkBtn = _this.$dialog.find('.note-link-btn');
41811              var $openInNewWindow = _this.$dialog
41812                  .find('.sn-checkbox-open-in-new-window input[type=checkbox]');
41813              _this.ui.onDialogShown(_this.$dialog, function () {
41814                  _this.context.triggerEvent('dialog.shown');
41815                  // if no url was given, copy text to url
41816                  if (!linkInfo.url) {
41817                      linkInfo.url = linkInfo.text;
41818                  }
41819                  $linkText.val(linkInfo.text);
41820                  var handleLinkTextUpdate = function () {
41821                      _this.toggleLinkBtn($linkBtn, $linkText, $linkUrl);
41822                      // if linktext was modified by keyup,
41823                      // stop cloning text from linkUrl
41824                      linkInfo.text = $linkText.val();
41825                  };
41826                  $linkText.on('input', handleLinkTextUpdate).on('paste', function () {
41827                      setTimeout(handleLinkTextUpdate, 0);
41828                  });
41829                  var handleLinkUrlUpdate = function () {
41830                      _this.toggleLinkBtn($linkBtn, $linkText, $linkUrl);
41831                      // display same link on `Text to display` input
41832                      // when create a new link
41833                      if (!linkInfo.text) {
41834                          $linkText.val($linkUrl.val());
41835                      }
41836                  };
41837                  $linkUrl.on('input', handleLinkUrlUpdate).on('paste', function () {
41838                      setTimeout(handleLinkUrlUpdate, 0);
41839                  }).val(linkInfo.url);
41840                  if (!env.isSupportTouch) {
41841                      $linkUrl.trigger('focus');
41842                  }
41843                  _this.toggleLinkBtn($linkBtn, $linkText, $linkUrl);
41844                  _this.bindEnterKey($linkUrl, $linkBtn);
41845                  _this.bindEnterKey($linkText, $linkBtn);
41846                  var isNewWindowChecked = linkInfo.isNewWindow !== undefined
41847                      ? linkInfo.isNewWindow : _this.context.options.linkTargetBlank;
41848                  $openInNewWindow.prop('checked', isNewWindowChecked);
41849                  $linkBtn.one('click', function (event) {
41850                      event.preventDefault();
41851                      deferred.resolve({
41852                          range: linkInfo.range,
41853                          url: $linkUrl.val(),
41854                          text: $linkText.val(),
41855                          isNewWindow: $openInNewWindow.is(':checked')
41856                      });
41857                      _this.ui.hideDialog(_this.$dialog);
41858                  });
41859              });
41860              _this.ui.onDialogHidden(_this.$dialog, function () {
41861                  // detach events
41862                  $linkText.off('input paste keypress');
41863                  $linkUrl.off('input paste keypress');
41864                  $linkBtn.off('click');
41865                  if (deferred.state() === 'pending') {
41866                      deferred.reject();
41867                  }
41868              });
41869              _this.ui.showDialog(_this.$dialog);
41870          }).promise();
41871      };
41872      /**
41873       * @param {Object} layoutInfo
41874       */
41875      LinkDialog.prototype.show = function () {
41876          var _this = this;
41877          var linkInfo = this.context.invoke('editor.getLinkInfo');
41878          this.context.invoke('editor.saveRange');
41879          this.showLinkDialog(linkInfo).then(function (linkInfo) {
41880              _this.context.invoke('editor.restoreRange');
41881              _this.context.invoke('editor.createLink', linkInfo);
41882          }).fail(function () {
41883              _this.context.invoke('editor.restoreRange');
41884          });
41885      };
41886      return LinkDialog;
41887  }());
41888
41889  var LinkPopover = /** @class */ (function () {
41890      function LinkPopover(context) {
41891          var _this = this;
41892          this.context = context;
41893          this.ui = $$1.summernote.ui;
41894          this.options = context.options;
41895          this.events = {
41896              'summernote.keyup summernote.mouseup summernote.change summernote.scroll': function () {
41897                  _this.update();
41898              },
41899              'summernote.disable summernote.dialog.shown': function () {
41900                  _this.hide();
41901              }
41902          };
41903      }
41904      LinkPopover.prototype.shouldInitialize = function () {
41905          return !lists.isEmpty(this.options.popover.link);
41906      };
41907      LinkPopover.prototype.initialize = function () {
41908          this.$popover = this.ui.popover({
41909              className: 'note-link-popover',
41910              callback: function ($node) {
41911                  var $content = $node.find('.popover-content,.note-popover-content');
41912                  $content.prepend('<span><a target="_blank"></a>&nbsp;</span>');
41913              }
41914          }).render().appendTo(this.options.container);
41915          var $content = this.$popover.find('.popover-content,.note-popover-content');
41916          this.context.invoke('buttons.build', $content, this.options.popover.link);
41917      };
41918      LinkPopover.prototype.destroy = function () {
41919          this.$popover.remove();
41920      };
41921      LinkPopover.prototype.update = function () {
41922          // Prevent focusing on editable when invoke('code') is executed
41923          if (!this.context.invoke('editor.hasFocus')) {
41924              this.hide();
41925              return;
41926          }
41927          var rng = this.context.invoke('editor.createRange');
41928          if (rng.isCollapsed() && rng.isOnAnchor()) {
41929              var anchor = dom.ancestor(rng.sc, dom.isAnchor);
41930              var href = $$1(anchor).attr('href');
41931              this.$popover.find('a').attr('href', href).html(href);
41932              var pos = dom.posFromPlaceholder(anchor);
41933              this.$popover.css({
41934                  display: 'block',
41935                  left: pos.left,
41936                  top: pos.top
41937              });
41938          }
41939          else {
41940              this.hide();
41941          }
41942      };
41943      LinkPopover.prototype.hide = function () {
41944          this.$popover.hide();
41945      };
41946      return LinkPopover;
41947  }());
41948
41949  var ImageDialog = /** @class */ (function () {
41950      function ImageDialog(context) {
41951          this.context = context;
41952          this.ui = $$1.summernote.ui;
41953          this.$body = $$1(document.body);
41954          this.$editor = context.layoutInfo.editor;
41955          this.options = context.options;
41956          this.lang = this.options.langInfo;
41957      }
41958      ImageDialog.prototype.initialize = function () {
41959          var $container = this.options.dialogsInBody ? this.$body : this.$editor;
41960          var imageLimitation = '';
41961          if (this.options.maximumImageFileSize) {
41962              var unit = Math.floor(Math.log(this.options.maximumImageFileSize) / Math.log(1024));
41963              var readableSize = (this.options.maximumImageFileSize / Math.pow(1024, unit)).toFixed(2) * 1 +
41964                  ' ' + ' KMGTP'[unit] + 'B';
41965              imageLimitation = "<small>" + (this.lang.image.maximumFileSize + ' : ' + readableSize) + "</small>";
41966          }
41967          var body = [
41968              '<div class="form-group note-form-group note-group-select-from-files">',
41969              '<label class="note-form-label">' + this.lang.image.selectFromFiles + '</label>',
41970              '<input class="note-image-input note-form-control note-input" ',
41971              ' type="file" name="files" accept="image/*" multiple="multiple" />',
41972              imageLimitation,
41973              '</div>',
41974              '<div class="form-group note-group-image-url" style="overflow:auto;">',
41975              '<label class="note-form-label">' + this.lang.image.url + '</label>',
41976              '<input class="note-image-url form-control note-form-control note-input ',
41977              ' col-md-12" type="text" />',
41978              '</div>'
41979          ].join('');
41980          var buttonClass = 'btn btn-primary note-btn note-btn-primary note-image-btn';
41981          var footer = "<input type=\"button\" href=\"#\" class=\"" + buttonClass + "\" value=\"" + this.lang.image.insert + "\" disabled>";
41982          this.$dialog = this.ui.dialog({
41983              title: this.lang.image.insert,
41984              fade: this.options.dialogsFade,
41985              body: body,
41986              footer: footer
41987          }).render().appendTo($container);
41988      };
41989      ImageDialog.prototype.destroy = function () {
41990          this.ui.hideDialog(this.$dialog);
41991          this.$dialog.remove();
41992      };
41993      ImageDialog.prototype.bindEnterKey = function ($input, $btn) {
41994          $input.on('keypress', function (event) {
41995              if (event.keyCode === key.code.ENTER) {
41996                  event.preventDefault();
41997                  $btn.trigger('click');
41998              }
41999          });
42000      };
42001      ImageDialog.prototype.show = function () {
42002          var _this = this;
42003          this.context.invoke('editor.saveRange');
42004          this.showImageDialog().then(function (data) {
42005              // [workaround] hide dialog before restore range for IE range focus
42006              _this.ui.hideDialog(_this.$dialog);
42007              _this.context.invoke('editor.restoreRange');
42008              if (typeof data === 'string') { // image url
42009                  // If onImageLinkInsert set,
42010                  if (_this.options.callbacks.onImageLinkInsert) {
42011                      _this.context.triggerEvent('image.link.insert', data);
42012                  }
42013                  else {
42014                      _this.context.invoke('editor.insertImage', data);
42015                  }
42016              }
42017              else { // array of files
42018                  // If onImageUpload set,
42019                  if (_this.options.callbacks.onImageUpload) {
42020                      _this.context.triggerEvent('image.upload', data);
42021                  }
42022                  else {
42023                      // else insert Image as dataURL
42024                      _this.context.invoke('editor.insertImagesAsDataURL', data);
42025                  }
42026              }
42027          }).fail(function () {
42028              _this.context.invoke('editor.restoreRange');
42029          });
42030      };
42031      /**
42032       * show image dialog
42033       *
42034       * @param {jQuery} $dialog
42035       * @return {Promise}
42036       */
42037      ImageDialog.prototype.showImageDialog = function () {
42038          var _this = this;
42039          return $$1.Deferred(function (deferred) {
42040              var $imageInput = _this.$dialog.find('.note-image-input');
42041              var $imageUrl = _this.$dialog.find('.note-image-url');
42042              var $imageBtn = _this.$dialog.find('.note-image-btn');
42043              _this.ui.onDialogShown(_this.$dialog, function () {
42044                  _this.context.triggerEvent('dialog.shown');
42045                  // Cloning imageInput to clear element.
42046                  $imageInput.replaceWith($imageInput.clone().on('change', function (event) {
42047                      deferred.resolve(event.target.files || event.target.value);
42048                  }).val(''));
42049                  $imageBtn.click(function (event) {
42050                      event.preventDefault();
42051                      deferred.resolve($imageUrl.val());
42052                  });
42053                  $imageUrl.on('keyup paste', function () {
42054                      var url = $imageUrl.val();
42055                      _this.ui.toggleBtn($imageBtn, url);
42056                  }).val('');
42057                  if (!env.isSupportTouch) {
42058                      $imageUrl.trigger('focus');
42059                  }
42060                  _this.bindEnterKey($imageUrl, $imageBtn);
42061              });
42062              _this.ui.onDialogHidden(_this.$dialog, function () {
42063                  $imageInput.off('change');
42064                  $imageUrl.off('keyup paste keypress');
42065                  $imageBtn.off('click');
42066                  if (deferred.state() === 'pending') {
42067                      deferred.reject();
42068                  }
42069              });
42070              _this.ui.showDialog(_this.$dialog);
42071          });
42072      };
42073      return ImageDialog;
42074  }());
42075
42076  /**
42077   * Image popover module
42078   *  mouse events that show/hide popover will be handled by Handle.js.
42079   *  Handle.js will receive the events and invoke 'imagePopover.update'.
42080   */
42081  var ImagePopover = /** @class */ (function () {
42082      function ImagePopover(context) {
42083          var _this = this;
42084          this.context = context;
42085          this.ui = $$1.summernote.ui;
42086          this.editable = context.layoutInfo.editable[0];
42087          this.options = context.options;
42088          this.events = {
42089              'summernote.disable': function () {
42090                  _this.hide();
42091              }
42092          };
42093      }
42094      ImagePopover.prototype.shouldInitialize = function () {
42095          return !lists.isEmpty(this.options.popover.image);
42096      };
42097      ImagePopover.prototype.initialize = function () {
42098          this.$popover = this.ui.popover({
42099              className: 'note-image-popover'
42100          }).render().appendTo(this.options.container);
42101          var $content = this.$popover.find('.popover-content,.note-popover-content');
42102          this.context.invoke('buttons.build', $content, this.options.popover.image);
42103      };
42104      ImagePopover.prototype.destroy = function () {
42105          this.$popover.remove();
42106      };
42107      ImagePopover.prototype.update = function (target) {
42108          if (dom.isImg(target)) {
42109              var pos = dom.posFromPlaceholder(target);
42110              var posEditor = dom.posFromPlaceholder(this.editable);
42111              this.$popover.css({
42112                  display: 'block',
42113                  left: this.options.popatmouse ? event.pageX - 20 : pos.left,
42114                  top: this.options.popatmouse ? event.pageY : Math.min(pos.top, posEditor.top)
42115              });
42116          }
42117          else {
42118              this.hide();
42119          }
42120      };
42121      ImagePopover.prototype.hide = function () {
42122          this.$popover.hide();
42123      };
42124      return ImagePopover;
42125  }());
42126
42127  var TablePopover = /** @class */ (function () {
42128      function TablePopover(context) {
42129          var _this = this;
42130          this.context = context;
42131          this.ui = $$1.summernote.ui;
42132          this.options = context.options;
42133          this.events = {
42134              'summernote.mousedown': function (we, e) {
42135                  _this.update(e.target);
42136              },
42137              'summernote.keyup summernote.scroll summernote.change': function () {
42138                  _this.update();
42139              },
42140              'summernote.disable': function () {
42141                  _this.hide();
42142              }
42143          };
42144      }
42145      TablePopover.prototype.shouldInitialize = function () {
42146          return !lists.isEmpty(this.options.popover.table);
42147      };
42148      TablePopover.prototype.initialize = function () {
42149          this.$popover = this.ui.popover({
42150              className: 'note-table-popover'
42151          }).render().appendTo(this.options.container);
42152          var $content = this.$popover.find('.popover-content,.note-popover-content');
42153          this.context.invoke('buttons.build', $content, this.options.popover.table);
42154          // [workaround] Disable Firefox's default table editor
42155          if (env.isFF) {
42156              document.execCommand('enableInlineTableEditing', false, false);
42157          }
42158      };
42159      TablePopover.prototype.destroy = function () {
42160          this.$popover.remove();
42161      };
42162      TablePopover.prototype.update = function (target) {
42163          if (this.context.isDisabled()) {
42164              return false;
42165          }
42166          var isCell = dom.isCell(target);
42167          if (isCell) {
42168              var pos = dom.posFromPlaceholder(target);
42169              this.$popover.css({
42170                  display: 'block',
42171                  left: pos.left,
42172                  top: pos.top
42173              });
42174          }
42175          else {
42176              this.hide();
42177          }
42178          return isCell;
42179      };
42180      TablePopover.prototype.hide = function () {
42181          this.$popover.hide();
42182      };
42183      return TablePopover;
42184  }());
42185
42186  var VideoDialog = /** @class */ (function () {
42187      function VideoDialog(context) {
42188          this.context = context;
42189          this.ui = $$1.summernote.ui;
42190          this.$body = $$1(document.body);
42191          this.$editor = context.layoutInfo.editor;
42192          this.options = context.options;
42193          this.lang = this.options.langInfo;
42194      }
42195      VideoDialog.prototype.initialize = function () {
42196          var $container = this.options.dialogsInBody ? this.$body : this.$editor;
42197          var body = [
42198              '<div class="form-group note-form-group row-fluid">',
42199              "<label class=\"note-form-label\">" + this.lang.video.url + " <small class=\"text-muted\">" + this.lang.video.providers + "</small></label>",
42200              '<input class="note-video-url form-control note-form-control note-input" type="text" />',
42201              '</div>'
42202          ].join('');
42203          var buttonClass = 'btn btn-primary note-btn note-btn-primary note-video-btn';
42204          var footer = "<input type=\"button\" href=\"#\" class=\"" + buttonClass + "\" value=\"" + this.lang.video.insert + "\" disabled>";
42205          this.$dialog = this.ui.dialog({
42206              title: this.lang.video.insert,
42207              fade: this.options.dialogsFade,
42208              body: body,
42209              footer: footer
42210          }).render().appendTo($container);
42211      };
42212      VideoDialog.prototype.destroy = function () {
42213          this.ui.hideDialog(this.$dialog);
42214          this.$dialog.remove();
42215      };
42216      VideoDialog.prototype.bindEnterKey = function ($input, $btn) {
42217          $input.on('keypress', function (event) {
42218              if (event.keyCode === key.code.ENTER) {
42219                  event.preventDefault();
42220                  $btn.trigger('click');
42221              }
42222          });
42223      };
42224      VideoDialog.prototype.createVideoNode = function (url) {
42225          // video url patterns(youtube, instagram, vimeo, dailymotion, youku, mp4, ogg, webm)
42226          var ytRegExp = /\/\/(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))([\w|-]{11})(?:(?:[\?&]t=)(\S+))?$/;
42227          var ytRegExpForStart = /^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/;
42228          var ytMatch = url.match(ytRegExp);
42229          var igRegExp = /(?:www\.|\/\/)instagram\.com\/p\/(.[a-zA-Z0-9_-]*)/;
42230          var igMatch = url.match(igRegExp);
42231          var vRegExp = /\/\/vine\.co\/v\/([a-zA-Z0-9]+)/;
42232          var vMatch = url.match(vRegExp);
42233          var vimRegExp = /\/\/(player\.)?vimeo\.com\/([a-z]*\/)*(\d+)[?]?.*/;
42234          var vimMatch = url.match(vimRegExp);
42235          var dmRegExp = /.+dailymotion.com\/(video|hub)\/([^_]+)[^#]*(#video=([^_&]+))?/;
42236          var dmMatch = url.match(dmRegExp);
42237          var youkuRegExp = /\/\/v\.youku\.com\/v_show\/id_(\w+)=*\.html/;
42238          var youkuMatch = url.match(youkuRegExp);
42239          var qqRegExp = /\/\/v\.qq\.com.*?vid=(.+)/;
42240          var qqMatch = url.match(qqRegExp);
42241          var qqRegExp2 = /\/\/v\.qq\.com\/x?\/?(page|cover).*?\/([^\/]+)\.html\??.*/;
42242          var qqMatch2 = url.match(qqRegExp2);
42243          var mp4RegExp = /^.+.(mp4|m4v)$/;
42244          var mp4Match = url.match(mp4RegExp);
42245          var oggRegExp = /^.+.(ogg|ogv)$/;
42246          var oggMatch = url.match(oggRegExp);
42247          var webmRegExp = /^.+.(webm)$/;
42248          var webmMatch = url.match(webmRegExp);
42249          var $video;
42250          if (ytMatch && ytMatch[1].length === 11) {
42251              var youtubeId = ytMatch[1];
42252              var start = 0;
42253              if (typeof ytMatch[2] !== 'undefined') {
42254                  var ytMatchForStart = ytMatch[2].match(ytRegExpForStart);
42255                  if (ytMatchForStart) {
42256                      for (var n = [3600, 60, 1], i = 0, r = n.length; i < r; i++) {
42257                          start += (typeof ytMatchForStart[i + 1] !== 'undefined' ? n[i] * parseInt(ytMatchForStart[i + 1], 10) : 0);
42258                      }
42259                  }
42260              }
42261              $video = $$1('<iframe>')
42262                  .attr('frameborder', 0)
42263                  .attr('src', '//www.youtube.com/embed/' + youtubeId + (start > 0 ? '?start=' + start : ''))
42264                  .attr('width', '640').attr('height', '360');
42265          }
42266          else if (igMatch && igMatch[0].length) {
42267              $video = $$1('<iframe>')
42268                  .attr('frameborder', 0)
42269                  .attr('src', 'https://instagram.com/p/' + igMatch[1] + '/embed/')
42270                  .attr('width', '612').attr('height', '710')
42271                  .attr('scrolling', 'no')
42272                  .attr('allowtransparency', 'true');
42273          }
42274          else if (vMatch && vMatch[0].length) {
42275              $video = $$1('<iframe>')
42276                  .attr('frameborder', 0)
42277                  .attr('src', vMatch[0] + '/embed/simple')
42278                  .attr('width', '600').attr('height', '600')
42279                  .attr('class', 'vine-embed');
42280          }
42281          else if (vimMatch && vimMatch[3].length) {
42282              $video = $$1('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')
42283                  .attr('frameborder', 0)
42284                  .attr('src', '//player.vimeo.com/video/' + vimMatch[3])
42285                  .attr('width', '640').attr('height', '360');
42286          }
42287          else if (dmMatch && dmMatch[2].length) {
42288              $video = $$1('<iframe>')
42289                  .attr('frameborder', 0)
42290                  .attr('src', '//www.dailymotion.com/embed/video/' + dmMatch[2])
42291                  .attr('width', '640').attr('height', '360');
42292          }
42293          else if (youkuMatch && youkuMatch[1].length) {
42294              $video = $$1('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')
42295                  .attr('frameborder', 0)
42296                  .attr('height', '498')
42297                  .attr('width', '510')
42298                  .attr('src', '//player.youku.com/embed/' + youkuMatch[1]);
42299          }
42300          else if ((qqMatch && qqMatch[1].length) || (qqMatch2 && qqMatch2[2].length)) {
42301              var vid = ((qqMatch && qqMatch[1].length) ? qqMatch[1] : qqMatch2[2]);
42302              $video = $$1('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')
42303                  .attr('frameborder', 0)
42304                  .attr('height', '310')
42305                  .attr('width', '500')
42306                  .attr('src', 'http://v.qq.com/iframe/player.html?vid=' + vid + '&amp;auto=0');
42307          }
42308          else if (mp4Match || oggMatch || webmMatch) {
42309              $video = $$1('<video controls>')
42310                  .attr('src', url)
42311                  .attr('width', '640').attr('height', '360');
42312          }
42313          else {
42314              // this is not a known video link. Now what, Cat? Now what?
42315              return false;
42316          }
42317          $video.addClass('note-video-clip');
42318          return $video[0];
42319      };
42320      VideoDialog.prototype.show = function () {
42321          var _this = this;
42322          var text = this.context.invoke('editor.getSelectedText');
42323          this.context.invoke('editor.saveRange');
42324          this.showVideoDialog(text).then(function (url) {
42325              // [workaround] hide dialog before restore range for IE range focus
42326              _this.ui.hideDialog(_this.$dialog);
42327              _this.context.invoke('editor.restoreRange');
42328              // build node
42329              var $node = _this.createVideoNode(url);
42330              if ($node) {
42331                  // insert video node
42332                  _this.context.invoke('editor.insertNode', $node);
42333              }
42334          }).fail(function () {
42335              _this.context.invoke('editor.restoreRange');
42336          });
42337      };
42338      /**
42339       * show image dialog
42340       *
42341       * @param {jQuery} $dialog
42342       * @return {Promise}
42343       */
42344      VideoDialog.prototype.showVideoDialog = function (text) {
42345          var _this = this;
42346          return $$1.Deferred(function (deferred) {
42347              var $videoUrl = _this.$dialog.find('.note-video-url');
42348              var $videoBtn = _this.$dialog.find('.note-video-btn');
42349              _this.ui.onDialogShown(_this.$dialog, function () {
42350                  _this.context.triggerEvent('dialog.shown');
42351                  $videoUrl.val(text).on('input', function () {
42352                      _this.ui.toggleBtn($videoBtn, $videoUrl.val());
42353                  });
42354                  if (!env.isSupportTouch) {
42355                      $videoUrl.trigger('focus');
42356                  }
42357                  $videoBtn.click(function (event) {
42358                      event.preventDefault();
42359                      deferred.resolve($videoUrl.val());
42360                  });
42361                  _this.bindEnterKey($videoUrl, $videoBtn);
42362              });
42363              _this.ui.onDialogHidden(_this.$dialog, function () {
42364                  $videoUrl.off('input');
42365                  $videoBtn.off('click');
42366                  if (deferred.state() === 'pending') {
42367                      deferred.reject();
42368                  }
42369              });
42370              _this.ui.showDialog(_this.$dialog);
42371          });
42372      };
42373      return VideoDialog;
42374  }());
42375
42376  var HelpDialog = /** @class */ (function () {
42377      function HelpDialog(context) {
42378          this.context = context;
42379          this.ui = $$1.summernote.ui;
42380          this.$body = $$1(document.body);
42381          this.$editor = context.layoutInfo.editor;
42382          this.options = context.options;
42383          this.lang = this.options.langInfo;
42384      }
42385      HelpDialog.prototype.initialize = function () {
42386          var $container = this.options.dialogsInBody ? this.$body : this.$editor;
42387          var body = [
42388              '<p class="text-center">',
42389              '<a href="http://summernote.org/" target="_blank">Summernote 0.8.11</a> · ',
42390              '<a href="https://github.com/summernote/summernote" target="_blank">Project</a> · ',
42391              '<a href="https://github.com/summernote/summernote/issues" target="_blank">Issues</a>',
42392              '</p>'
42393          ].join('');
42394          this.$dialog = this.ui.dialog({
42395              title: this.lang.options.help,
42396              fade: this.options.dialogsFade,
42397              body: this.createShortcutList(),
42398              footer: body,
42399              callback: function ($node) {
42400                  $node.find('.modal-body,.note-modal-body').css({
42401                      'max-height': 300,
42402                      'overflow': 'scroll'
42403                  });
42404              }
42405          }).render().appendTo($container);
42406      };
42407      HelpDialog.prototype.destroy = function () {
42408          this.ui.hideDialog(this.$dialog);
42409          this.$dialog.remove();
42410      };
42411      HelpDialog.prototype.createShortcutList = function () {
42412          var _this = this;
42413          var keyMap = this.options.keyMap[env.isMac ? 'mac' : 'pc'];
42414          return Object.keys(keyMap).map(function (key) {
42415              var command = keyMap[key];
42416              var $row = $$1('<div><div class="help-list-item"/></div>');
42417              $row.append($$1('<label><kbd>' + key + '</kdb></label>').css({
42418                  'width': 180,
42419                  'margin-right': 10
42420              })).append($$1('<span/>').html(_this.context.memo('help.' + command) || command));
42421              return $row.html();
42422          }).join('');
42423      };
42424      /**
42425       * show help dialog
42426       *
42427       * @return {Promise}
42428       */
42429      HelpDialog.prototype.showHelpDialog = function () {
42430          var _this = this;
42431          return $$1.Deferred(function (deferred) {
42432              _this.ui.onDialogShown(_this.$dialog, function () {
42433                  _this.context.triggerEvent('dialog.shown');
42434                  deferred.resolve();
42435              });
42436              _this.ui.showDialog(_this.$dialog);
42437          }).promise();
42438      };
42439      HelpDialog.prototype.show = function () {
42440          var _this = this;
42441          this.context.invoke('editor.saveRange');
42442          this.showHelpDialog().then(function () {
42443              _this.context.invoke('editor.restoreRange');
42444          });
42445      };
42446      return HelpDialog;
42447  }());
42448
42449  var AIR_MODE_POPOVER_X_OFFSET = 20;
42450  var AirPopover = /** @class */ (function () {
42451      function AirPopover(context) {
42452          var _this = this;
42453          this.context = context;
42454          this.ui = $$1.summernote.ui;
42455          this.options = context.options;
42456          this.events = {
42457              'summernote.keyup summernote.mouseup summernote.scroll': function () {
42458                  _this.update();
42459              },
42460              'summernote.disable summernote.change summernote.dialog.shown': function () {
42461                  _this.hide();
42462              },
42463              'summernote.focusout': function (we, e) {
42464                  // [workaround] Firefox doesn't support relatedTarget on focusout
42465                  //  - Ignore hide action on focus out in FF.
42466                  if (env.isFF) {
42467                      return;
42468                  }
42469                  if (!e.relatedTarget || !dom.ancestor(e.relatedTarget, func.eq(_this.$popover[0]))) {
42470                      _this.hide();
42471                  }
42472              }
42473          };
42474      }
42475      AirPopover.prototype.shouldInitialize = function () {
42476          return this.options.airMode && !lists.isEmpty(this.options.popover.air);
42477      };
42478      AirPopover.prototype.initialize = function () {
42479          this.$popover = this.ui.popover({
42480              className: 'note-air-popover'
42481          }).render().appendTo(this.options.container);
42482          var $content = this.$popover.find('.popover-content');
42483          this.context.invoke('buttons.build', $content, this.options.popover.air);
42484      };
42485      AirPopover.prototype.destroy = function () {
42486          this.$popover.remove();
42487      };
42488      AirPopover.prototype.update = function () {
42489          var styleInfo = this.context.invoke('editor.currentStyle');
42490          if (styleInfo.range && !styleInfo.range.isCollapsed()) {
42491              var rect = lists.last(styleInfo.range.getClientRects());
42492              if (rect) {
42493                  var bnd = func.rect2bnd(rect);
42494                  this.$popover.css({
42495                      display: 'block',
42496                      left: Math.max(bnd.left + bnd.width / 2, 0) - AIR_MODE_POPOVER_X_OFFSET,
42497                      top: bnd.top + bnd.height
42498                  });
42499                  this.context.invoke('buttons.updateCurrentStyle', this.$popover);
42500              }
42501          }
42502          else {
42503              this.hide();
42504          }
42505      };
42506      AirPopover.prototype.hide = function () {
42507          this.$popover.hide();
42508      };
42509      return AirPopover;
42510  }());
42511
42512  var POPOVER_DIST = 5;
42513  var HintPopover = /** @class */ (function () {
42514      function HintPopover(context) {
42515          var _this = this;
42516          this.context = context;
42517          this.ui = $$1.summernote.ui;
42518          this.$editable = context.layoutInfo.editable;
42519          this.options = context.options;
42520          this.hint = this.options.hint || [];
42521          this.direction = this.options.hintDirection || 'bottom';
42522          this.hints = $$1.isArray(this.hint) ? this.hint : [this.hint];
42523          this.events = {
42524              'summernote.keyup': function (we, e) {
42525                  if (!e.isDefaultPrevented()) {
42526                      _this.handleKeyup(e);
42527                  }
42528              },
42529              'summernote.keydown': function (we, e) {
42530                  _this.handleKeydown(e);
42531              },
42532              'summernote.disable summernote.dialog.shown': function () {
42533                  _this.hide();
42534              }
42535          };
42536      }
42537      HintPopover.prototype.shouldInitialize = function () {
42538          return this.hints.length > 0;
42539      };
42540      HintPopover.prototype.initialize = function () {
42541          var _this = this;
42542          this.lastWordRange = null;
42543          this.$popover = this.ui.popover({
42544              className: 'note-hint-popover',
42545              hideArrow: true,
42546              direction: ''
42547          }).render().appendTo(this.options.container);
42548          this.$popover.hide();
42549          this.$content = this.$popover.find('.popover-content,.note-popover-content');
42550          this.$content.on('click', '.note-hint-item', function (e) {
42551              _this.$content.find('.active').removeClass('active');
42552              $$1(e.currentTarget).addClass('active');
42553              _this.replace();
42554          });
42555      };
42556      HintPopover.prototype.destroy = function () {
42557          this.$popover.remove();
42558      };
42559      HintPopover.prototype.selectItem = function ($item) {
42560          this.$content.find('.active').removeClass('active');
42561          $item.addClass('active');
42562          this.$content[0].scrollTop = $item[0].offsetTop - (this.$content.innerHe
42562ight() / 2);
42563      };
42564      HintPopover.prototype.moveDown = function () {
42565          var $current = this.$content.find('.note-hint-item.active');
42566          var $next = $current.next();
42567          if ($next.length) {
42568              this.selectItem($next);
42569          }
42570          else {
42571              var $nextGroup = $current.parent().next();
42572              if (!$nextGroup.length) {
42573                  $nextGroup = this.$content.find('.note-hint-group').first();
42574              }
42575              this.selectItem($nextGroup.find('.note-hint-item').first());
42576          }
42577      };
42578      HintPopover.prototype.moveUp = function () {
42579          var $current = this.$content.find('.note-hint-item.active');
42580          var $prev = $current.prev();
42581          if ($prev.length) {
42582              this.selectItem($prev);
42583          }
42584          else {
42585              var $prevGroup = $current.parent().prev();
42586              if (!$prevGroup.length) {
42587                  $prevGroup = this.$content.find('.note-hint-group').last();
42588              }
42589              this.selectItem($prevGroup.find('.note-hint-item').last());
42590          }
42591      };
42592      HintPopover.prototype.replace = function () {
42593          var $item = this.$content.find('.note-hint-item.active');
42594          if ($item.length) {
42595              var node = this.nodeFromItem($item);
vendor: 6,094 bytes, lines 42596-42758
42596              // XXX: consider to move codes to editor for recording redo/undo.
42597              this.lastWordRange.insertNode(node);
42598              range.createFromNode(node).collapse().select();
42599              this.lastWordRange = null;
42600              this.hide();
42601              this.context.triggerEvent('change', this.$editable.html(), this.$editable[0]);
42602              this.context.invoke('editor.focus');
42603          }
42604      };
42605      HintPopover.prototype.nodeFromItem = function ($item) {
42606          var hint = this.hints[$item.data('index')];
42607          var item = $item.data('item');
42608          var node = hint.content ? hint.content(item) : item;
42609          if (typeof node === 'string') {
42610              node = dom.createText(node);
42611          }
42612          return node;
42613      };
42614      HintPopover.prototype.createItemTemplates = function (hintIdx, items) {
42615          var hint = this.hints[hintIdx];
42616          return items.map(function (item, idx) {
42617              var $item = $$1('<div class="note-hint-item"/>');
42618              $item.append(hint.template ? hint.template(item) : item + '');
42619              $item.data({
42620                  'index': hintIdx,
42621                  'item': item
42622              });
42623              return $item;
42624          });
42625      };
42626      HintPopover.prototype.handleKeydown = function (e) {
42627          if (!this.$popover.is(':visible')) {
42628              return;
42629          }
42630          if (e.keyCode === key.code.ENTER) {
42631              e.preventDefault();
42632              this.replace();
42633          }
42634          else if (e.keyCode === key.code.UP) {
42635              e.preventDefault();
42636              this.moveUp();
42637          }
42638          else if (e.keyCode === key.code.DOWN) {
42639              e.preventDefault();
42640              this.moveDown();
42641          }
42642      };
42643      HintPopover.prototype.searchKeyword = function (index, keyword, callback) {
42644          var hint = this.hints[index];
42645          if (hint && hint.match.test(keyword) && hint.search) {
42646              var matches = hint.match.exec(keyword);
42647              hint.search(matches[1], callback);
42648          }
42649          else {
42650              callback();
42651          }
42652      };
42653      HintPopover.prototype.createGroup = function (idx, keyword) {
42654          var _this = this;
42655          var $group = $$1('<div class="note-hint-group note-hint-group-' + idx + '"/>');
42656          this.searchKeyword(idx, keyword, function (items) {
42657              items = items || [];
42658              if (items.length) {
42659                  $group.html(_this.createItemTemplates(idx, items));
42660                  _this.show();
42661              }
42662          });
42663          return $group;
42664      };
42665      HintPopover.prototype.handleKeyup = function (e) {
42666          var _this = this;
42667          if (!lists.contains([key.code.ENTER, key.code.UP, key.code.DOWN], e.keyCode)) {
42668              var wordRange = this.context.invoke('editor.createRange').getWordRange();
42669              var keyword_1 = wordRange.toString();
42670              if (this.hints.length && keyword_1) {
42671                  this.$content.empty();
42672                  var bnd = func.rect2bnd(lists.last(wordRange.getClientRects()));
42673                  if (bnd) {
42674                      this.$popover.hide();
42675                      this.lastWordRange = wordRange;
42676                      this.hints.forEach(function (hint, idx) {
42677                          if (hint.match.test(keyword_1)) {
42678                              _this.createGroup(idx, keyword_1).appendTo(_this.$content);
42679                          }
42680                      });
42681                      // select first .note-hint-item
42682                      this.$content.find('.note-hint-item:first').addClass('active');
42683                      // set position for popover after group is created
42684                      if (this.direction === 'top') {
42685                          this.$popover.css({
42686                              left: bnd.left,
42687                              top: bnd.top - this.$popover.outerHeight() - POPOVER_DIST
42688                          });
42689                      }
42690                      else {
42691                          this.$popover.css({
42692                              left: bnd.left,
42693                              top: bnd.top + bnd.height + POPOVER_DIST
42694                          });
42695                      }
42696                  }
42697              }
42698              else {
42699                  this.hide();
42700              }
42701          }
42702      };
42703      HintPopover.prototype.show = function () {
42704          this.$popover.show();
42705      };
42706      HintPopover.prototype.hide = function () {
42707          this.$popover.hide();
42708      };
42709      return HintPopover;
42710  }());
42711
42712  var Context = /** @class */ (function () {
42713      /**
42714       * @param {jQuery} $note
42715       * @param {Object} options
42716       */
42717      function Context($note, options) {
42718          this.ui = $$1.summernote.ui;
42719          this.$note = $note;
42720          this.memos = {};
42721          this.modules = {};
42722          this.layoutInfo = {};
42723          this.options = options;
42724          this.initialize();
42725      }
42726      /**
42727       * create layout and initialize modules and other resources
42728       */
42729      Context.prototype.initialize = function () {
42730          this.layoutInfo = this.ui.createLayout(this.$note, this.options);
42731          this._initialize();
42732          this.$note.hide();
42733          return this;
42734      };
42735      /**
42736       * destroy modules and other resources and remove layout
42737       */
42738      Context.prototype.destroy = function () {
42739          this._destroy();
42740          this.$note.removeData('summernote');
42741          this.ui.removeLayout(this.$note, this.layoutInfo);
42742      };
42743      /**
42744       * destory modules and other resources and initialize it again
42745       */
42746      Context.prototype.reset = function () {
42747          var disabled = this.isDisabled();
42748          this.code(dom.emptyPara);
42749          this._destroy();
42750          this._initialize();
42751          if (disabled) {
42752              this.disable();
42753          }
42754      };
42755      Context.prototype._initialize = function () {
42756          var _this = this;
42757          // add optional buttons
42758          var buttons = $$1.extend({}, this.options.buttons);
42759          Object.keys(buttons).forEach(function (key) {
42760              _this.memo('button.' + key, buttons[key]);
42761          });
42762          var modules = $$1.extend({}, this.options.modules, $$1.summernote.plugins || {});
42763          // add and initialize modules
42764          Object.keys(modules).forEach(function (key) {
42765              _this.module(key, modules[key], true);
42766          });
42767          Object.keys(this.modules).forEach(function (key) {
42768              _this.initializeModule(key);
42769          });
42770      };
42771      Context.prototype._destroy = function () {
42772          var _this = this;
42773          // destroy modules with reversed order
42774          Object.keys(this.modules).reverse().forEach(function (key) {
42775              _this.removeModule(key);
42776          });
42777          Object.keys(this.memos).forEach(function (key) {
42778              _this.removeMemo(key);
42779          });
42780          // trigger custom onDestroy callback
42781          this.triggerEvent('destroy', this);
42782      };
42783      Context.prototype.code = function (html) {
42784          var isActivated = this.invoke('codeview.isActivated');
42785          if (html === undefined) {
42786              this.invoke('codeview.sync');
42787              return isActivated ? this.layoutInfo.codable.val() : this.layoutInfo.editable.html();
42788          }
42789          else {
42790              if (isActivated) {
42791                  this.layoutInfo.codable.val(html);
42792              }
42793              else {
42794                  this.layoutInfo.editable.html(html);
42795              }
42796              this.$note.val(html);
42797              this.triggerEvent('change', html);
42798          }
42799      };
42800      Context.prototype.isDisabled = function () {
42801          return this.layoutInfo.editable.attr('contenteditable') === 'false';
42802      };
42803      Context.prototype.enable = function () {
42804          this.layoutInfo.editable.attr('contenteditable', true);
42805          this.invoke('toolbar.activate', true);
42806          this.triggerEvent('disable', false);
42807      };
42808      Context.prototype.disable = function () {
42809          // close codeview if codeview is opend
42810          if (this.invoke('codeview.isActivated')) {
42811              this.invoke('codeview.deactivate');
42812          }
42813          this.layoutInfo.editable.attr('contenteditable', false);
42814          this.invoke('toolbar.deactivate', true);
42815          this.triggerEvent('disable', true);
42816      };
42817      Context.prototype.triggerEvent = function () {
42818          var namespace = lists.head(arguments);
42819          var args = lists.tail(lists.from(arguments));
42820          var callback = this.options.callbacks[func.namespaceToCamel(namespace, 'on')];
42821          if (callback) {
42822              callback.apply(this.$note[0], args);
42823          }
42824          this.$note.trigger('summernote.' + namespace, args);
42825      };
42826      Context.prototype.initializeModule = function (key) {
42827          var module = this.modules[key];
42828          module.shouldInitialize = module.shouldInitialize || func.ok;
42829          if (!module.shouldInitialize()) {
42830              return;
42831          }
42832          // initialize module
42833          if (module.initialize) {
42834              module.initialize();
42835          }
42836          // attach events
42837          if (module.events) {
42838              dom.attachEvents(this.$note, module.events);
42839          }
42840      };
42841      Context.prototype.module = function (key, ModuleClass, withoutIntialize) {
42842          if (arguments.length === 1) {
42843              return this.modules[key];
42844          }
42845          this.modules[key] = new ModuleClass(this);
42846          if (!withoutIntialize) {
42847              this.initializeModule(key);
42848          }
42849      };
42850      Context.prototype.removeModule = function (key) {
42851          var module = this.modules[key];
42852          if (module.shouldInitialize()) {
42853              if (module.events) {
42854                  dom.detachEvents(this.$note, module.events);
42855              }
42856              if (module.destroy) {
42857                  module.destroy();
42858              }
42859          }
42860          delete this.modules[key];
42861      };
42862      Context.prototype.memo = function (key, obj) {
42863          if (arguments.length === 1) {
42864              return this.memos[key];
42865          }
42866          this.memos[key] = obj;
42867      };
42868      Context.prototype.removeMemo = function (key) {
42869          if (this.memos[key] && this.memos[key].destroy) {
42870              this.memos[key].destroy();
42871          }
42872          delete this.memos[key];
42873      };
42874      /**
42875       * Some buttons need to change their visual style immediately once they get pressed
42876       */
42877      Context.prototype.createInvokeHandlerAndUpdateState = function (namespace, value) {
42878          var _this = this;
42879          return function (event) {
42880              _this.createInvokeHandler(namespace, value)(event);
42881              _this.invoke('buttons.updateCurrentStyle');
42882          };
42883      };
42884      Context.prototype.createInvokeHandler = function (namespace, value) {
42885          var _this = this;
42886          return function (event) {
42887              event.preventDefault();
42888              var $target = $$1(event.target);
42889              _this.invoke(namespace, value || $target.closest('[data-value]').data('value'), $target);
42890          };
42891      };
42892      Context.prototype.invoke = function () {
42893          var namespace = lists.head(arguments);
42894          var args = lists.tail(lists.from(arguments));
42895          var splits = namespace.split('.');
42896          var hasSeparator = splits.length > 1;
42897          var moduleName = hasSeparator && lists.head(splits);
42898          var methodName = hasSeparator ? lists.last(splits) : lists.head(splits);
42899          var module = this.modules[moduleName || 'editor'];
42900          if (!moduleName && this[methodName]) {
42901              return this[methodName].apply(this, args);
42902          }
42903          else if (module && module[methodName] && module.shouldInitialize()) {
42904              return module[methodName].apply(module, args);
42905          }
42906      };
42907      return Context;
42908  }());
42909
42910  $$1.fn.extend({
42911      /**
42912       * Summernote API
42913       *
42914       * @param {Object|String}
42915       * @return {this}
42916       */
42917      summernote: function () {
42918          var type = $$1.type(lists.head(arguments));
42919          var isExternalAPICalled = type === 'string';
42920          var hasInitOptions = type === 'object';
42921          var options = $$1.extend({}, $$1.summernote.options, hasInitOptions ? lists.head(arguments) : {});
42922          // Update options
42923          options.langInfo = $$1.extend(true, {}, $$1.summernote.lang['en-US'], $$1.summernote.lang[options.lang]);
42924          options.icons = $$1.extend(true, {}, $$1.summernote.options.icons, options.icons);
42925          options.tooltip = options.tooltip === 'auto' ? !env.isSupportTouch : options.tooltip;
42926          this.each(function (idx, note) {
42927              var $note = $$1(note);
42928              if (!$note.data('summernote')) {
42929                  var context = new Context($note, options);
42930                  $note.data('summernote', context);
42931                  $note.data('summernote').triggerEvent('init', context.layoutInfo);
42932              }
42933          });
42934          var $note = this.first();
42935          if ($note.length) {
42936              var context = $note.data('summernote');
42937              if (isExternalAPICalled) {
vendor: 9,302 bytes, lines 42938-43155
42938                  return context.invoke.apply(context, lists.from(arguments));
42939              }
42940              else if (options.focus) {
42941                  context.invoke('editor.focus');
42942              }
42943          }
42944          return this;
42945      }
42946  });
42947
42948  $$1.summernote = $$1.extend($$1.summernote, {
42949      version: '0.8.11',
42950      ui: ui,
42951      dom: dom,
42952      range: range,
42953      plugins: {},
42954      options: {
42955          modules: {
42956              'editor': Editor,
42957              'clipboard': Clipboard,
42958              'dropzone': Dropzone,
42959              'codeview': CodeView,
42960              'statusbar': Statusbar,
42961              'fullscreen': Fullscreen,
42962              'handle': Handle,
42963              // FIXME: HintPopover must be front of autolink
42964              //  - Script error about range when Enter key is pressed on hint popover
42965              'hintPopover': HintPopover,
42966              'autoLink': AutoLink,
42967              'autoSync': AutoSync,
42968              'placeholder': Placeholder,
42969              'buttons': Buttons,
42970              'toolbar': Toolbar,
42971              'linkDialog': LinkDialog,
42972              'linkPopover': LinkPopover,
42973              'imageDialog': ImageDialog,
42974              'imagePopover': ImagePopover,
42975              'tablePopover': TablePopover,
42976              'videoDialog': VideoDialog,
42977              'helpDialog': HelpDialog,
42978              'airPopover': AirPopover
42979          },
42980          buttons: {},
42981          lang: 'en-US',
42982          followingToolbar: true,
42983          otherStaticBar: '',
42984          // toolbar
42985          toolbar: [
42986              ['style', ['style']],
42987              ['font', ['bold', 'underline', 'clear']],
42988              ['fontname', ['fontname']],
42989              ['color', ['color']],
42990              ['para', ['ul', 'ol', 'paragraph']],
42991              ['table', ['table']],
42992              ['insert', ['link', 'picture', 'video']],
42993              ['view', ['fullscreen', 'codeview', 'help']]
42994          ],
42995          // popover
42996          popatmouse: true,
42997          popover: {
42998              image: [
42999                  ['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']],
43000                  ['float', ['floatLeft', 'floatRight', 'floatNone']],
43001                  ['remove', ['removeMedia']]
43002              ],
43003              link: [
43004                  ['link', ['linkDialogShow', 'unlink']]
43005              ],
43006              table: [
43007                  ['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],
43008                  ['delete', ['deleteRow', 'deleteCol', 'deleteTable']]
43009              ],
43010              air: [
43011                  ['color', ['color']],
43012                  ['font', ['bold', 'underline', 'clear']],
43013                  ['para', ['ul', 'paragraph']],
43014                  ['table', ['table']],
43015                  ['insert', ['link', 'picture']]
43016              ]
43017          },
43018          // air mode: inline editor
43019          airMode: false,
43020          width: null,
43021          height: null,
43022          linkTargetBlank: true,
43023          focus: false,
43024          tabSize: 4,
43025          styleWithSpan: true,
43026          shortcuts: true,
43027          textareaAutoSync: true,
43028          hintDirection: 'bottom',
43029          tooltip: 'auto',
43030          container: 'body',
43031          maxTextLength: 0,
43032          blockquoteBreakingLevel: 2,
43033          styleTags: ['p', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
43034          fontNames: [
43035              'Arial', 'Arial Black', 'Comic Sans MS', 'Courier New',
43036              'Helvetica Neue', 'Helvetica', 'Impact', 'Lucida Grande',
43037              'Tahoma', 'Times New Roman', 'Verdana'
43038          ],
43039          fontSizes: ['8', '9', '10', '11', '12', '14', '18', '24', '36'],
43040          // pallete colors(n x n)
43041          colors: [
43042              ['#000000', '#424242', '#636363', '#9C9C94', '#CEC6CE', '#EFEFEF', '#F7F7F7', '#FFFFFF'],
43043              ['#FF0000', '#FF9C00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF', '#9C00FF', '#FF00FF'],
43044              ['#F7C6CE', '#FFE7CE', '#FFEFC6', '#D6EFD6', '#CEDEE7', '#CEE7F7', '#D6D6E7', '#E7D6DE'],
43045              ['#E79C9C', '#FFC69C', '#FFE79C', '#B5D6A5', '#A5C6CE', '#9CC6EF', '#B5A5D6', '#D6A5BD'],
43046              ['#E76363', '#F7AD6B', '#FFD663', '#94BD7B', '#73A5AD', '#6BADDE', '#8C7BC6', '#C67BA5'],
43047              ['#CE0000', '#E79439', '#EFC631', '#6BA54A', '#4A7B8C', '#3984C6', '#634AA5', '#A54A7B'],
43048              ['#9C0000', '#B56308', '#BD9400', '#397B21', '#104A5A', '#085294', '#311873', '#731842'],
43049              ['#630000', '#7B3900', '#846300', '#295218', '#083139', '#003163', '#21104A', '#4A1031']
43050          ],
43051          // http://chir.ag/projects/name-that-color/
43052          colorsName: [
43053              ['Black', 'Tundora', 'Dove Gray', 'Star Dust', 'Pale Slate', 'Gallery', 'Alabaster', 'White'],
43054              ['Red', 'Orange Peel', 'Yellow', 'Green', 'Cyan', 'Blue', 'Electric Violet', 'Magenta'],
43055              ['Azalea', 'Karry', 'Egg White', 'Zanah', 'Botticelli', 'Tropical Blue', 'Mischka', 'Twilight'],
43056              ['Tonys Pink', 'Peach Orange', 'Cream Brulee', 'Sprout', 'Casper', 'Perano', 'Cold Purple', 'Careys Pink'],
43057              ['Mandy', 'Rajah', 'Dandelion', 'Olivine', 'Gulf Stream', 'Viking', 'Blue Marguerite', 'Puce'],
43058              ['Guardsman Red', 'Fire Bush', 'Golden Dream', 'Chelsea Cucumber', 'Smalt Blue', 'Boston Blue', 'Butterfly Bush', 'Cadillac'],
43059              ['Sangria', 'Mai Tai', 'Buddha Gold', 'Forest Green', 'Eden', 'Venice Blue', 'Meteorite', 'Claret'],
43060              ['Rosewood', 'Cinnamon', 'Olive', 'Parsley', 'Tiber', 'Midnight Blue', 'Valentino', 'Loulou']
43061          ],
43062          lineHeights: ['1.0', '1.2', '1.4', '1.5', '1.6', '1.8', '2.0', '3.0'],
43063          tableClassName: 'table table-bordered',
43064          insertTableMaxSize: {
43065              col: 10,
43066              row: 10
43067          },
43068          dialogsInBody: false,
43069          dialogsFade: false,
43070          maximumImageFileSize: null,
43071          callbacks: {
43072              onInit: null,
43073              onFocus: null,
43074              onBlur: null,
43075              onBlurCodeview: null,
43076              onEnter: null,
43077              onKeyup: null,
43078              onKeydown: null,
43079              onImageUpload: null,
43080              onImageUploadError: null,
43081              onImageLinkInsert: null
43082          },
43083          codemirror: {
43084              mode: 'text/html',
43085              htmlMode: true,
43086              lineNumbers: true
43087          },
43088          keyMap: {
43089              pc: {
43090                  'ENTER': 'insertParagraph',
43091                  'CTRL+Z': 'undo',
43092                  'CTRL+Y': 'redo',
43093                  'TAB': 'tab',
43094                  'SHIFT+TAB': 'untab',
43095                  'CTRL+B': 'bold',
43096                  'CTRL+I': 'italic',
43097                  'CTRL+U': 'underline',
43098                  'CTRL+SHIFT+S': 'strikethrough',
43099                  'CTRL+BACKSLASH': 'removeFormat',
43100                  'CTRL+SHIFT+L': 'justifyLeft',
43101                  'CTRL+SHIFT+E': 'justifyCenter',
43102                  'CTRL+SHIFT+R': 'justifyRight',
43103                  'CTRL+SHIFT+J': 'justifyFull',
43104                  'CTRL+SHIFT+NUM7': 'insertUnorderedList',
43105                  'CTRL+SHIFT+NUM8': 'insertOrderedList',
43106                  'CTRL+LEFTBRACKET': 'outdent',
43107                  'CTRL+RIGHTBRACKET': 'indent',
43108                  'CTRL+NUM0': 'formatPara',
43109                  'CTRL+NUM1': 'formatH1',
43110                  'CTRL+NUM2': 'formatH2',
43111                  'CTRL+NUM3': 'formatH3',
43112                  'CTRL+NUM4': 'formatH4',
43113                  'CTRL+NUM5': 'formatH5',
43114                  'CTRL+NUM6': 'formatH6',
43115                  'CTRL+ENTER': 'insertHorizontalRule',
43116                  'CTRL+K': 'linkDialog.show'
43117              },
43118              mac: {
43119                  'ENTER': 'insertParagraph',
43120                  'CMD+Z': 'undo',
43121                  'CMD+SHIFT+Z': 'redo',
43122                  'TAB': 'tab',
43123                  'SHIFT+TAB': 'untab',
43124                  'CMD+B': 'bold',
43125                  'CMD+I': 'italic',
43126                  'CMD+U': 'underline',
43127                  'CMD+SHIFT+S': 'strikethrough',
43128                  'CMD+BACKSLASH': 'removeFormat',
43129                  'CMD+SHIFT+L': 'justifyLeft',
43130                  'CMD+SHIFT+E': 'justifyCenter',
43131                  'CMD+SHIFT+R': 'justifyRight',
43132                  'CMD+SHIFT+J': 'justifyFull',
43133                  'CMD+SHIFT+NUM7': 'insertUnorderedList',
43134                  'CMD+SHIFT+NUM8': 'insertOrderedList',
43135                  'CMD+LEFTBRACKET': 'outdent',
43136                  'CMD+RIGHTBRACKET': 'indent',
43137                  'CMD+NUM0': 'formatPara',
43138                  'CMD+NUM1': 'formatH1',
43139                  'CMD+NUM2': 'formatH2',
43140                  'CMD+NUM3': 'formatH3',
43141                  'CMD+NUM4': 'formatH4',
43142                  'CMD+NUM5': 'formatH5',
43143                  'CMD+NUM6': 'formatH6',
43144                  'CMD+ENTER': 'insertHorizontalRule',
43145                  'CMD+K': 'linkDialog.show'
43146              }
43147          },
43148          icons: {
43149              'align': 'note-icon-align',
43150              'alignCenter': 'note-icon-align-center',
43151              'alignJustify': 'note-icon-align-justify',
43152              'alignLeft': 'note-icon-align-left',
43153              'alignRight': 'note-icon-align-right',
43154              'rowBelow': 'note-icon-row-below',
43155              'colBefore': 'note-icon-col-before',
43156              'colAfter': 'note-icon-col-after',
43157              'rowAbove': 'note-icon-row-above',
43158              'rowRemove': 'note-icon-row-remove',
43159              'colRemove': 'note-icon-col-remove',
43160              'indent': 'note-icon-align-indent',
43161              'outdent': 'note-icon-align-outdent',
43162              'arrowsAlt': 'note-icon-arrows-alt',
43163              'bold': 'note-icon-bold',
43164              'caret': 'note-icon-caret',
43165              'circle': 'note-icon-circle',
43166              'close': 'note-icon-close',
43167              'code': 'note-icon-code',
43168              'eraser': 'note-icon-eraser',
43169              'font': 'note-icon-font',
43170              'frame': 'note-icon-frame',
43171              'italic': 'note-icon-italic',
43172              'link': 'note-icon-link',
43173              'unlink': 'note-icon-chain-broken',
43174              'magic': 'note-icon-magic',
43175              'menuCheck': 'note-icon-menu-check',
43176              'minus': 'note-icon-minus',
43177              'orderedlist': 'note-icon-orderedlist',
43178              'pencil': 'note-icon-pencil',
43179              'picture': 'note-icon-picture',
43180              'question': 'note-icon-question',
43181              'redo': 'note-icon-redo',
43182              'square': 'note-icon-square',
43183              'strikethrough': 'note-icon-strikethrough',
43184              'subscript': 'note-icon-subscript',
43185              'superscript': 'note-icon-superscript',
43186              'table': 'note-icon-table',
43187              'textHeight': 'note-icon-text-height',
43188              'trash': 'note-icon-trash',
43189              'underline': 'note-icon-underline',
43190              'undo': 'note-icon-undo',
43191              'unorderedlist': 'note-icon-unorderedlist',
43192              'video': 'note-icon-video'
43193          }
43194      }
43195  });
43196
43197})));
43198//# sourceMappingURL=summernote.js.map
43199
43200// Released under MIT license
43201// Copyright (c) 2009-2010 Dominic Baggott
43202// Copyright (c) 2009-2010 Ash Berlin
43203// Copyright (c) 2011 Christoph Dorn <[email protected]> (http://www.christophdorn.com)
43204
43205/*jshint browser:true, devel:true */
43206
43207(function( expose ) {
43208
43209/**
43210 *  class Markdown
43211 *
43212 *  Markdown processing in Javascript done right. We have very particular views
43213 *  on what constitutes 'right' which include:
43214 *
43215 *  - produces well-formed HTML (this means that em and strong nesting is
43216 *    important)
43217 *
43218 *  - has an intermediate representation to allow processing of parsed data (We
43219 *    in fact have two, both as [JsonML]: a markdown tree and an HTML tree).
43220 *
43221 *  - is easily extensible to add new dialects without having to rewrite the
43222 *    entire parsing mechanics
43223 *
43224 *  - has a good test suite
43225 *
43226 *  This implementation fulfills all of these (except that the test suite could
43227 *  do with expanding to automatically run all the fixtures from other Markdown
43228 *  implementations.)
43229 *
43230 *  ##### Intermediate Representation
43231 *
43232 *  *TODO* Talk about this :) Its JsonML, but document the node names we use.
43233 *
43234 *  [JsonML]: http://jsonml.org/ "JSON Markup Language"
43235 **/
43236var Markdown = expose.Markdown = function(dialect) {
43237  switch (typeof dialect) {
43238    case "undefined":
43239      this.dialect = Markdown.dialects.Gruber;
43240      break;
43241    case "object":
43242      this.dialect = dialect;
43243      break;
43244    default:
43245      if ( dialect in Markdown.dialects ) {
43246        this.dialect = Markdown.dialects[dialect];
43247      }
43248      else {
43249        throw new Error("Unknown Markdown dialect '" + String(dialect) + "'");
43250      }
43251      break;
43252  }
43253  this.em_state = [];
43254  this.strong_state = [];
43255  this.debug_indent = "";
43256};
43257
43258/**
43259 *  parse( markdown, [dialect] ) -> JsonML
43260 *  - markdown (String): markdown string to parse
43261 *  - dialect (String | Dialect): the dialect to use, defaults to gruber
43262 *
43263 *  Parse `markdown` and return a markdown document as a Markdown.JsonML tree.
43264 **/
43265expose.parse = function( source, dialect ) {
43266  // dialect will default if undefined
43267  var md = new Markdown( dialect );
43268  return md.toTree( source );
43269};
43270
43271/**
43272 *  toHTML( markdown, [dialect]  ) -> String
43273 *  toHTML( md_tree ) -> String
43274 *  - markdown (String): markdown string to parse
43275 *  - md_tree (Markdown.JsonML): parsed markdown tree
43276 *
43277 *  Take markdown (either as a string or as a JsonML tree) and run it through
43278 *  [[toHTMLTree]] then turn it into a well-formated HTML fragment.
43279 **/
43280expose.toHTML = function toHTML( source , dialect , options ) {
43281  var input = expose.toHTMLTree( source , dialect , options );
43282
43283  return expose.renderJsonML( input );
43284};
43285
43286/**
43287 *  toHTMLTree( markdown, [dialect] ) -> JsonML
43288 *  toHTMLTree( md_tree ) -> JsonML
43289 *  - markdown (String): markdown string to parse
43290 *  - dialect (String | Dialect): the dialect to use, defaults to gruber
43291 *  - md_tree (Markdown.JsonML): parsed markdown tree
43292 *
43293 *  Turn markdown into HTML, represented as a JsonML tree. If a string is given
43294 *  to this function, it is first parsed into a markdown tree by calling
43295 *  [[parse]].
43296 **/
43297expose.toHTMLTree = function toHTMLTree( input, dialect , options ) {
43298  // convert string input to an MD tree
43299  if ( typeof input ==="string" ) input = this.parse( input, dialect );
43300
43301  // Now convert the MD tree to an HTML tree
43302
43303  // remove references from the tree
43304  var attrs = extract_attr( input ),
43305      refs = {};
43306
43307  if ( attrs && attrs.references ) {
43308    refs = attrs.references;
43309  }
43310
43311  var html = convert_tree_to_html( input, refs , options );
43312  merge_text_nodes( html );
43313  return html;
43314};
43315
43316// For Spidermonkey based engines
43317function mk_block_toSource() {
43318  return "Markdown.mk_block( " +
43319          uneval(this.toString()) +
43320          ", " +
43321          uneval(this.trailing) +
43322          ", " +
43323          uneval(this.lineNumber) +
43324          " )";
43325}
43326
43327// node
43328function mk_block_inspect() {
43329  var util = require("util");
43330  return "Markdown.mk_block( " +
43331          util.inspect(this.toString()) +
43332          ", " +
43333          util.inspect(this.trailing) +
43334          ", " +
43335          util.inspect(this.lineNumber) +
43336          " )";
43337
43338}
43339
43340var mk_block = Markdown.mk_block = function(block, trail, line) {
43341  // Be helpful for default case in tests.
43342  if ( arguments.length == 1 ) trail = "\n\n";
43343
43344  var s = new String(block);
43345  s.trailing = trail;
43346  // To make it clear its not just a string
43347  s.inspect = mk_block_inspect;
43348  s.toSource = mk_block_toSource;
43349
43350  if ( line != undefined )
43351    s.lineNumber = line;
43352
43353  return s;
43354};
43355
43356function count_lines( str ) {
43357  var n = 0, i = -1;
43358  while ( ( i = str.indexOf("\n", i + 1) ) !== -1 ) n++;
43359  return n;
43360}
43361
43362// Internal - split source into rough blocks
43363Markdown.prototype.split_blocks = function splitBlocks( input, startLine ) {
43364  input = input.replace(/(\r\n|\n|\r)/g, "\n");
43365  // [\s\S] matches _anything_ (newline or space)
43366  // [^] is equivalent but doesn't work in IEs.
vendor: 15,397 bytes, lines 43367-43825
43367  var re = /([\s\S]+?)($|\n#|\n(?:\s*\n|$)+)/g,
43368      blocks = [],
43369      m;
43370
43371  var line_no = 1;
43372
43373  if ( ( m = /^(\s*\n)/.exec(input) ) != null ) {
43374    // skip (but count) leading blank lines
43375    line_no += count_lines( m[0] );
43376    re.lastIndex = m[0].length;
43377  }
43378
43379  while ( ( m = re.exec(input) ) !== null ) {
43380    if (m[2] == "\n#") {
43381      m[2] = "\n";
43382      re.lastIndex--;
43383    }
43384    blocks.push( mk_block( m[1], m[2], line_no ) );
43385    line_no += count_lines( m[0] );
43386  }
43387
43388  return blocks;
43389};
43390
43391/**
43392 *  Markdown#processBlock( block, next ) -> undefined | [ JsonML, ... ]
43393 *  - block (String): the block to process
43394 *  - next (Array): the following blocks
43395 *
43396 * Process `block` and return an array of JsonML nodes representing `block`.
43397 *
43398 * It does this by asking each block level function in the dialect to process
43399 * the block until one can. Succesful handling is indicated by returning an
43400 * array (with zero or more JsonML nodes), failure by a false value.
43401 *
43402 * Blocks handlers are responsible for calling [[Markdown#processInline]]
43403 * themselves as appropriate.
43404 *
43405 * If the blocks were split incorrectly or adjacent blocks need collapsing you
43406 * can adjust `next` in place using shift/splice etc.
43407 *
43408 * If any of this default behaviour is not right for the dialect, you can
43409 * define a `__call__` method on the dialect that will get invoked to handle
43410 * the block processing.
43411 */
43412Markdown.prototype.processBlock = function processBlock( block, next ) {
43413  var cbs = this.dialect.block,
43414      ord = cbs.__order__;
43415
43416  if ( "__call__" in cbs ) {
43417    return cbs.__call__.call(this, block, next);
43418  }
43419
43420  for ( var i = 0; i < ord.length; i++ ) {
43421    //D:this.debug( "Testing", ord[i] );
43422    var res = cbs[ ord[i] ].call( this, block, next );
43423    if ( res ) {
43424      //D:this.debug("  matched");
43425      if ( !isArray(res) || ( res.length > 0 && !( isArray(res[0]) ) ) )
43426        this.debug(ord[i], "didn't return a proper array");
43427      //D:this.debug( "" );
43428      return res;
43429    }
43430  }
43431
43432  // Uhoh! no match! Should we throw an error?
43433  return [];
43434};
43435
43436Markdown.prototype.processInline = function processInline( block ) {
43437  return this.dialect.inline.__call__.call( this, String( block ) );
43438};
43439
43440/**
43441 *  Markdown#toTree( source ) -> JsonML
43442 *  - source (String): markdown source to parse
43443 *
43444 *  Parse `source` into a JsonML tree representing the markdown document.
43445 **/
43446// custom_tree means set this.tree to `custom_tree` and restore old value on return
43447Markdown.prototype.toTree = function toTree( source, custom_root ) {
43448  var blocks = source instanceof Array ? source : this.split_blocks( source );
43449
43450  // Make tree a member variable so its easier to mess with in extensions
43451  var old_tree = this.tree;
43452  try {
43453    this.tree = custom_root || this.tree || [ "markdown" ];
43454
43455    blocks:
43456    while ( blocks.length ) {
43457      var b = this.processBlock( blocks.shift(), blocks );
43458
43459      // Reference blocks and the like won't return any content
43460      if ( !b.length ) continue blocks;
43461
43462      this.tree.push.apply( this.tree, b );
43463    }
43464    return this.tree;
43465  }
43466  finally {
43467    if ( custom_root ) {
43468      this.tree = old_tree;
43469    }
43470  }
43471};
43472
43473// Noop by default
43474Markdown.prototype.debug = function () {
43475  var args = Array.prototype.slice.call( arguments);
43476  args.unshift(this.debug_indent);
43477  if ( typeof print !== "undefined" )
43478      print.apply( print, args );
43479  if ( typeof console !== "undefined" && typeof console.log !== "undefined" )
43480      console.log.apply( null, args );
43481}
43482
43483Markdown.prototype.loop_re_over_block = function( re, block, cb ) {
43484  // Dont use /g regexps with this
43485  var m,
43486      b = block.valueOf();
43487
43488  while ( b.length && (m = re.exec(b) ) != null ) {
43489    b = b.substr( m[0].length );
43490    cb.call(this, m);
43491  }
43492  return b;
43493};
43494
43495/**
43496 * Markdown.dialects
43497 *
43498 * Namespace of built-in dialects.
43499 **/
43500Markdown.dialects = {};
43501
43502/**
43503 * Markdown.dialects.Gruber
43504 *
43505 * The default dialect that follows the rules set out by John Gruber's
43506 * markdown.pl as closely as possible. Well actually we follow the behaviour of
43507 * that script which in some places is not exactly what the syntax web page
43508 * says.
43509 **/
43510Markdown.dialects.Gruber = {
43511  block: {
43512    atxHeader: function atxHeader( block, next ) {
43513      var m = block.match( /^(#{1,6})\s*(.*?)\s*#*\s*(?:\n|$)/ );
43514
43515      if ( !m ) return undefined;
43516
43517      var header = [ "header", { level: m[ 1 ].length } ];
43518      Array.prototype.push.apply(header, this.processInline(m[ 2 ]));
43519
43520      if ( m[0].length < block.length )
43521        next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) );
43522
43523      return [ header ];
43524    },
43525
43526    setextHeader: function setextHeader( block, next ) {
43527      var m = block.match( /^(.*)\n([-=])\2\2+(?:\n|$)/ );
43528
43529      if ( !m ) return undefined;
43530
43531      var level = ( m[ 2 ] === "=" ) ? 1 : 2;
43532      var header = [ "header", { level : level }, m[ 1 ] ];
43533
43534      if ( m[0].length < block.length )
43535        next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) );
43536
43537      return [ header ];
43538    },
43539
43540    code: function code( block, next ) {
43541      // |    Foo
43542      // |bar
43543      // should be a code block followed by a paragraph. Fun
43544      //
43545      // There might also be adjacent code block to merge.
43546
43547      var ret = [],
43548          re = /^(?: {0,3}\t| {4})(.*)\n?/,
43549          lines;
43550
43551      // 4 spaces + content
43552      if ( !block.match( re ) ) return undefined;
43553
43554      block_search:
43555      do {
43556        // Now pull out the rest of the lines
43557        var b = this.loop_re_over_block(
43558                  re, block.valueOf(), function( m ) { ret.push( m[1] ); } );
43559
43560        if ( b.length ) {
43561          // Case alluded to in first comment. push it back on as a new block
43562          next.unshift( mk_block(b, block.trailing) );
43563          break block_search;
43564        }
43565        else if ( next.length ) {
43566          // Check the next block - it might be code too
43567          if ( !next[0].match( re ) ) break block_search;
43568
43569          // Pull how how many blanks lines follow - minus two to account for .join
43570          ret.push ( block.trailing.replace(/[^\n]/g, "").substring(2) );
43571
43572          block = next.shift();
43573        }
43574        else {
43575          break block_search;
43576        }
43577      } while ( true );
43578
43579      return [ [ "code_block", ret.join("\n") ] ];
43580    },
43581
43582    horizRule: function horizRule( block, next ) {
43583      // this needs to find any hr in the block to handle abutting blocks
43584      var m = block.match( /^(?:([\s\S]*?)\n)?[ \t]*([-_*])(?:[ \t]*\2){2,}[ \t]*(?:\n([\s\S]*))?$/ );
43585
43586      if ( !m ) {
43587        return undefined;
43588      }
43589
43590      var jsonml = [ [ "hr" ] ];
43591
43592      // if there's a leading abutting block, process it
43593      if ( m[ 1 ] ) {
43594        jsonml.unshift.apply( jsonml, this.processBlock( m[ 1 ], [] ) );
43595      }
43596
43597      // if there's a trailing abutting block, stick it into next
43598      if ( m[ 3 ] ) {
43599        next.unshift( mk_block( m[ 3 ] ) );
43600      }
43601
43602      return jsonml;
43603    },
43604
43605    // There are two types of lists. Tight and loose. Tight lists have no whitespace
43606    // between the items (and result in text just in the <li>) and loose lists,
43607    // which have an empty line between list items, resulting in (one or more)
43608    // paragraphs inside the <li>.
43609    //
43610    // There are all sorts weird edge cases about the original markdown.pl's
43611    // handling of lists:
43612    //
43613    // * Nested lists are supposed to be indented by four chars per level. But
43614    //   if they aren't, you can get a nested list by indenting by less than
43615    //   four so long as the indent doesn't match an indent of an existing list
43616    //   item in the 'nest stack'.
43617    //
43618    // * The type of the list (bullet or number) is controlled just by the
43619    //    first item at the indent. Subsequent changes are ignored unless they
43620    //    are for nested lists
43621    //
43622    lists: (function( ) {
43623      // Use a closure to hide a few variables.
43624      var any_list = "[*+-]|\\d+\\.",
43625          bullet_list = /[*+-]/,
43626          number_list = /\d+\./,
43627          // Capture leading indent as it matters for determining nested lists.
43628          is_list_re = new RegExp( "^( {0,3})(" + any_list + ")[ \t]+" ),
43629          indent_re = "(?: {0,3}\\t| {4})";
43630
43631      // TODO: Cache this regexp for certain depths.
43632      // Create a regexp suitable for matching an li for a given stack depth
43633      function regex_for_depth( depth ) {
43634
43635        return new RegExp(
43636          // m[1] = indent, m[2] = list_type
43637          "(?:^(" + indent_re + "{0," + depth + "} {0,3})(" + any_list + ")\\s+)|" +
43638          // m[3] = cont
43639          "(^" + indent_re + "{0," + (depth-1) + "}[ ]{0,4})"
43640        );
43641      }
43642      function expand_tab( input ) {
43643        return input.replace( / {0,3}\t/g, "    " );
43644      }
43645
43646      // Add inline content `inline` to `li`. inline comes from processInline
43647      // so is an array of content
43648      function add(li, loose, inline, nl) {
43649        if ( loose ) {
43650          li.push( [ "para" ].concat(inline) );
43651          return;
43652        }
43653        // Hmmm, should this be any block level element or just paras?
43654        var add_to = li[li.length -1] instanceof Array && li[li.length - 1][0] == "para"
43655                   ? li[li.length -1]
43656                   : li;
43657
43658        // If there is already some content in this list, add the new line in
43659        if ( nl && li.length > 1 ) inline.unshift(nl);
43660
43661        for ( var i = 0; i < inline.length; i++ ) {
43662          var what = inline[i],
43663              is_str = typeof what == "string";
43664          if ( is_str && add_to.length > 1 && typeof add_to[add_to.length-1] == "string" ) {
43665            add_to[ add_to.length-1 ] += what;
43666          }
43667          else {
43668            add_to.push( what );
43669          }
43670        }
43671      }
43672
43673      // contained means have an indent greater than the current one. On
43674      // *every* line in the block
43675      function get_contained_blocks( depth, blocks ) {
43676
43677        var re = new RegExp( "^(" + indent_re + "{" + depth + "}.*?\\n?)*$" ),
43678            replace = new RegExp("^" + indent_re + "{" + depth + "}", "gm"),
43679            ret = [];
43680
43681        while ( blocks.length > 0 ) {
43682          if ( re.exec( blocks[0] ) ) {
43683            var b = blocks.shift(),
43684                // Now remove that indent
43685                x = b.replace( replace, "");
43686
43687            ret.push( mk_block( x, b.trailing, b.lineNumber ) );
43688          }
43689          else {
43690            break;
43691          }
43692        }
43693        return ret;
43694      }
43695
43696      // passed to stack.forEach to turn list items up the stack into paras
43697      function paragraphify(s, i, stack) {
43698        var list = s.list;
43699        var last_li = list[list.length-1];
43700
43701        if ( last_li[1] instanceof Array && last_li[1][0] == "para" ) {
43702          return;
43703        }
43704        if ( i + 1 == stack.length ) {
43705          // Last stack frame
43706          // Keep the same array, but replace the contents
43707          last_li.push( ["para"].concat( last_li.splice(1, last_li.length - 1) ) );
43708        }
43709        else {
43710          var sublist = last_li.pop();
43711          last_li.push( ["para"].concat( last_li.splice(1, last_li.length - 1) ), sublist );
43712        }
43713      }
43714
43715      // The matcher function
43716      return function( block, next ) {
43717        var m = block.match( is_list_re );
43718        if ( !m ) return undefined;
43719
43720        function make_list( m ) {
43721          var list = bullet_list.exec( m[2] )
43722                   ? ["bulletlist"]
43723                   : ["numberlist"];
43724
43725          stack.push( { list: list, indent: m[1] } );
43726          return list;
43727        }
43728
43729
43730        var stack = [], // Stack of lists for nesting.
43731            list = make_list( m ),
43732            last_li,
43733            loose = false,
43734            ret = [ stack[0].list ],
43735            i;
43736
43737        // Loop to search over block looking for inner block elements and loose lists
43738        loose_search:
43739        while ( true ) {
43740          // Split into lines preserving new lines at end of line
43741          var lines = block.split( /(?=\n)/ );
43742
43743          // We have to grab all lines for a li and call processInline on them
43744          // once as there are some inline things that can span lines.
43745          var li_accumulate = "";
43746
43747          // Loop over the lines in this block looking for tight lists.
43748          tight_search:
43749          for ( var line_no = 0; line_no < lines.length; line_no++ ) {
43750            var nl = "",
43751                l = lines[line_no].replace(/^\n/, function(n) { nl = n; return ""; });
43752
43753            // TODO: really should cache this
43754            var line_re = regex_for_depth( stack.length );
43755
43756            m = l.match( line_re );
43757            //print( "line:", uneval(l), "\nline match:", uneval(m) );
43758
43759            // We have a list item
43760            if ( m[1] !== undefined ) {
43761              // Process the previous list item, if any
43762              if ( li_accumulate.length ) {
43763                add( last_li, loose, this.processInline( li_accumulate ), nl );
43764                // Loose mode will have been dealt with. Reset it
43765                loose = false;
43766                li_accumulate = "";
43767              }
43768
43769              m[1] = expand_tab( m[1] );
43770              var wanted_depth = Math.floor(m[1].length/4)+1;
43771              //print( "want:", wanted_depth, "stack:", stack.length);
43772              if ( wanted_depth > stack.length ) {
43773                // Deep enough for a nested list outright
43774                //print ( "new nested list" );
43775                list = make_list( m );
43776                last_li.push( list );
43777                last_li = list[1] = [ "listitem" ];
43778              }
43779              else {
43780                // We aren't deep enough to be strictly a new level. This is
43781                // where Md.pl goes nuts. If the indent matches a level in the
43782                // stack, put it there, else put it one deeper then the
43783                // wanted_depth deserves.
43784                var found = false;
43785                for ( i = 0; i < stack.length; i++ ) {
43786                  if ( stack[ i ].indent != m[1] ) continue;
43787                  list = stack[ i ].list;
43788                  stack.splice( i+1, stack.length - (i+1) );
43789                  found = true;
43790                  break;
43791                }
43792
43793                if (!found) {
43794                  //print("not found. l:", uneval(l));
43795                  wanted_depth++;
43796                  if ( wanted_depth <= stack.length ) {
43797                    stack.splice(wanted_depth, stack.length - wanted_depth);
43798                    //print("Desired depth now", wanted_depth, "stack:", stack.length);
43799                    list = stack[wanted_depth-1].list;
43800                    //print("list:", uneval(list) );
43801                  }
43802                  else {
43803                    //print ("made new stack for messy indent");
43804                    list = make_list(m);
43805                    last_li.push(list);
43806                  }
43807                }
43808
43809                //print( uneval(list), "last", list === stack[stack.length-1].list );
43810                last_li = [ "listitem" ];
43811                list.push(last_li);
43812              } // end depth of shenegains
43813              nl = "";
43814            }
43815
43816            // Add content
43817            if ( l.length > m[0].length ) {
43818              li_accumulate += nl + l.substr( m[0].length );
43819            }
43820          } // tight_search
43821
43822          if ( li_accumulate.length ) {
43823            add( last_li, loose, this.processInline( li_accumulate ), nl );
43824            // Loose mode will have been dealt with. Reset it
43825            loose = false;
43826            li_accumulate = "";
43827          }
43828
43829          // Look at the next block - we might have a loose list. Or an extra
43830          // paragraph for the current li
43831          var contained = get_contained_blocks( stack.length, next );
43832
43833          // Deal with code blocks or properly nested lists
43834          if ( contained.length > 0 ) {
43835            // Make sure all listitems up the stack are paragraphs
43836            forEach( stack, paragraphify, this);
43837
43838            last_li.push.apply( last_li, this.toTree( contained, [] ) );
43839          }
43840
43841          var next_block = next[0] && next[0].valueOf() || "";
43842
43843          if ( next_block.match(is_list_re) || next_block.match( /^ / ) ) {
43844            block = next.shift();
43845
43846            // Check for an HR following a list: features/lists/hr_abutting
43847            var hr = this.dialect.block.horizRule( block, next );
43848
43849            if ( hr ) {
43850              ret.push.apply(ret, hr);
43851              break;
43852            }
43853
43854            // Make sure all listitems up the stack are paragraphs
43855            forEach( stack, paragraphify, this);
43856
43857            loose = true;
43858            continue loose_search;
43859          }
43860          break;
43861        } // loose_search
43862
43863        return ret;
43864      };
43865    })(),
43866
43867    blockquote: function blockquote( block, next ) {
43868      if ( !block.match( /^>/m ) )
43869        return undefined;
43870
43871      var jsonml = [];
43872
43873      // separate out the leading abutting block, if any. I.e. in this case:
43874      //
43875      //  a
43876      //  > b
43877      //
43878      if ( block[ 0 ] != ">" ) {
43879        var lines = block.split( /\n/ ),
43880            prev = [],
43881            line_no = block.lineNumber;
43882
43883        // keep shifting lines until you find a crotchet
43884        while ( lines.length && lines[ 0 ][ 0 ] != ">" ) {
43885            prev.push( lines.shift() );
43886            line_no++;
43887        }
43888
43889        var abutting = mk_block( prev.join( "\n" ), "\n", block.lineNumber );
43890        jsonml.push.apply( jsonml, this.processBlock( abutting, [] ) );
43891        // reassemble new block of just block quotes!
43892        block = mk_block( lines.join( "\n" ), block.trailing, line_no );
43893      }
43894
43895
43896      // if the next block is also a blockquote merge it in
43897      while ( next.length && next[ 0 ][ 0 ] == ">" ) {
43898        var b = next.shift();
43899        block = mk_block( block + block.trailing + b, b.trailing, block.lineNumber );
43900      }
43901
43902      // Strip off the leading "> " and re-process as a block.
43903      var input = block.replace( /^> ?/gm, "" ),
43904          old_tree = this.tree,
43905          processedBlock = this.toTree( input, [ "blockquote" ] ),
43906          attr = extract_attr( processedBlock );
43907
43908      // If any link references were found get rid of them
43909      if ( attr && attr.references ) {
43910        delete attr.references;
43911        // And then remove the attribute object if it's empty
43912        if ( isEmpty( attr ) ) {
43913          processedBlock.splice( 1, 1 );
43914        }
43915      }
43916
43917      jsonml.push( processedBlock );
43918      return jsonml;
43919    },
43920
43921    referenceDefn: function referenceDefn( block, next) {
43922      var re = /^\s*\[(.*?)\]:\s*(\S+)(?:\s+(?:(['"])(.*?)\3|\((.*?)\)))?\n?/;
43923      // interesting matches are [ , ref_id, url, , title, title ]
43924
43925      if ( !block.match(re) )
43926        return undefined;
43927
43928      // make an attribute node if it doesn't exist
43929      if ( !extract_attr( this.tree ) ) {
43930        this.tree.splice( 1, 0, {} );
43931      }
43932
43933      var attrs = extract_attr( this.tree );
43934
43935      // make a references hash if it doesn't exist
43936      if ( attrs.references === undefined ) {
43937        attrs.references = {};
43938      }
43939
43940      var b = this.loop_re_over_block(re, block, function( m ) {
43941
43942        if ( m[2] && m[2][0] == "<" && m[2][m[2].length-1] == ">" )
43943          m[2] = m[2].substring( 1, m[2].length - 1 );
43944
43945        var ref = attrs.references[ m[1].toLowerCase() ] = {
43946          href: m[2]
43947        };
43948
43949        if ( m[4] !== undefined )
43950          ref.title = m[4];
43951        else if ( m[5] !== undefined )
43952          ref.title = m[5];
43953
43954      } );
43955
43956      if ( b.length )
43957        next.unshift( mk_block( b, block.trailing ) );
43958
43959      return [];
43960    },
43961
43962    para: function para( block, next ) {
43963      // everything's a para!
43964      return [ ["para"].concat( this.processInline( block ) ) ];
43965    }
43966  }
43967};
43968
43969Markdown.dialects.Gruber.inline = {
43970
43971    __oneElement__: function oneElement( text, patterns_or_re, previous_nodes ) {
43972      var m,
43973          res,
43974          lastIndex = 0;
43975
43976      patterns_or_re = patterns_or_re || this.dialect.inline.__patterns__;
43977      var re = new RegExp( "([\\s\\S]*?)(" + (patterns_or_re.source || patterns_or_re) + ")" );
43978
43979      m = re.exec( text );
43980      if (!m) {
43981        // Just boring text
43982        return [ text.length, text ];
43983      }
43984      else if ( m[1] ) {
43985        // Some un-interesting text matched. Return that first
43986        return [ m[1].length, m[1] ];
43987      }
43988
43989      var res;
43990      if ( m[2] in this.dialect.inline ) {
43991        res = this.dialect.inline[ m[2] ].call(
43992                  this,
43993                  text.substr( m.index ), m, previous_nodes || [] );
43994      }
43995      // Default for now to make dev easier. just slurp special and output it.
43996      res = res || [ m[2].length, m[2] ];
43997      return res;
43998    },
43999
44000    __call__: function inline( text, patterns ) {
44001
44002      var out = [],
44003          res;
44004
44005      function add(x) {
44006        //D:self.debug("  adding output", uneval(x));
44007        if ( typeof x == "string" && typeof out[out.length-1] == "string" )
44008          out[ out.length-1 ] += x;
44009        else
44010          out.push(x);
44011      }
44012
44013      while ( text.length > 0 ) {
44014        res = this.dialect.inline.__oneElement__.call(this, text, patterns, out );
44015        text = text.substr( res.shift() );
44016        forEach(res, add )
44017      }
44018
44019      return out;
44020    },
44021
44022    // These characters are intersting elsewhere, so have rules for them so that
44023    // chunks of plain text blocks don't include them
44024    "]": function () {},
44025    "}": function () {},
44026
44027    __escape__ : /^\\[\\`\*_{}\[\]()#\+.!\-]/,
44028
44029    "\\": function escaped( text ) {
44030      // [ length of input processed, node/children to add... ]
44031      // Only esacape: \ ` * _ { } [ ] ( ) # * + - . !
44032      if ( this.dialect.inline.__escape__.exec( text ) )
44033        return [ 2, text.charAt( 1 ) ];
44034      else
44035        // Not an esacpe
44036        return [ 1, "\\" ];
44037    },
44038
44039    "![": function image( text ) {
44040
44041      // Unlike images, alt text is plain text only. no other elements are
44042      // allowed in there
44043
44044      // ![Alt text](/path/to/img.jpg "Optional title")
44045      //      1          2            3       4         <--- captures
44046      var m = text.match( /^!\[(.*?)\][ \t]*\([ \t]*([^")]*?)(?:[ \t]+(["'])(.*?)\3)?[ \t]*\)/ );
44047
44048      if ( m ) {
44049        if ( m[2] && m[2][0] == "<" && m[2][m[2].length-1] == ">" )
44050          m[2] = m[2].substring( 1, m[2].length - 1 );
44051
44052        m[2] = this.dialect.inline.__call__.call( this, m[2], /\\/ )[0];
44053
44054        var attrs = { alt: m[1], href: m[2] || "" };
44055        if ( m[4] !== undefined)
44056          attrs.title = m[4];
44057
44058        return [ m[0].length, [ "img", attrs ] ];
44059      }
44060
44061      // ![Alt text][id]
44062      m = text.match( /^!\[(.*?)\][ \t]*\[(.*?)\]/ );
44063
44064      if ( m ) {
44065        // We can't check if the reference is known here as it likely wont be
44066        // found till after. Check it in md tree->hmtl tree conversion
44067        return [ m[0].length, [ "img_ref", { alt: m[1], ref: m[2].toLowerCase(), original: m[0] } ] ];
44068      }
44069
44070      // Just consume the '!['
44071      return [ 2, "![" ];
44072    },
44073
44074    "[": function link( text ) {
44075
44076      var orig = String(text);
44077      // Inline content is possible inside `link text`
44078      var res = Markdown.DialectHelpers.inline_until_char.call( this, text.substr(1), "]" );
44079
44080      // No closing ']' found. Just consume the [
44081      if ( !res ) return [ 1, "[" ];
44082
44083      var consumed = 1 + res[ 0 ],
44084          children = res[ 1 ],
44085          link,
44086          attrs;
44087
44088      // At this point the first [...] has been parsed. See what follows to find
44089      // out which kind of link we are (reference or direct url)
44090      text = text.substr( consumed );
44091
44092      // [link text](/path/to/img.jpg "Optional title")
44093      //                 1            2       3         <--- captures
44094      // This will capture up to the last paren in the block. We then pull
44095      // back based on if there a matching ones in the url
44096      //    ([here](/url/(test))
44097      // The parens have to be balanced
44098      var m = text.match( /^\s*\([ \t]*([^"']*)(?:[ \t]+(["'])(.*?)\2)?[ \t]*\)/ );
44099      if ( m ) {
44100        var url = m[1];
44101        consumed += m[0].length;
44102
44103        if ( url && url[0] == "<" && url[url.length-1] == ">" )
44104          url = url.substring( 1, url.length - 1 );
44105
44106        // If there is a title we don't have to worry about parens in the url
44107        if ( !m[3] ) {
44108          var open_parens = 1; // One open that isn't in the capture
44109          for ( var len = 0; len < url.length; len++ ) {
44110            switch ( url[len] ) {
44111            case "(":
44112              open_parens++;
44113              break;
44114            case ")":
44115              if ( --open_parens == 0) {
44116                consumed -= url.length - len;
44117                url = url.substring(0, len);
44118              }
44119              break;
44120            }
44121          }
44122        }
44123
44124        // Process escapes only
44125        url = this.dialect.inline.__call__.call( this, url, /\\/ )[0];
44126
44127        attrs = { href: url || "" };
44128        if ( m[3] !== undefined)
44129          attrs.title = m[3];
44130
44131        link = [ "link", attrs ].concat( children );
44132        return [ consumed, link ];
44133      }
44134
44135      // [Alt text][id]
44136      // [Alt text] [id]
44137      m = text.match( /^\s*\[(.*?)\]/ );
44138
44139      if ( m ) {
44140
44141        consumed += m[ 0 ].length;
44142
44143        // [links][] uses links as its reference
44144        attrs = { ref: ( m[ 1 ] || String(children) ).toLowerCase(),  original: orig.substr( 0, consumed ) };
44145
44146        link = [ "link_ref", attrs ].concat( children );
44147
44148        // We can't check if the reference is known here as it likely wont be
44149        // found till after. Check it in md tree->hmtl tree conversion.
44150        // Store the original so that conversion can revert if the ref isn't found.
44151        return [ consumed, link ];
44152      }
44153
44154      // [id]
44155      // Only if id is plain (no formatting.)
44156      if ( children.length == 1 && typeof children[0] == "string" ) {
44157
44158        attrs = { ref: children[0].toLowerCase(),  original: orig.substr( 0, consumed ) };
44159        link = [ "link_ref", attrs, children[0] ];
44160        return [ consumed, link ];
44161      }
44162
44163      // Just consume the "["
44164      return [ 1, "[" ];
44165    },
44166
44167
44168    "<": function autoLink( text ) {
44169      var m;
44170
44171      if ( ( m = text.match( /^<(?:((https?|ftp|mailto):[^>]+)|(.*?@.*?\.[a-zA-Z]+))>/ ) ) != null ) {
44172        if ( m[3] ) {
44173          return [ m[0].length, [ "link", { href: "mailto:" + m[3] }, m[3] ] ];
44174
44175        }
44176        else if ( m[2] == "mailto" ) {
44177          return [ m[0].length, [ "link", { href: m[1] }, m[1].substr("mailto:".length ) ] ];
44178        }
44179        else
44180          return [ m[0].length, [ "link", { href: m[1] }, m[1] ] ];
44181      }
44182
44183      return [ 1, "<" ];
44184    },
44185
44186    "`": function inlineCode( text ) {
44187      // Inline code block. as many backticks as you like to start it
44188      // Always skip over the opening ticks.
vendor: 5,188 bytes, lines 44189-44377
44189      var m = text.match( /(`+)(([\s\S]*?)\1)/ );
44190
44191      if ( m && m[2] )
44192        return [ m[1].length + m[2].length, [ "inlinecode", m[3] ] ];
44193      else {
44194        // TODO: No matching end code found - warn!
44195        return [ 1, "`" ];
44196      }
44197    },
44198
44199    "  \n": function lineBreak( text ) {
44200      return [ 3, [ "linebreak" ] ];
44201    }
44202
44203};
44204
44205// Meta Helper/generator method for em and strong handling
44206function strong_em( tag, md ) {
44207
44208  var state_slot = tag + "_state",
44209      other_slot = tag == "strong" ? "em_state" : "strong_state";
44210
44211  function CloseTag(len) {
44212    this.len_after = len;
44213    this.name = "close_" + md;
44214  }
44215
44216  return function ( text, orig_match ) {
44217
44218    if ( this[state_slot][0] == md ) {
44219      // Most recent em is of this type
44220      //D:this.debug("closing", md);
44221      this[state_slot].shift();
44222
44223      // "Consume" everything to go back to the recrusion in the else-block below
44224      return[ text.length, new CloseTag(text.length-md.length) ];
44225    }
44226    else {
44227      // Store a clone of the em/strong states
44228      var other = this[other_slot].slice(),
44229          state = this[state_slot].slice();
44230
44231      this[state_slot].unshift(md);
44232
44233      //D:this.debug_indent += "  ";
44234
44235      // Recurse
44236      var res = this.processInline( text.substr( md.length ) );
44237      //D:this.debug_indent = this.debug_indent.substr(2);
44238
44239      var last = res[res.length - 1];
44240
44241      //D:this.debug("processInline from", tag + ": ", uneval( res ) );
44242
44243      var check = this[state_slot].shift();
44244      if ( last instanceof CloseTag ) {
44245        res.pop();
44246        // We matched! Huzzah.
44247        var consumed = text.length - last.len_after;
44248        return [ consumed, [ tag ].concat(res) ];
44249      }
44250      else {
44251        // Restore the state of the other kind. We might have mistakenly closed it.
44252        this[other_slot] = other;
44253        this[state_slot] = state;
44254
44255        // We can't reuse the processed result as it could have wrong parsing contexts in it.
44256        return [ md.length, md ];
44257      }
44258    }
44259  }; // End returned function
44260}
44261
44262Markdown.dialects.Gruber.inline["**"] = strong_em("strong", "**");
44263Markdown.dialects.Gruber.inline["__"] = strong_em("strong", "__");
44264Markdown.dialects.Gruber.inline["*"]  = strong_em("em", "*");
44265Markdown.dialects.Gruber.inline["_"]  = strong_em("em", "_");
44266
44267
44268// Build default order from insertion order.
44269Markdown.buildBlockOrder = function(d) {
44270  var ord = [];
44271  for ( var i in d ) {
44272    if ( i == "__order__" || i == "__call__" ) continue;
44273    ord.push( i );
44274  }
44275  d.__order__ = ord;
44276};
44277
44278// Build patterns for inline matcher
44279Markdown.buildInlinePatterns = function(d) {
44280  var patterns = [];
44281
44282  for ( var i in d ) {
44283    // __foo__ is reserved and not a pattern
44284    if ( i.match( /^__.*__$/) ) continue;
44285    var l = i.replace( /([\\.*+?|()\[\]{}])/g, "\\$1" )
44286             .replace( /\n/, "\\n" );
44287    patterns.push( i.length == 1 ? l : "(?:" + l + ")" );
44288  }
44289
44290  patterns = patterns.join("|");
44291  d.__patterns__ = patterns;
44292  //print("patterns:", uneval( patterns ) );
44293
44294  var fn = d.__call__;
44295  d.__call__ = function(text, pattern) {
44296    if ( pattern != undefined ) {
44297      return fn.call(this, text, pattern);
44298    }
44299    else
44300    {
44301      return fn.call(this, text, patterns);
44302    }
44303  };
44304};
44305
44306Markdown.DialectHelpers = {};
44307Markdown.DialectHelpers.inline_until_char = function( text, want ) {
44308  var consumed = 0,
44309      nodes = [];
44310
44311  while ( true ) {
44312    if ( text.charAt( consumed ) == want ) {
44313      // Found the character we were looking for
44314      consumed++;
44315      return [ consumed, nodes ];
44316    }
44317
44318    if ( consumed >= text.length ) {
44319      // No closing char found. Abort.
44320      return null;
44321    }
44322
44323    var res = this.dialect.inline.__oneElement__.call(this, text.substr( consumed ) );
44324    consumed += res[ 0 ];
44325    // Add any returned nodes.
44326    nodes.push.apply( nodes, res.slice( 1 ) );
44327  }
44328}
44329
44330// Helper function to make sub-classing a dialect easier
44331Markdown.subclassDialect = function( d ) {
44332  function Block() {}
44333  Block.prototype = d.block;
44334  function Inline() {}
44335  Inline.prototype = d.inline;
44336
44337  return { block: new Block(), inline: new Inline() };
44338};
44339
44340Markdown.buildBlockOrder ( Markdown.dialects.Gruber.block );
44341Markdown.buildInlinePatterns( Markdown.dialects.Gruber.inline );
44342
44343Markdown.dialects.Maruku = Markdown.subclassDialect( Markdown.dialects.Gruber );
44344
44345Markdown.dialects.Maruku.processMetaHash = function processMetaHash( meta_string ) {
44346  var meta = split_meta_hash( meta_string ),
44347      attr = {};
44348
44349  for ( var i = 0; i < meta.length; ++i ) {
44350    // id: #foo
44351    if ( /^#/.test( meta[ i ] ) ) {
44352      attr.id = meta[ i ].substring( 1 );
44353    }
44354    // class: .foo
44355    else if ( /^\./.test( meta[ i ] ) ) {
44356      // if class already exists, append the new one
44357      if ( attr["class"] ) {
44358        attr["class"] = attr["class"] + meta[ i ].replace( /./, " " );
44359      }
44360      else {
44361        attr["class"] = meta[ i ].substring( 1 );
44362      }
44363    }
44364    // attribute: foo=bar
44365    else if ( /\=/.test( meta[ i ] ) ) {
44366      var s = meta[ i ].split( /\=/ );
44367      attr[ s[ 0 ] ] = s[ 1 ];
44368    }
44369  }
44370
44371  return attr;
44372}
44373
44374function split_meta_hash( meta_string ) {
44375  var meta = meta_string.split( "" ),
44376      parts = [ "" ],
44377      in_quotes = false;
44378
44379  while ( meta.length ) {
44380    var letter = meta.shift();
44381    switch ( letter ) {
44382      case " " :
44383        // if we're in a quoted section, keep it
44384        if ( in_quotes ) {
44385          parts[ parts.length - 1 ] += letter;
44386        }
44387        // otherwise make a new part
44388        else {
44389          parts.push( "" );
44390        }
44391        break;
44392      case "'" :
44393      case '"' :
44394        // reverse the quotes and move straight on
44395        in_quotes = !in_quotes;
44396        break;
44397      case "\\" :
44398        // shift off the next letter to be used straight away.
44399        // it was escaped so we'll keep it whatever it is
44400        letter = meta.shift();
44401      default :
44402        parts[ parts.length - 1 ] += letter;
44403        break;
44404    }
44405  }
44406
44407  return parts;
44408}
44409
44410Markdown.dialects.Maruku.block.document_meta = function document_meta( block, next ) {
44411  // we're only interested in the first block
44412  if ( block.lineNumber > 1 ) return undefined;
44413
44414  // document_meta blocks consist of one or more lines of `Key: Value\n`
44415  if ( ! block.match( /^(?:\w+:.*\n)*\w+:.*$/ ) ) return undefined;
44416
44417  // make an attribute node if it doesn't exist
44418  if ( !extract_attr( this.tree ) ) {
44419    this.tree.splice( 1, 0, {} );
44420  }
44421
44422  var pairs = block.split( /\n/ );
44423  for ( p in pairs ) {
44424    var m = pairs[ p ].match( /(\w+):\s*(.*)$/ ),
44425        key = m[ 1 ].toLowerCase(),
44426        value = m[ 2 ];
44427
44428    this.tree[ 1 ][ key ] = value;
44429  }
44430
44431  // document_meta produces no content!
44432  return [];
44433};
44434
44435Markdown.dialects.Maruku.block.block_meta = function block_meta( block, next ) {
44436  // check if the last line of the block is an meta hash
44437  var m = block.match( /(^|\n) {0,3}\{:\s*((?:\\\}|[^\}])*)\s*\}$/ );
44438  if ( !m ) return undefined;
44439
44440  // process the meta hash
44441  var attr = this.dialect.processMetaHash( m[ 2 ] );
44442
44443  var hash;
44444
44445  // if we matched ^ then we need to apply meta to the previous block
44446  if ( m[ 1 ] === "" ) {
44447    var node = this.tree[ this.tree.length - 1 ];
44448    hash = extract_attr( node );
44449
44450    // if the node is a string (rather than JsonML), bail
44451    if ( typeof node === "string" ) return undefined;
44452
44453    // create the attribute hash if it doesn't exist
44454    if ( !hash ) {
44455      hash = {};
44456      node.splice( 1, 0, hash );
44457    }
44458
44459    // add the attributes in
44460    for ( a in attr ) {
44461      hash[ a ] = attr[ a ];
44462    }
44463
44464    // return nothing so the meta hash is removed
44465    return [];
44466  }
44467
44468  // pull the meta hash off the block and process what's left
44469  var b = block.replace( /\n.*$/, "" ),
44470      result = this.processBlock( b, [] );
44471
44472  // get or make the attributes hash
44473  hash = extract_attr( result[ 0 ] );
44474  if ( !hash ) {
44475    hash = {};
44476    result[ 0 ].splice( 1, 0, hash );
44477  }
44478
44479  // attach the attributes to the block
44480  for ( a in attr ) {
44481    hash[ a ] = attr[ a ];
44482  }
44483
44484  return result;
44485};
44486
44487Markdown.dialects.Maruku.block.definition_list = function definition_list( block, next ) {
44488  // one or more terms followed by one or more definitions, in a single block
44489  var tight = /^((?:[^\s:].*\n)+):\s+([\s\S]+)$/,
44490      list = [ "dl" ],
44491      i, m;
44492
44493  // see if we're dealing with a tight or loose block
44494  if ( ( m = block.match( tight ) ) ) {
44495    // pull subsequent tight DL blocks out of `next`
44496    var blocks = [ block ];
44497    while ( next.length && tight.exec( next[ 0 ] ) ) {
44498      blocks.push( next.shift() );
44499    }
44500
44501    for ( var b = 0; b < blocks.length; ++b ) {
44502      var m = blocks[ b ].match( tight ),
44503          terms = m[ 1 ].replace( /\n$/, "" ).split( /\n/ ),
44504          defns = m[ 2 ].split( /\n:\s+/ );
44505
44506      // print( uneval( m ) );
44507
44508      for ( i = 0; i < terms.length; ++i ) {
44509        list.push( [ "dt", terms[ i ] ] );
44510      }
44511
44512      for ( i = 0; i < defns.length; ++i ) {
44513        // run inline processing over the definition
44514        list.push( [ "dd" ].concat( this.processInline( defns[ i ].replace( /(\n)\s+/, "$1" ) ) ) );
44515      }
44516    }
44517  }
44518  else {
44519    return undefined;
44520  }
44521
44522  return [ list ];
44523};
44524
44525// splits on unescaped instances of @ch. If @ch is not a character the result
44526// can be unpredictable
44527
44528Markdown.dialects.Maruku.block.table = function table (block, next) {
44529
44530    var _split_on_unescaped = function(s, ch) {
44531        ch = ch || '\\s';
44532        if (ch.match(/^[\\|\[\]{}?*.+^$]$/)) { ch = '\\' + ch; }
44533        var res = [ ],
44534            r = new RegExp('^((?:\\\\.|[^\\\\' + ch + '])*)' + ch + '(.*)'),
44535            m;
44536        while(m = s.match(r)) {
44537            res.push(m[1]);
44538            s = m[2];
44539        }
44540        res.push(s);
44541        return res;
44542    }
44543
44544    var leading_pipe = /^ {0,3}\|(.+)\n {0,3}\|\s*([\-:]+[\-| :]*)\n((?:\s*\|.*(?:\n|$))*)(?=\n|$)/,
44545        // find at least an unescaped pipe in each line
44546        no_leading_pipe = /^ {0,3}(\S(?:\\.|[^\\|])*\|.*)\n {0,3}([\-:]+\s*\|[\-| :]*)\n((?:(?:\\.|[^\\|])*\|.*(?:\n|$))*)(?=\n|$)/,
44547        i, m;
44548    if (m = block.match(leading_pipe)) {
44549        // remove leading pipes in contents
44550        // (header and horizontal rule already have the leading pipe left out)
44551        m[3] = m[3].replace(/^\s*\|/gm, '');
44552    } else if (! ( m = block.match(no_leading_pipe))) {
44553        return undefined;
44554    }
44555
44556    var table = [ "table", [ "thead", [ "tr" ] ], [ "tbody" ] ];
44557
44558    // remove trailing pipes, then split on pipes
44559    // (no escaped pipes are allowed in horizontal rule)
44560    m[2] = m[2].replace(/\|\s*$/, '').split('|');
44561
44562    // process alignment
44563    var html_attrs = [ ];
44564    forEach (m[2], function (s) {
44565        if (s.match(/^\s*-+:\s*$/))       html_attrs.push({align: "right"});
44566        else if (s.match(/^\s*:-+\s*$/))  html_attrs.push({align: "left"});
44567        else if (s.match(/^\s*:-+:\s*$/)) html_attrs.push({align: "center"});
44568        else                              html_attrs.push({});
44569    });
44570
44571    // now for the header, avoid escaped pipes
44572    m[1] = _split_on_unescaped(m[1].replace(/\|\s*$/, ''), '|');
44573    for (i = 0; i < m[1].length; i++) {
44574        table[1][1].push(['th', html_attrs[i] || {}].concat(
44575            this.processInline(m[1][i].trim())));
44576    }
44577
44578    // now for body contents
44579    forEach (m[3].replace(/\|\s*$/mg, '').split('\n'), function (row) {
44580        var html_row = ['tr'];
44581        row = _split_on_unescaped(row, '|');
44582        for (i = 0; i < row.length; i++) {
44583            html_row.push(['td', html_attrs[i] || {}].concat(this.processInline(row[i].trim())));
44584        }
44585        table[2].push(html_row);
44586    }, this);
44587
44588    return [table];
44589}
44590
44591Markdown.dialects.Maruku.inline[ "{:" ] = function inline_meta( text, matches, out ) {
44592  if ( !out.length ) {
44593    return [ 2, "{:" ];
44594  }
44595
44596  // get the preceeding element
44597  var before = out[ out.length - 1 ];
44598
44599  if ( typeof before === "string" ) {
44600    return [ 2, "{:" ];
44601  }
44602
44603  // match a meta hash
44604  var m = text.match( /^\{:\s*((?:\\\}|[^\}])*)\s*\}/ );
44605
44606  // no match, false alarm
44607  if ( !m ) {
44608    return [ 2, "{:" ];
44609  }
44610
44611  // attach the attributes to the preceeding element
44612  var meta = this.dialect.processMetaHash( m[ 1 ] ),
44613      attr = extract_attr( before );
44614
44615  if ( !attr ) {
44616    attr = {};
44617    before.splice( 1, 0, attr );
44618  }
44619
44620  for ( var k in meta ) {
44621    attr[ k ] = meta[ k ];
44622  }
44623
44624  // cut out the string and replace it with nothing
44625  return [ m[ 0 ].length, "" ];
44626};
44627
44628Markdown.dialects.Maruku.inline.__escape__ = /^\\[\\`\*_{}\[\]()#\+.!\-|:]/;
44629
44630Markdown.buildBlockOrder ( Markdown.dialects.Maruku.block );
44631Markdown.buildInlinePatterns( Markdown.dialects.Maruku.inline );
44632
44633var isArray = Array.isArray || function(obj) {
44634  return Object.prototype.toString.call(obj) == "[object Array]";
44635};
44636
44637var forEach;
44638// Don't mess with Array.prototype. Its not friendly
44639if ( Array.prototype.forEach ) {
44640  forEach = function( arr, cb, thisp ) {
44641    return arr.forEach( cb, thisp );
44642  };
44643}
44644else {
44645  forEach = function(arr, cb, thisp) {
44646    for (var i = 0; i < arr.length; i++) {
44647      cb.call(thisp || arr, arr[i], i, arr);
44648    }
44649  }
44650}
44651
44652var isEmpty = function( obj ) {
44653  for ( var key in obj ) {
44654    if ( hasOwnProperty.call( obj, key ) ) {
44655      return false;
44656    }
44657  }
44658
44659  return true;
44660}
44661
44662function extract_attr( jsonml ) {
44663  return isArray(jsonml)
44664      && jsonml.length > 1
44665      && typeof jsonml[ 1 ] === "object"
44666      && !( isArray(jsonml[ 1 ]) )
44667      ? jsonml[ 1 ]
44668      : undefined;
44669}
44670
44671
44672
44673/**
44674 *  renderJsonML( jsonml[, options] ) -> String
44675 *  - jsonml (Array): JsonML array to render to XML
44676 *  - options (Object): options
44677 *
44678 *  Converts the given JsonML into well-formed XML.
44679 *
44680 *  The options currently understood are:
44681 *
44682 *  - root (Boolean): wether or not the root node should be included in the
44683 *    output, or just its children. The default `false` is to not include the
44684 *    root itself.
44685 */
44686expose.renderJsonML = function( jsonml, options ) {
44687  options = options || {};
44688  // include the root element in the rendered output?
44689  options.root = options.root || false;
44690
44691  var content = [];
44692
44693  if ( options.root ) {
44694    content.push( render_tree( jsonml ) );
44695  }
44696  else {
44697    jsonml.shift(); // get rid of the tag
44698    if ( jsonml.length && typeof jsonml[ 0 ] === "object" && !( jsonml[ 0 ] instanceof Array ) ) {
44699      jsonml.shift(); // get rid of the attributes
44700    }
44701
44702    while ( jsonml.length ) {
44703      content.push( render_tree( jsonml.shift() ) );
44704    }
44705  }
44706
44707  return content.join( "\n\n" );
44708};
44709
44710function escapeHTML( text ) {
44711  return text.replace( /&/g, "&amp;" )
44712             .replace( /</g, "&lt;" )
44713             .replace( />/g, "&gt;" )
44714             .replace( /"/g, "&quot;" )
44715             .replace( /'/g, "&#39;" );
44716}
44717
44718function render_tree( jsonml ) {
44719  // basic case
44720  if ( typeof jsonml === "string" ) {
44721    return escapeHTML( jsonml );
44722  }
44723
44724  var tag = jsonml.shift(),
44725      attributes = {},
44726      content = [];
44727
44728  if ( jsonml.length && typeof jsonml[ 0 ] === "object" && !( jsonml[ 0 ] instanceof Array ) ) {
44729    attributes = jsonml.shift();
44730  }
44731
44732  while ( jsonml.length ) {
44733    content.push( render_tree( jsonml.shift() ) );
44734  }
44735
44736  var tag_attrs = "";
44737  for ( var a in attributes ) {
44738    tag_attrs += " " + a + '="' + escapeHTML( attributes[ a ] ) + '"';
44739  }
44740
44741  // be careful about adding whitespace here for inline elements
44742  if ( tag == "img" || tag == "br" || tag == "hr" ) {
44743    return "<"+ tag + tag_attrs + "/>";
44744  }
44745  else {
44746    return "<"+ tag + tag_attrs + ">" + content.join( "" ) + "</" + tag + ">";
44747  }
44748}
44749
44750function convert_tree_to_html( tree, references, options ) {
44751  var i;
44752  options = options || {};
44753
44754  // shallow clone
44755  var jsonml = tree.slice( 0 );
44756
44757  if ( typeof options.preprocessTreeNode === "function" ) {
44758      jsonml = options.preprocessTreeNode(jsonml, references);
44759  }
44760
44761  // Clone attributes if they exist
44762  var attrs = extract_attr( jsonml );
44763  if ( attrs ) {
44764    jsonml[ 1 ] = {};
44765    for ( i in attrs ) {
44766      jsonml[ 1 ][ i ] = attrs[ i ];
44767    }
44768    attrs = jsonml[ 1 ];
44769  }
44770
44771  // basic case
44772  if ( typeof jsonml === "string" ) {
44773    return jsonml;
44774  }
44775
44776  // convert this node
44777  switch ( jsonml[ 0 ] ) {
44778    case "header":
44779      jsonml[ 0 ] = "h" + jsonml[ 1 ].level;
44780      delete jsonml[ 1 ].level;
44781      break;
44782    case "bulletlist":
44783      jsonml[ 0 ] = "ul";
44784      break;
44785    case "numberlist":
44786      jsonml[ 0 ] = "ol";
44787      break;
44788    case "listitem":
44789      jsonml[ 0 ] = "li";
44790      break;
44791    case "para":
44792      jsonml[ 0 ] = "p";
44793      break;
44794    case "markdown":
44795      jsonml[ 0 ] = "html";
44796      if ( attrs ) delete attrs.references;
44797      break;
44798    case "code_block":
44799      jsonml[ 0 ] = "pre";
44800      i = attrs ? 2 : 1;
44801      var code = [ "code" ];
44802      code.push.apply( code, jsonml.splice( i, jsonml.length - i ) );
44803      jsonml[ i ] = code;
44804      break;
44805    case "inlinecode":
44806      jsonml[ 0 ] = "code";
44807      break;
44808    case "img":
44809      jsonml[ 1 ].src = jsonml[ 1 ].href;
44810      delete jsonml[ 1 ].href;
44811      break;
44812    case "linebreak":
44813      jsonml[ 0 ] = "br";
44814    break;
44815    case "link":
44816      jsonml[ 0 ] = "a";
44817      break;
44818    case "link_ref":
44819      jsonml[ 0 ] = "a";
44820
44821      // grab this ref and clean up the attribute node
44822      var ref = references[ attrs.ref ];
44823
44824      // if the reference exists, make the link
44825      if ( ref ) {
44826        delete attrs.ref;
44827
44828        // add in the href and title, if present
44829        attrs.href = ref.href;
44830        if ( ref.title ) {
44831          attrs.title = ref.title;
44832        }
44833
44834        // get rid of the unneeded original text
44835        delete attrs.original;
44836      }
44837      // the reference doesn't exist, so revert to plain text
44838      else {
44839        return attrs.original;
44840      }
44841      break;
44842    case "img_ref":
44843      jsonml[ 0 ] = "img";
44844
44845      // grab this ref and clean up the attribute node
44846      var ref = references[ attrs.ref ];
44847
44848      // if the reference exists, make the link
44849      if ( ref ) {
44850        delete attrs.ref;
44851
44852        // add in the href and title, if present
44853        attrs.src = ref.href;
44854        if ( ref.title ) {
44855          attrs.title = ref.title;
44856        }
44857
44858        // get rid of the unneeded original text
44859        delete attrs.original;
44860      }
44861      // the reference doesn't exist, so revert to plain text
44862      else {
44863        return attrs.original;
44864      }
44865      break;
44866  }
44867
44868  // convert all the children
44869  i = 1;
44870
44871  // deal with the attribute node, if it exists
44872  if ( attrs ) {
44873    // if there are keys, skip over it
44874    for ( var key in jsonml[ 1 ] ) {
44875        i = 2;
44876        break;
44877    }
44878    // if there aren't, remove it
44879    if ( i === 1 ) {
44880      jsonml.splice( i, 1 );
44881    }
44882  }
44883
44884  for ( ; i < jsonml.length; ++i ) {
44885    jsonml[ i ] = convert_tree_to_html( jsonml[ i ], references, options );
44886  }
44887
44888  return jsonml;
44889}
44890
44891
44892// merges adjacent text nodes into a single node
44893function merge_text_nodes( jsonml ) {
44894  // skip the tag name and attribute hash
44895  var i = extract_attr( jsonml ) ? 2 : 1;
44896
44897  while ( i < jsonml.length ) {
44898    // if it's a string check the next item too
44899    if ( typeof jsonml[ i ] === "string" ) {
44900      if ( i + 1 < jsonml.length && typeof jsonml[ i + 1 ] === "string" ) {
44901        // merge the second string into the first and remove it
44902        jsonml[ i ] += jsonml.splice( i + 1, 1 )[ 0 ];
44903      }
44904      else {
44905        ++i;
44906      }
44907    }
44908    // if it's not a string recurse
44909    else {
44910      merge_text_nodes( jsonml[ i ] );
44911      ++i;
44912    }
44913  }
44914}
44915
44916} )( (function() {
44917  if ( typeof exports === "undefined" ) {
44918    window.markdown = {};
44919    return window.markdown;
44920  }
44921  else {
44922    return exports;
44923  }
44924} )() );
44925
44926/* ===================================================
44927 * bootstrap-markdown.js v2.10.0
44928 * http://github.com/toopay/bootstrap-markdown
44929 * ===================================================
44930 * Copyright 2013-2016 Taufan Aditya
44931 *
44932 * Licensed under the Apache License, Version 2.0 (the "License");
44933 * you may not use this file except in compliance with the License.
44934 * You may obtain a copy of the License at
44935 *
44936 * http://www.apache.org/licenses/LICENSE-2.0
44937 *
44938 * Unless required by applicable law or agreed to in writing, software
44939 * distributed under the License is distributed on an "AS IS" BASIS,
44940 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
44941 * See the License for the specific language governing permissions and
44942 * limitations under the License.
44943 * ========================================================== */
44944
44945(function(factory){
44946    if (typeof define === "function" && define.amd) {
44947        //RequireJS
44948        define(["jquery"], factory);
44949    } else if (typeof exports === 'object') {
44950        //Backbone.js
44951        factory(require('jquery'));
44952    } else {
44953        //Jquery plugin
44954        factory(jQuery);
44955    }
44956}(function($){
44957  "use strict"; // jshint ;_;
44958
44959  /* MARKDOWN CLASS DEFINITION
44960   * ========================== */
44961
44962  var Markdown = function (element, options) {
44963    // @TODO : remove this BC on next major release
44964    // @see : https://github.com/toopay/bootstrap-markdown/issues/109
44965    var opts = ['autofocus', 'savable', 'hideable', 'width', 
44966      'height', 'resize', 'iconlibrary', 'language', 
44967      'footer', 'fullscreen', 'hiddenButtons', 'disabledButtons'];
44968    $.each(opts,function(_, opt){
44969      if (typeof $(element).data(opt) !== 'undefined') {
44970        options = typeof options == 'object' ? options : {}
44971        options[opt] = $(element).data(opt)
44972      }
44973    });
44974    // End BC
44975
44976    // Class Properties
44977    this.$ns           = 'bootstrap-markdown';
44978    this.$element      = $(element);
44979    this.$editable     = {el:null, type:null,attrKeys:[], attrValues:[], content:null};
44980    this.$options      = $.extend(true, {}, $.fn.markdown.defaults, options, this.$element.data('options'));
44981    this.$oldContent   = null;
44982    this.$isPreview    = false;
44983    this.$isFullscreen = false;
44984    this.$editor       = null;
44985    this.$textarea     = null;
44986    this.$handler      = [];
44987    this.$callback     = [];
44988    this.$nextTab      = [];
44989
44990    this.showEditor();
44991  };
44992
44993  Markdown.prototype = {
44994
44995    constructor: Markdown
44996
44997  , __alterButtons: function(name,alter) {
44998      var handler = this.$handler, isAll = (name == 'all'),that = this;
44999
45000      $.each(handler,function(k,v) {
45001        var halt = true;
45002        if (isAll) {
45003          halt = false;
45004        } else {
45005          halt = v.indexOf(name) < 0;
45006        }
45007
45008        if (halt === false) {
45009          alter(that.$editor.find('button[data-handler="'+v+'"]'));
45010        }
45011      });
45012    }
45013
45014  , __buildButtons: function(buttonsArray, container) {
45015      var i,
45016          ns = this.$ns,
45017          handler = this.$handler,
45018          callback = this.$callback;
45019
45020      for (i=0;i<buttonsArray.length;i++) {
45021        // Build each group container
45022        var y, btnGroups = buttonsArray[i];
45023        for (y=0;y<btnGroups.length;y++) {
45024          // Build each button group
45025          var z,
45026              buttons = btnGroups[y].data,
45027              btnGroupContainer = $('<div/>', {
45028                                    'class': 'btn-group'
45029                                  });
45030
45031          for (z=0;z<buttons.length;z++) {
45032            var button = buttons[z],
45033                buttonContainer, buttonIconContainer,
45034                buttonHandler = ns+'-'+button.name,
45035                buttonIcon = this.__getIcon(button.icon),
45036                btnText = button.btnText ? button.btnText : '',
45037                btnClass = button.btnClass ? button.btnClass : 'btn',
45038                tabIndex = button.tabIndex ? button.tabIndex : '-1',
45039                hotkey = typeof button.hotkey !== 'undefined' ? button.hotkey : '',
45040                hotkeyCaption = typeof jQuery.hotkeys !== 'undefined' && hotkey !== '' ? ' ('+hotkey+')' : '';
45041
45042            // Construct the button object
45043            buttonContainer = $('<button></button>');
45044            buttonContainer.text(' ' + this.__localize(btnText)).addClass('btn-default btn-sm').addClass(btnClass);
45045            if(btnClass.match(/btn\-(primary|success|info|warning|danger|link)/)){
45046                buttonContainer.removeClass('btn-default');
45047            }
45048            buttonContainer.attr({
45049                'type': 'button',
45050                'title': this.__localize(button.title) + hotkeyCaption,
45051                'tabindex': tabIndex,
45052                'data-provider': ns,
45053                'data-handler': buttonHandler,
45054                'data-hotkey': hotkey
45055            });
45056            if (button.toggle === true){
45057              buttonContainer.attr('data-toggle', 'button');
45058            }
45059            buttonIconContainer = $('<span/>');
45060            buttonIconContainer.addClass(buttonIcon);
45061            buttonIconContainer.prependTo(buttonContainer);
45062
45063            // Attach the button object
45064            btnGroupContainer.append(buttonContainer);
45065
45066            // Register handler and callback
45067            handler.push(buttonHandler);
45068            callback.push(button.callback);
45069          }
45070
45071          // Attach the button group into container dom
45072          container.append(btnGroupContainer);
45073        }
45074      }
45075
45076      return container;
45077    }
45078  , __setListener: function() {
45079      // Set size and resizable Properties
45080      var hasRows = typeof this.$textarea.attr('rows') !== 'undefined',
45081          maxRows = this.$textarea.val().split("\n").length > 5 ? this.$textarea.val().split("\n").length : '5',
45082          rowsVal = hasRows ? this.$textarea.attr('rows') : maxRows;
45083
45084      this.$textarea.attr('rows',rowsVal);
45085      if (this.$options.resize) {
45086        this.$textarea.css('resize',this.$options.resize);
45087      }
45088
45089      this.$textarea.on({
45090          'focus' : $.proxy(this.focus, this),
45091          'keyup' : $.proxy(this.keyup, this),
45092          'change' : $.proxy(this.change, this),
45093          'select' : $.proxy(this.select, this)
45094      });
45095
45096      if (this.eventSupported('keydown')) {
45097        this.$textarea.on('keydown', $.proxy(this.keydown, this));
45098      }
45099
45100      if (this.eventSupported('keypress')) {
45101        this.$textarea.on('keypress', $.proxy(this.keypress, this))
45102      }
45103
45104      // Re-attach markdown data
45105      this.$textarea.data('markdown',this);
45106    }
45107
45108  , __handle: function(e) {
45109      var target = $(e.currentTarget),
45110          handler = this.$handler,
45111          callback = this.$callback,
45112          handlerName = target.attr('data-handler'),
45113          callbackIndex = handler.indexOf(handlerName),
45114          callbackHandler = callback[callbackIndex];
45115
45116      // Trigger the focusin
45117      $(e.currentTarget).focus();
45118
45119      callbackHandler(this);
45120
45121      // Trigger onChange for each button handle
45122      this.change(this);
45123
45124      // Unless it was the save handler,
45125      // focusin the textarea
45126      if (handlerName.indexOf('cmdSave') < 0) {
45127        this.$textarea.focus();
45128      }
45129
45130      e.preventDefault();
45131    }
45132
45133  , __localize: function(string) {
45134      var messages = $.fn.markdown.messages,
45135          language = this.$options.language;
45136      if (
45137        typeof messages !== 'undefined' &&
45138        typeof messages[language] !== 'undefined' &&
45139        typeof messages[language][string] !== 'undefined'
45140      ) {
45141        return messages[language][string];
45142      }
45143      return string;
45144    }
45145
45146  , __getIcon: function(src) {
45147    return typeof src == 'object' ? src[this.$options.iconlibrary] : src;
45148  }
45149
45150  , setFullscreen: function(mode) {
45151    var $editor = this.$editor,
45152        $textarea = this.$textarea;
45153
45154    if (mode === true) {
45155      $editor.addClass('md-fullscreen-mode');
45156      $('body').addClass('md-nooverflow');
45157      this.$options.onFullscreen(this);
45158    } else {
45159      $editor.removeClass('md-fullscreen-mode');
45160      $('body').removeClass('md-nooverflow');
45161
45162      if (this.$isPreview == true) this.hidePreview().showPreview()
45163    }
45164
45165    this.$isFullscreen = mode;
45166    $textarea.focus();
45167  }
45168
45169  , showEditor: function() {
45170      var instance = this,
45171          textarea,
45172          ns = this.$ns,
45173          container = this.$element,
45174          originalHeigth = container.css('height'),
45175          originalWidth = container.css('width'),
45176          editable = this.$editable,
45177          handler = this.$handler,
45178          callback = this.$callback,
45179          options = this.$options,
45180          editor = $( '<div/>', {
45181                      'class': 'md-editor',
45182                      click: function() {
45183                        instance.focus();
45184                      }
45185                    });
45186
45187      // Prepare the editor
45188      if (this.$editor === null) {
45189        // Create the panel
45190        var editorHeader = $('<div/>', {
45191                            'class': 'md-header btn-toolbar'
45192                            });
45193
45194        // Merge the main & additional button groups together
45195        var allBtnGroups = [];
45196        if (options.buttons.length > 0) allBtnGroups = allBtnGroups.concat(options.buttons[0]);
45197        if (options.additionalButtons.length > 0) {
45198          // iterate the additional button groups
45199          $.each(options.additionalButtons[0], function(idx, buttonGroup){
45200            
45201            // see if the group name of the addional group matches an existing group
45202            var matchingGroups = $.grep(allBtnGroups, function(allButtonGroup, allIdx){
45203              return allButtonGroup.name === buttonGroup.name;
45204            });
45205
45206            // if it matches add the addional buttons to that group, if not just add it to the all buttons group
45207            if(matchingGroups.length > 0) {
45208              matchingGroups[0].data = matchingGroups[0].data.concat(buttonGroup.data);
45209            } else {              
45210              allBtnGroups.push(options.additionalButtons[0][idx]);
45211            }
45212
45213          });
45214        } 
45215
45216        // Reduce and/or reorder the button groups
45217        if (options.reorderButtonGroups.length > 0) {
45218          allBtnGroups = allBtnGroups
45219              .filter(function(btnGroup) {
45220                return options.reorderButtonGroups.indexOf(btnGroup.name) > -1;
45221              })
45222              .sort(function(a, b) {
45223                if (options.reorderButtonGroups.indexOf(a.name) < options.reorderButtonGroups.indexOf(b.name)) return -1;
45224                if (options.reorderButtonGroups.indexOf(a.name) > options.reorderButtonGroups.indexOf(b.name)) return 1;
45225                return 0;
45226              });
45227        }
45228
45229        // Build the buttons
45230        if (allBtnGroups.length > 0) {
45231          editorHeader = this.__buildButtons([allBtnGroups], editorHeader);
45232        }
45233
45234        if (options.fullscreen.enable) {
45235          editorHeader.append('<div class="md-controls"><a class="md-control md-control-fullscreen" href="#"><span class="'+this.__getIcon(options.fullscreen.icons.fullscreenOn)+'"></span></a></div>').on('click', '.md-control-fullscreen', function(e) {
45236              e.preventDefault();
45237              instance.setFullscreen(true);
45238          });
45239        }
45240
45241        editor.append(editorHeader);
45242
45243        // Wrap the textarea
45244        if (container.is('textarea')) {
45245          container.before(editor);
45246          textarea = container;
45247          textarea.addClass('md-input');
45248          editor.append(textarea);
45249        } else {
45250          var rawContent = (typeof toMarkdown == 'function') ? toMarkdown(container.html()) : container.html(),
45251              currentContent = $.trim(rawContent);
45252
45253          // This is some arbitrary content that could be edited
45254          textarea = $('<textarea/>', {
45255                       'class': 'md-input',
45256                       'val' : currentContent
45257                      });
45258
45259          editor.append(textarea);
45260
45261          // Save the editable
45262          editable.el = container;
45263          editable.type = container.prop('tagName').toLowerCase();
45264          editable.content = container.html();
45265
45266          $(container[0].attributes).each(function(){
45267            editable.attrKeys.push(this.nodeName);
45268            editable.attrValues.push(this.nodeValue);
45269          });
45270
45271          // Set editor to blocked the original container
45272          container.replaceWith(editor);
45273        }
45274
45275        var editorFooter = $('<div/>', {
45276                           'class': 'md-footer'
45277                         }),
45278            createFooter = false,
45279            footer = '';
45280        // Create the footer if savable
45281        if (options.savable) {
45282          createFooter = true;
45283          var saveHandler = 'cmdSave';
45284
45285          // Register handler and callback
45286          handler.push(saveHandler);
45287          callback.push(options.onSave);
45288
45289          editorFooter.append('<button class="btn btn-success" data-provider="'
45290                              + ns
45291                              + '" data-handler="'
45292                              + saveHandler
45293                              + '"><i class="icon icon-white icon-ok"></i> '
45294                              + this.__localize('Save')
45295                              + '</button>');
45296
45297
45298        }
45299
45300        footer = typeof options.footer === 'function' ? options.footer(this) : options.footer;
45301
45302        if ($.trim(footer) !== '') {
45303          createFooter = true;
45304          editorFooter.append(footer);
45305        }
45306
45307        if (createFooter) editor.append(editorFooter);
45308
45309        // Set width
45310        if (options.width && options.width !== 'inherit') {
45311          if (jQuery.isNumeric(options.width)) {
45312            editor.css('display', 'table');
45313            textarea.css('width', options.width + 'px');
45314          } else {
45315            editor.addClass(options.width);
45316          }
45317        }
45318
45319        // Set height
45320        if (options.height && options.height !== 'inherit') {
45321          if (jQuery.isNumeric(options.height)) {
45322            var height = options.height;
45323            if (editorHeader) height = Math.max(0, height - editorHeader.outerHeight());
45324            if (editorFooter) height = Math.max(0, height - editorFooter.outerHeight());
45325            textarea.css('height', height + 'px');
45326          } else {
45327            editor.addClass(options.height);
45328          }
45329        }
45330
45331        // Reference
45332        this.$editor     = editor;
45333        this.$textarea   = textarea;
45334        this.$editable   = editable;
45335        this.$oldContent = this.getContent();
45336
45337        this.__setListener();
45338
45339        // Set editor attributes, data short-hand API and listener
45340        this.$editor.attr('id',(new Date()).getTime());
45341        this.$editor.on('click', '[data-provider="bootstrap-markdown"]', $.proxy(this.__handle, this));
45342
45343        if (this.$element.is(':disabled') || this.$element.is('[readonly]')) {
45344          this.$editor.addClass('md-editor-disabled');
45345          this.disableButtons('all');
45346        }
45347
45348        if (this.eventSupported('keydown') && typeof jQuery.hotkeys === 'object') {
45349          editorHeader.find('[data-provider="bootstrap-markdown"]').each(function() {
45350            var $button = $(this),
45351                hotkey = $button.attr('data-hotkey');
45352            if (hotkey.toLowerCase() !== '') {
45353              textarea.bind('keydown', hotkey, function() {
45354                $button.trigger('click');
45355                return false;
45356              });
45357            }
45358          });
45359        }
45360
45361        if (options.initialstate === 'preview') {
45362          this.showPreview();
45363        } else if (options.initialstate === 'fullscreen' && options.fullscreen.enable) {
45364          this.setFullscreen(true);
45365        }
45366
45367      } else {
45368        this.$editor.show();
45369      }
45370
45371      if (options.autofocus) {
45372        this.$textarea.focus();
45373        this.$editor.addClass('active');
45374      }
45375
45376      if (options.fullscreen.enable && options.fullscreen !== false) {
45377        this.$editor.append('<div class="md-fullscreen-controls">'
45378                        + '<a href="#" class="exit-fullscreen" title="Exit fullscreen"><span class="' + this.__getIcon(options.fullscreen.icons.fullscreenOff) + '">'
45379                        + '</span></a>'
45380                        + '</div>');
45381        this.$editor.on('click', '.exit-fullscreen', function(e) {
45382          e.preventDefault();
45383          instance.setFullscreen(false);
45384        });
45385      }
45386
45387      // hide hidden buttons from options
45388      this.hideButtons(options.hiddenButtons);
45389
45390      // disable disabled buttons from options
45391      this.disableButtons(options.disabledButtons);
45392
45393      // Trigger the onShow hook
45394      options.onShow(this);
45395
45396      return this;
45397    }
45398
45399  , parseContent: function(val) {
45400      var content;
45401
45402      // parse with supported markdown parser
45403      var val = val || this.$textarea.val();
45404
45405      if (this.$options.parser) {
45406        content = this.$options.parser(val);
45407      } else if (typeof markdown == 'object') {
45408        content = markdown.toHTML(val);
45409      } else if (typeof marked == 'function') {
45410        content = marked(val);
45411      } else {
45412        content = val;
45413      }
45414
45415      return content;
45416    }
45417
45418  , showPreview: function() {
45419      var options = this.$options,
45420          container = this.$textarea,
45421          afterContainer = container.next(),
45422          replacementContainer = $('<div/>',{'class':'md-preview','data-provider':'markdown-preview'}),
45423          content,
45424          callbackContent;
45425
45426      if (this.$isPreview == true) {
45427        // Avoid sequenced element creation on missused scenario
45428        // @see https://github.com/toopay/bootstrap-markdown/issues/170
45429        return this;
45430      }
45431      
45432      // Give flag that tell the editor enter preview mode
45433      this.$isPreview = true;
45434      // Disable all buttons
45435      this.disableButtons('all').enableButtons('cmdPreview');
45436
45437      // Try to get the content from callback
45438      callbackContent = options.onPreview(this);
45439      // Set the content based from the callback content if string otherwise parse value from textarea
45440      content = typeof callbackContent == 'string' ? callbackContent : this.parseContent();
45441
45442      // Build preview element
45443      replacementContainer.html(content);
45444
45445      if (afterContainer && afterContainer.attr('class') == 'md-footer') {
45446        // If there is footer element, insert the preview container before it
45447        replacementContainer.insertBefore(afterContainer);
45448      } else {
45449        // Otherwise, just append it after textarea
45450        container.parent().append(replacementContainer);
45451      }
45452
45453      // Set the preview element dimensions
45454      replacementContainer.css({
45455        width: container.outerWidth() + 'px',
45456        height: container.outerHeight() + 'px'
45457      });
45458
45459      if (this.$options.resize) {
45460        replacementContainer.css('resize',this.$options.resize);
45461      }
45462
45463      // Hide the last-active textarea
45464      container.hide();
45465
45466      // Attach the editor instances
45467      replacementContainer.data('markdown',this);
45468
45469      if (this.$element.is(':disabled') || this.$element.is('[readonly]')) {
45470        this.$editor.addClass('md-editor-disabled');
45471        this.disableButtons('all');
45472      }
45473
45474      return this;
45475    }
45476
45477  , hidePreview: function() {
45478      // Give flag that tell the editor quit preview mode
45479      this.$isPreview = false;
45480
45481      // Obtain the preview container
45482      var container = this.$editor.find('div[data-provider="markdown-preview"]');
45483
45484      // Remove the preview container
45485      container.remove();
45486
45487      // Enable all buttons
45488      this.enableButtons('all');
45489      // Disable configured disabled buttons
45490      this.disableButtons(this.$options.disabledButtons);
45491
45492      // Back to the editor
45493      this.$textarea.show();
45494      this.__setListener();
45495
45496      return this;
45497    }
45498
45499  , isDirty: function() {
45500      return this.$oldContent != this.getContent();
45501    }
45502
45503  , getContent: function() {
45504      return this.$textarea.val();
45505    }
45506
45507  , setContent: function(content) {
45508      this.$textarea.val(content);
45509
45510      return this;
45511    }
45512
45513  , findSelection: function(chunk) {
45514    var content = this.getContent(), startChunkPosition;
45515
45516    if (startChunkPosition = content.indexOf(chunk), startChunkPosition >= 0 && chunk.length > 0) {
45517      var oldSelection = this.getSelection(), selection;
45518
45519      this.setSelection(startChunkPosition,startChunkPosition+chunk.length);
45520      selection = this.getSelection();
45521
45522      this.setSelection(oldSelection.start,oldSelection.end);
45523
45524      return selection;
45525    } else {
45526      return null;
45527    }
45528  }
45529
45530  , getSelection: function() {
45531
45532      var e = this.$textarea[0];
45533
45534      return (
45535
45536          ('selectionStart' in e && function() {
45537              var l = e.selectionEnd - e.selectionStart;
45538              return { start: e.selectionStart, end: e.selectionEnd, length: l, text: e.value.substr(e.selectionStart, l) };
45539          }) ||
45540
45541          /* browser not supported */
45542          function() {
45543            return null;
45544          }
45545
45546      )();
45547
45548    }
45549
45550  , setSelection: function(start,end) {
45551
45552      var e = this.$textarea[0];
45553
45554      return (
45555
45556          ('selectionStart' in e && function() {
45557              e.selectionStart = start;
45558              e.selectionEnd = end;
45559              return;
45560          }) ||
45561
45562          /* browser not supported */
45563          function() {
45564            return null;
45565          }
45566
45567      )();
45568
45569    }
45570
45571  , replaceSelection: function(text) {
45572
45573      var e = this.$textarea[0];
45574
45575      return (
45576
45577          ('selectionStart' in e && function() {
45578              e.value = e.value.substr(0, e.selectionStart) + text + e.value.substr(e.selectionEnd, e.value.length);
45579              // Set cursor to the last replacement end
45580              e.selectionStart = e.value.length;
45581              return this;
45582          }) ||
45583
45584          /* browser not supported */
45585          function() {
45586              e.value += text;
45587              return jQuery(e);
45588          }
45589
45590      )();
45591    }
45592
45593  , getNextTab: function() {
45594      // Shift the nextTab
45595      if (this.$nextTab.length === 0) {
45596        return null;
45597      } else {
45598        var nextTab, tab = this.$nextTab.shift();
45599
45600        if (typeof tab == 'function') {
45601          nextTab = tab();
45602        } else if (typeof tab == 'object' && tab.length > 0) {
45603          nextTab = tab;
45604        }
45605
45606        return nextTab;
45607      }
45608    }
45609
45610  , setNextTab: function(start,end) {
45611      // Push new selection into nextTab collections
45612      if (typeof start == 'string') {
45613        var that = this;
45614        this.$nextTab.push(function(){
45615          return that.findSelection(start);
45616        });
45617      } else if (typeof start == 'number' && typeof end == 'number') {
45618        var oldSelection = this.getSelection();
45619
45620        this.setSelection(start,end);
45621        this.$nextTab.push(this.getSelection());
45622
45623        this.setSelection(oldSelection.start,oldSelection.end);
45624      }
45625
45626      return;
45627    }
45628
45629  , __parseButtonNameParam: function (names) {
45630      return typeof names == 'string' ?
45631                      names.split(' ') :
45632                      names;
45633
45634    }
45635
45636  , enableButtons: function(name) {
45637      var buttons = this.__parseButtonNameParam(name),
45638        that = this;
45639
45640      $.each(buttons, function(i, v) {
45641        that.__alterButtons(buttons[i], function (el) {
45642          el.removeAttr('disabled');
45643        });
45644      });
45645
45646      return this;
45647    }
45648
45649  , disableButtons: function(name) {
45650      var buttons = this.__parseButtonNameParam(name),
45651        that = this;
45652
45653      $.each(buttons, function(i, v) {
45654        that.__alterButtons(buttons[i], function (el) {
45655          el.attr('disabled','disabled');
45656        });
45657      });
45658
45659      return this;
45660    }
45661
45662  , hideButtons: function(name) {
45663      var buttons = this.__parseButtonNameParam(name),
45664        that = this;
45665
45666      $.each(buttons, function(i, v) {
45667        that.__alterButtons(buttons[i], function (el) {
45668          el.addClass('hidden');
45669        });
45670      });
45671
45672      return this;
45673    }
45674
45675  , showButtons: function(name) {
45676      var buttons = this.__parseButtonNameParam(name),
45677        that = this;
45678
45679      $.each(buttons, function(i, v) {
45680        that.__alterButtons(buttons[i], function (el) {
45681          el.removeClass('hidden');
45682        });
45683      });
45684
45685      return this;
45686    }
45687
45688  , eventSupported: function(eventName) {
45689      var isSupported = eventName in this.$element;
45690      if (!isSupported) {
45691        this.$element.setAttribute(eventName, 'return;');
45692        isSupported = typeof this.$element[eventName] === 'function';
45693      }
45694      return isSupported;
45695    }
45696
45697  , keyup: function (e) {
45698      var blocked = false;
45699      switch(e.keyCode) {
45700        case 40: // down arrow
45701        case 38: // up arrow
45702        case 16: // shift
45703        case 17: // ctrl
45704        case 18: // alt
45705          break;
45706
45707        case 9: // tab
45708          var nextTab;
45709          if (nextTab = this.getNextTab(),nextTab !== null) {
45710            // Get the nextTab if exists
45711            var that = this;
45712            setTimeout(function(){
45713              that.setSelection(nextTab.start,nextTab.end);
45714            },500);
45715
45716            blocked = true;
45717          } else {
45718            // The next tab memory contains nothing...
45719            // check the cursor position to determine tab action
45720            var cursor = this.getSelection();
45721
45722            if (cursor.start == cursor.end && cursor.end == this.getContent().length) {
45723              // The cursor already reach the end of the content
45724              blocked = false;
45725            } else {
45726              // Put the cursor to the end
45727              this.setSelection(this.getContent().length,this.getContent().length);
45728
45729              blocked = true;
45730            }
45731          }
45732
45733          break;
45734
45735        case 13: // enter
45736          blocked = false;
45737          break;
45738        case 27: // escape
45739          if (this.$isFullscreen) this.setFullscreen(false);
45740          blocked = false;
45741          break;
45742
45743        default:
45744          blocked = false;
45745      }
45746
45747      if (blocked) {
45748        e.stopPropagation();
45749        e.preventDefault();
45750      }
45751
45752      this.$options.onChange(this);
45753    }
45754
45755  , change: function(e) {
45756      this.$options.onChange(this);
45757      return this;
45758    }
45759  , select: function (e) {
45760      this.$options.onSelect(this);
45761      return this;
45762    }
45763  , focus: function (e) {
45764      var options = this.$options,
45765          isHideable = options.hideable,
45766          editor = this.$editor;
45767
45768      editor.addClass('active');
45769
45770      // Blur other markdown(s)
45771      $(document).find('.md-editor').each(function(){
45772        if ($(this).attr('id') !== editor.attr('id')) {
45773          var attachedMarkdown;
45774
45775          if (attachedMarkdown = $(this).find('textarea').data('markdown'),
45776              attachedMarkdown === null) {
45777              attachedMarkdown = $(this).find('div[data-provider="markdown-preview"]').data('markdown');
45778          }
45779
45780          if (attachedMarkdown) {
45781            attachedMarkdown.blur();
45782          }
45783        }
45784      });
45785
45786      // Trigger the onFocus hook
45787      options.onFocus(this);
45788
45789      return this;
45790    }
45791
45792  , blur: function (e) {
45793      var options = this.$options,
45794          isHideable = options.hideable,
45795          editor = this.$editor,
45796          editable = this.$editable;
45797
45798      if (editor.hasClass('active') || this.$element.parent().length === 0) {
45799        editor.removeClass('active');
45800
45801        if (isHideable) {
45802          // Check for editable elements
45803          if (editable.el !== null) {
45804            // Build the original element
45805            var oldElement = $('<'+editable.type+'/>'),
45806                content = this.getContent(),
45807                currentContent = this.parseContent(content);
45808
45809            $(editable.attrKeys).each(function(k,v) {
45810              oldElement.attr(editable.attrKeys[k],editable.attrValues[k]);
45811            });
45812
45813            // Get the editor content
45814            oldElement.html(currentContent);
45815
45816            editor.replaceWith(oldElement);
45817          } else {
45818            editor.hide();
45819          }
45820        }
45821
45822        // Trigger the onBlur hook
45823        options.onBlur(this);
45824      }
45825
45826      return this;
45827    }
45828
45829  };
45830
45831 /* MARKDOWN PLUGIN DEFINITION
45832  * ========================== */
45833
45834  var old = $.fn.markdown;
45835
45836  $.fn.markdown = function (option) {
45837    return this.each(function () {
45838      var $this = $(this)
45839        , data = $this.data('markdown')
45840        , options = typeof option == 'object' && option;
45841      if (!data) $this.data('markdown', (data = new Markdown(this, options)))
45842    })
45843  };
45844
45845  $.fn.markdown.messages = {};
45846
45847  $.fn.markdown.defaults = {
45848    /* Editor Properties */
45849    autofocus: false,
45850    hideable: false,
45851    savable: false,
45852    width: 'inherit',
45853    height: 'inherit',
45854    resize: 'none',
45855    iconlibrary: 'glyph',
45856    language: 'en',
45857    initialstate: 'editor',
45858    parser: null,
45859
45860    /* Buttons Properties */
45861    buttons: [
45862      [{
45863        name: 'groupFont',
45864        data: [{
45865          name: 'cmdBold',
45866          hotkey: 'Ctrl+B',
45867          title: 'Bold',
45868          icon: { glyph: 'glyphicon glyphicon-bold', fa: 'fa fa-bold', 'fa-3': 'icon-bold' },
45869          callback: function(e){
45870            // Give/remove ** surround the selection
45871            var chunk, cursor, selected = e.getSelection(), content = e.getContent();
45872
45873            if (selected.length === 0) {
45874              // Give extra word
45875              chunk = e.__localize('strong text');
45876            } else {
45877              chunk = selected.text;
45878            }
45879
45880            // transform selection and set the cursor into chunked text
45881            if (content.substr(selected.start-2,2) === '**'
45882                && content.substr(selected.end,2) === '**' ) {
45883              e.setSelection(selected.start-2,selected.end+2);
45884              e.replaceSelection(chunk);
45885              cursor = selected.start-2;
45886            } else {
45887              e.replaceSelection('**'+chunk+'**');
45888              cursor = selected.start+2;
45889            }
45890
45891            // Set the cursor
45892            e.setSelection(cursor,cursor+chunk.length);
45893          }
45894        },{
45895          name: 'cmdItalic',
45896          title: 'Italic',
45897          hotkey: 'Ctrl+I',
45898          icon: { glyph: 'glyphicon glyphicon-italic', fa: 'fa fa-italic', 'fa-3': 'icon-italic' },
45899          callback: function(e){
45900            // Give/remove * surround the selection
45901            var chunk, cursor, selected = e.getSelection(), content = e.getContent();
45902
45903            if (selected.length === 0) {
45904              // Give extra word
45905              chunk = e.__localize('emphasized text');
45906            } else {
45907              chunk = selected.text;
45908            }
45909
45910            // transform selection and set the cursor into chunked text
45911            if (content.substr(selected.start-1,1) === '_'
45912                && content.substr(selected.end,1) === '_' ) {
45913              e.setSelection(selected.start-1,selected.end+1);
45914              e.replaceSelection(chunk);
45915              cursor = selected.start-1;
45916            } else {
45917              e.replaceSelection('_'+chunk+'_');
45918              cursor = selected.start+1;
45919            }
45920
45921            // Set the cursor
45922            e.setSelection(cursor,cursor+chunk.length);
45923          }
45924        },{
45925          name: 'cmdHeading',
45926          title: 'Heading',
45927          hotkey: 'Ctrl+H',
45928          icon: { glyph: 'glyphicon glyphicon-header', fa: 'fa fa-header', 'fa-3': 'icon-font' },
45929          callback: function(e){
45930            // Append/remove ### surround the selection
45931            var chunk, cursor, selected = e.getSelection(), content = e.getContent(), pointer, prevChar;
45932
45933            if (selected.length === 0) {
45934              // Give extra word
45935              chunk = e.__localize('heading text');
45936            } else {
45937              chunk = selected.text + '\n';
45938            }
45939
45940            // transform selection and set the cursor into chunked text
45941            if ((pointer = 4, content.substr(selected.start-pointer,pointer) === '### ')
45942                || (pointer = 3, content.substr(selected.start-pointer,pointer) === '###')) {
45943              e.setSelection(selected.start-pointer,selected.end);
45944              e.replaceSelection(chunk);
45945              cursor = selected.start-pointer;
45946            } else if (selected.start > 0 && (prevChar = content.substr(selected.start-1,1), !!prevChar && prevChar != '\n')) {
45947              e.replaceSelection('\n\n### '+chunk);
45948              cursor = selected.start+6;
45949            } else {
45950              // Empty string before element
45951              e.replaceSelection('### '+chunk);
45952              cursor = selected.start+4;
45953            }
45954
45955            // Set the cursor
45956            e.setSelection(cursor,cursor+chunk.length);
45957          }
45958        }]
45959      },{
45960        name: 'groupLink',
45961        data: [{
45962          name: 'cmdUrl',
45963          title: 'URL/Link',
45964          hotkey: 'Ctrl+L',
45965          icon: { glyph: 'glyphicon glyphicon-link', fa: 'fa fa-link', 'fa-3': 'icon-link' },
45966          callback: function(e){
45967            // Give [] surround the selection and prepend the link
45968            var chunk, cursor, selected = e.getSelection(), content = e.getContent(), link;
45969
45970            if (selected.length === 0) {
45971              // Give extra word
45972              chunk = e.__localize('enter link description here');
45973            } else {
45974              chunk = selected.text;
45975            }
45976
45977            link = prompt(e.__localize('Insert Hyperlink'),'http://');
45978
45979            var urlRegex = new RegExp('^((http|https)://|(mailto:)|(//))[a-z0-9]', 'i');
45980            if (link !== null && link !== '' && link !== 'http://' && urlRegex.test(link)) {
45981              var sanitizedLink = $('<div>'+link+'</div>').text();
45982
45983              // transform selection and set the cursor into chunked text
45984              e.replaceSelection('['+chunk+']('+sanitizedLink+')');
45985              cursor = selected.start+1;
45986
45987              // Set the cursor
45988              e.setSelection(cursor,cursor+chunk.length);
45989            }
45990          }
45991        },{
45992          name: 'cmdImage',
45993          title: 'Image',
45994          hotkey: 'Ctrl+G',
45995          icon: { glyph: 'glyphicon glyphicon-picture', fa: 'fa fa-picture-o', 'fa-3': 'icon-picture' },
45996          callback: function(e){
45997            // Give ![] surround the selection and prepend the image link
45998            var chunk, cursor, selected = e.getSelection(), content = e.getContent(), link;
45999
46000            if (selected.length === 0) {
46001              // Give extra word
46002              chunk = e.__localize('enter image description here');
46003            } else {
46004              chunk = selected.text;
46005            }
46006
46007            link = prompt(e.__localize('Insert Image Hyperlink'),'http://');
46008
46009            var urlRegex = new RegExp('^((http|https)://|(//))[a-z0-9]', 'i');
46010            if (link !== null && link !== '' && link !== 'http://' && urlRegex.test(link)) {
46011              var sanitizedLink = $('<div>'+link+'</div>').text();
46012
46013              // transform selection and set the cursor into chunked text
46014              e.replaceSelection('!['+chunk+']('+sanitizedLink+' "'+e.__localize('enter image title here')+'")');
46015              cursor = selected.start+2;
46016
46017              // Set the next tab
46018              e.setNextTab(e.__localize('enter image title here'));
46019
46020              // Set the cursor
46021              e.setSelection(cursor,cursor+chunk.length);
46022            }
46023          }
46024        }]
46025      },{
46026        name: 'groupMisc',
46027        data: [{
46028          name: 'cmdList',
46029          hotkey: 'Ctrl+U',
46030          title: 'Unordered List',
46031          icon: { glyph: 'glyphicon glyphicon-list', fa: 'fa fa-list', 'fa-3': 'icon-list-ul' },
46032          callback: function(e){
46033            // Prepend/Give - surround the selection
46034            var chunk, cursor, selected = e.getSelection(), content = e.getContent();
46035
46036            // transform selection and set the cursor into chunked text
46037            if (selected.length === 0) {
46038              // Give extra word
46039              chunk = e.__localize('list text here');
46040
46041              e.replaceSelection('- '+chunk);
46042              // Set the cursor
46043              cursor = selected.start+2;
46044            } else {
46045              if (selected.text.indexOf('\n') < 0) {
46046                chunk = selected.text;
46047
46048                e.replaceSelection('- '+chunk);
46049
46050                // Set the cursor
46051                cursor = selected.start+2;
46052              } else {
46053                var list = [];
46054
46055                list = selected.text.split('\n');
46056                chunk = list[0];
46057
46058                $.each(list,function(k,v) {
46059                  list[k] = '- '+v;
46060                });
46061
46062                e.replaceSelection('\n\n'+list.join('\n'));
46063
46064                // Set the cursor
46065                cursor = selected.start+4;
46066              }
46067            }
46068
46069            // Set the cursor
46070            e.setSelection(cursor,cursor+chunk.length);
46071          }
46072        },
46073        {
46074          name: 'cmdListO',
46075          hotkey: 'Ctrl+O',
46076          title: 'Ordered List',
46077          icon: { glyph: 'glyphicon glyphicon-th-list', fa: 'fa fa-list-ol', 'fa-3': 'icon-list-ol' },
46078          callback: function(e) {
46079
46080            // Prepend/Give - surround the selection
46081            var chunk, cursor, selected = e.getSelection(), content = e.getContent();
46082
46083            // transform selection and set the cursor into chunked text
46084            if (selected.length === 0) {
46085              // Give extra word
46086              chunk = e.__localize('list text here');
46087              e.replaceSelection('1. '+chunk);
46088              // Set the cursor
46089              cursor = selected.start+3;
46090            } else {
46091              if (selected.text.indexOf('\n') < 0) {
46092                chunk = selected.text;
46093
46094                e.replaceSelection('1. '+chunk);
46095
46096                // Set the cursor
46097                cursor = selected.start+3;
46098              } else {
46099                var list = [];
46100
46101                list = selected.text.split('\n');
46102                chunk = list[0];
46103
46104                $.each(list,function(k,v) {
46105                  list[k] = '1. '+v;
46106                });
46107
46108                e.replaceSelection('\n\n'+list.join('\n'));
46109
46110                // Set the cursor
46111                cursor = selected.start+5;
46112              }
46113            }
46114
46115            // Set the cursor
46116            e.setSelection(cursor,cursor+chunk.length);
46117          }
46118        },
46119        {
46120          name: 'cmdCode',
46121          hotkey: 'Ctrl+K',
46122          title: 'Code',
46123          icon: { glyph: 'glyphicon glyphicon-asterisk', fa: 'fa fa-code', 'fa-3': 'icon-code' },
46124          callback: function(e) {
46125            // Give/remove ** surround the selection
46126            var chunk, cursor, selected = e.getSelection(), content = e.getContent();
46127
46128            if (selected.length === 0) {
46129              // Give extra word
46130              chunk = e.__localize('code text here');
46131            } else {
46132              chunk = selected.text;
46133            }
46134
46135            // transform selection and set the cursor into chunked text
46136            if (content.substr(selected.start-4,4) === '```\n'
46137                && content.substr(selected.end,4) === '\n```') {
46138              e.setSelection(selected.start-4, selected.end+4);
46139              e.replaceSel
46139ection(chunk);
46140              cursor = selected.start-4;
46141            } else if (content.substr(selected.start-1,1) === '`'
46142                && content.substr(selected.end,1) === '`') {
46143              e.setSelection(selected.start-1,selected.end+1);
46144              e.replaceSelection(chunk);
46145              cursor = selected.start-1;
46146            } else if (content.indexOf('\n') > -1) {
46147              e.replaceSelection('```\n'+chunk+'\n```');
46148              cursor = selected.start+4;
46149            } else {
46150              e.replaceSelection('`'+chunk+'`');
46151              cursor = selected.start+1;
46152            }
46153
46154            // Set the cursor
46155            e.setSelection(cursor,cursor+chunk.length);
46156          }
46157        },
46158        {
46159          name: 'cmdQuote',
46160          hotkey: 'Ctrl+Q',
46161          title: 'Quote',
46162          icon: { glyph: 'glyphicon glyphicon-comment', fa: 'fa fa-quote-left', 'fa-3': 'icon-quote-left' },
46163          callback: function(e) {
46164            // Prepend/Give - surround the selection
46165            var chunk, cursor, selected = e.getSelection(), content = e.getContent();
46166
46167            // transform selection and set the cursor into chunked text
46168            if (selected.length === 0) {
46169              // Give extra word
46170              chunk = e.__localize('quote here');
46171
46172              e.replaceSelection('> '+chunk);
46173
46174              // Set the cursor
46175              cursor = selected.start+2;
46176            } else {
46177              if (selected.text.indexOf('\n') < 0) {
46178                chunk = selected.text;
46179
46180                e.replaceSelection('> '+chunk);
46181
46182                // Set the cursor
46183                cursor = selected.start+2;
46184              } else {
46185                var list = [];
46186
46187                list = selected.text.split('\n');
46188                chunk = list[0];
46189
46190                $.each(list,function(k,v) {
46191                  list[k] = '> '+v;
46192                });
46193
46194                e.replaceSelection('\n\n'+list.join('\n'));
46195
46196                // Set the cursor
46197                cursor = selected.start+4;
46198              }
46199            }
46200
46201            // Set the cursor
46202            e.setSelection(cursor,cursor+chunk.length);
46203          }
46204        }]
46205      },{
46206        name: 'groupUtil',
46207        data: [{
46208          name: 'cmdPreview',
46209          toggle: true,
46210          hotkey: 'Ctrl+P',
46211          title: 'Preview',
46212          btnText: 'Preview',
46213          btnClass: 'btn btn-primary btn-sm',
46214          icon: { glyph: 'glyphicon glyphicon-search', fa: 'fa fa-search', 'fa-3': 'icon-search' },
46215          callback: function(e){
46216            // Check the preview mode and toggle based on this flag
46217            var isPreview = e.$isPreview,content;
46218
46219            if (isPreview === false) {
46220              // Give flag that tell the editor enter preview mode
46221              e.showPreview();
46222            } else {
46223              e.hidePreview();
46224            }
46225          }
46226        }]
46227      }]
46228    ],
46229    additionalButtons:[], // Place to hook more buttons by code
46230    reorderButtonGroups:[],
46231    hiddenButtons:[], // Default hidden buttons
46232    disabledButtons:[], // Default disabled buttons
46233    footer: '',
46234    fullscreen: {
46235      enable: true,
46236      icons: {
46237        fullscreenOn: {
46238          fa: 'fa fa-expand',
46239          glyph: 'glyphicon glyphicon-fullscreen',
46240          'fa-3': 'icon-resize-full'
46241        },
46242        fullscreenOff: {
46243          fa: 'fa fa-compress',
46244          glyph: 'glyphicon glyphicon-fullscreen',
46245          'fa-3': 'icon-resize-small'
46246        }
46247      }
46248    },
46249
46250    /* Events hook */
46251    onShow: function (e) {},
46252    onPreview: function (e) {},
46253    onSave: function (e) {},
46254    onBlur: function (e) {},
46255    onFocus: function (e) {},
46256    onChange: function(e) {},
46257    onFullscreen: function(e) {},
46258    onSelect: function (e) {}
46259  };
46260
46261  $.fn.markdown.Constructor = Markdown;
46262
46263
46264 /* MARKDOWN NO CONFLICT
46265  * ==================== */
46266
46267  $.fn.markdown.noConflict = function () {
46268    $.fn.markdown = old;
46269    return this;
46270  };
46271
46272  /* MARKDOWN GLOBAL FUNCTION & DATA-API
46273  * ==================================== */
46274  var initMarkdown = function(el) {
46275    var $this = el;
46276
46277    if ($this.data('markdown')) {
46278      $this.data('markdown').showEditor();
46279      return;
46280    }
46281
46282    $this.markdown()
46283  };
46284
46285  var blurNonFocused = function(e) {
46286    var $activeElement = $(document.activeElement);
46287
46288    // Blur event
46289    $(document).find('.md-editor').each(function(){
46290      var $this            = $(this),
46291          focused          = $activeElement.closest('.md-editor')[0] === this,
46292          attachedMarkdown = $this.find('textarea').data('markdown') ||
46293                             $this.find('div[data-provider="markdown-preview"]').data('markdown');
46294
46295      if (attachedMarkdown && !focused) {
46296        attachedMarkdown.blur();
46297      }
46298    })
46299  };
46300
46301  $(document)
vendor: 8,506 bytes, lines 46302-46609
46302    .on('click.markdown.data-api', '[data-provide="markdown-editable"]', function (e) {
46303      initMarkdown($(this));
46304      e.preventDefault();
46305    })
46306    .on('click focusin', function (e) {
46307      blurNonFocused(e);
46308    })
46309    .ready(function(){
46310      $('textarea[data-provide="markdown"]').each(function(){
46311        initMarkdown($(this));
46312      })
46313    });
46314
46315}));
46316
46317$.fn.markdown.defaults.iconlibrary = 'fa';
46318$.fn.markdown.defaults.buttons[0][0]['data'][2]['icon']['fa'] = 'fa fa-heading';
46319$.fn.markdown.defaults.buttons[0][1]['data'][1]['icon']['fa'] = 'fa fa-image';
46320$.fn.markdown.defaults.buttons[0][2]['data'][1]['icon']['fa'] = 'fa fa-list-ol';
46321
46322/*!
46323 * jQuery Validation Plugin v1.19.0
46324 *
46325 * https://jqueryvalidation.org/
46326 *
46327 * Copyright (c) 2018 Jörn Zaefferer
46328 * Released under the MIT license
46329 */
46330(function( factory ) {
46331	if ( typeof define === "function" && define.amd ) {
46332		define( ["jquery"], factory );
46333	} else if (typeof module === "object" && module.exports) {
46334		module.exports = factory( require( "jquery" ) );
46335	} else {
46336		factory( jQuery );
46337	}
46338}(function( $ ) {
46339
46340$.extend( $.fn, {
46341
46342	// https://jqueryvalidation.org/validate/
46343	validate: function( options ) {
46344
46345		// If nothing is selected, return nothing; can't chain anyway
46346		if ( !this.length ) {
46347			if ( options && options.debug && window.console ) {
46348				console.warn( "Nothing selected, can't validate, returning nothing." );
46349			}
46350			return;
46351		}
46352
46353		// Check if a validator for this form was already created
46354		var validator = $.data( this[ 0 ], "validator" );
46355		if ( validator ) {
46356			return validator;
46357		}
46358
46359		// Add novalidate tag if HTML5.
46360		this.attr( "novalidate", "novalidate" );
46361
46362		validator = new $.validator( options, this[ 0 ] );
46363		$.data( this[ 0 ], "validator", validator );
46364
46365		if ( validator.settings.onsubmit ) {
46366
46367			this.on( "click.validate", ":submit", function( event ) {
46368
46369				// Track the used submit button to properly handle scripted
46370				// submits later.
46371				validator.submitButton = event.currentTarget;
46372
46373				// Allow suppressing validation by adding a cancel class to the submit button
46374				if ( $( this ).hasClass( "cancel" ) ) {
46375					validator.cancelSubmit = true;
46376				}
46377
46378				// Allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
46379				if ( $( this ).attr( "formnovalidate" ) !== undefined ) {
46380					validator.cancelSubmit = true;
46381				}
46382			} );
46383
46384			// Validate the form on submit
46385			this.on( "submit.validate", function( event ) {
46386				if ( validator.settings.debug ) {
46387
46388					// Prevent form submit to be able to see console output
46389					event.preventDefault();
46390				}
46391
46392				function handle() {
46393					var hidden, result;
46394
46395					// Insert a hidden input as a replacement for the missing submit button
46396					// The hidden input is inserted in two cases:
46397					//   - A user defined a `submitHandler`
46398					//   - There was a pending request due to `remote` method and `stopRequest()`
46399					//     was called to submit the form in case it's valid
46400					if ( validator.submitButton && ( validator.settings.submitHandler || validator.formSubmitted ) ) {
46401						hidden = $( "<input type='hidden'/>" )
46402							.attr( "name", validator.submitButton.name )
46403							.val( $( validator.submitButton ).val() )
46404							.appendTo( validator.currentForm );
46405					}
46406
46407					if ( validator.settings.submitHandler && !validator.settings.debug ) {
46408						result = validator.settings.submitHandler.call( validator, validator.currentForm, event );
46409						if ( hidden ) {
46410
46411							// And clean up afterwards; thanks to no-block-scope, hidden can be referenced
46412							hidden.remove();
46413						}
46414						if ( result !== undefined ) {
46415							return result;
46416						}
46417						return false;
46418					}
46419					return true;
46420				}
46421
46422				// Prevent submit for invalid forms or custom submit handlers
46423				if ( validator.cancelSubmit ) {
46424					validator.cancelSubmit = false;
46425					return handle();
46426				}
46427				if ( validator.form() ) {
46428					if ( validator.pendingRequest ) {
46429						validator.formSubmitted = true;
46430						return false;
46431					}
46432					return handle();
46433				} else {
46434					validator.focusInvalid();
46435					return false;
46436				}
46437			} );
46438		}
46439
46440		return validator;
46441	},
46442
46443	// https://jqueryvalidation.org/valid/
46444	valid: function() {
46445		var valid, validator, errorList;
46446
46447		if ( $( this[ 0 ] ).is( "form" ) ) {
46448			valid = this.validate().form();
46449		} else {
46450			errorList = [];
46451			valid = true;
46452			validator = $( this[ 0 ].form ).validate();
46453			this.each( function() {
46454				valid = validator.element( this ) && valid;
46455				if ( !valid ) {
46456					errorList = errorList.concat( validator.errorList );
46457				}
46458			} );
46459			validator.errorList = errorList;
46460		}
46461		return valid;
46462	},
46463
46464	// https://jqueryvalidation.org/rules/
46465	rules: function( command, argument ) {
46466		var element = this[ 0 ],
46467			isContentEditable = typeof this.attr( "contenteditable" ) !== "undefined" && this.attr( "contenteditable" ) !== "false",
46468			settings, staticRules, existingRules, data, param, filtered;
46469
46470		// If nothing is selected, return empty object; can't chain anyway
46471		if ( element == null ) {
46472			return;
46473		}
46474
46475		if ( !element.form && isContentEditable ) {
46476			element.form = this.closest( "form" )[ 0 ];
46477			element.name = this.attr( "name" );
46478		}
46479
46480		if ( element.form == null ) {
46481			return;
46482		}
46483
46484		if ( command ) {
46485			settings = $.data( element.form, "validator" ).settings;
46486			staticRules = settings.rules;
46487			existingRules = $.validator.staticRules( element );
46488			switch ( command ) {
46489			case "add":
46490				$.extend( existingRules, $.validator.normalizeRule( argument ) );
46491
46492				// Remove messages from rules, but allow them to be set separately
46493				delete existingRules.messages;
46494				staticRules[ element.name ] = existingRules;
46495				if ( argument.messages ) {
46496					settings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages );
46497				}
46498				break;
46499			case "remove":
46500				if ( !argument ) {
46501					delete staticRules[ element.name ];
46502					return existingRules;
46503				}
46504				filtered = {};
46505				$.each( argument.split( /\s/ ), function( index, method ) {
46506					filtered[ method ] = existingRules[ method ];
46507					delete existingRules[ method ];
46508				} );
46509				return filtered;
46510			}
46511		}
46512
46513		data = $.validator.normalizeRules(
46514		$.extend(
46515			{},
46516			$.validator.classRules( element ),
46517			$.validator.attributeRules( element ),
46518			$.validator.dataRules( element ),
46519			$.validator.staticRules( element )
46520		), element );
46521
46522		// Make sure required is at front
46523		if ( data.required ) {
46524			param = data.required;
46525			delete data.required;
46526			data = $.extend( { required: param }, data );
46527		}
46528
46529		// Make sure remote is at back
46530		if ( data.remote ) {
46531			param = data.remote;
46532			delete data.remote;
46533			data = $.extend( data, { remote: param } );
46534		}
46535
46536		return data;
46537	}
46538} );
46539
46540// Custom selectors
46541$.extend( $.expr.pseudos || $.expr[ ":" ], {		// '|| $.expr[ ":" ]' here enables backwards compatibility to jQuery 1.7. Can be removed when dropping jQ 1.7.x support
46542
46543	// https://jqueryvalidation.org/blank-selector/
46544	blank: function( a ) {
46545		return !$.trim( "" + $( a ).val() );
46546	},
46547
46548	// https://jqueryvalidation.org/filled-selector/
46549	filled: function( a ) {
46550		var val = $( a ).val();
46551		return val !== null && !!$.trim( "" + val );
46552	},
46553
46554	// https://jqueryvalidation.org/unchecked-selector/
46555	unchecked: function( a ) {
46556		return !$( a ).prop( "checked" );
46557	}
46558} );
46559
46560// Constructor for validator
46561$.validator = function( options, form ) {
46562	this.settings = $.extend( true, {}, $.validator.defaults, options );
46563	this.currentForm = form;
46564	this.init();
46565};
46566
46567// https://jqueryvalidation.org/jQuery.validator.format/
46568$.validator.format = function( source, params ) {
46569	if ( arguments.length === 1 ) {
46570		return function() {
46571			var args = $.makeArray( arguments );
46572			args.unshift( source );
46573			return $.validator.format.apply( this, args );
46574		};
46575	}
46576	if ( params === undefined ) {
46577		return source;
46578	}
46579	if ( arguments.length > 2 && params.constructor !== Array  ) {
46580		params = $.makeArray( arguments ).slice( 1 );
46581	}
46582	if ( params.constructor !== Array ) {
46583		params = [ params ];
46584	}
46585	$.each( params, function( i, n ) {
46586		source = source.replace( new RegExp( "\\{" + i + "\\}", "g" ), function() {
46587			return n;
46588		} );
46589	} );
46590	return source;
46591};
46592
46593$.extend( $.validator, {
46594
46595	defaults: {
46596		messages: {},
46597		groups: {},
46598		rules: {},
46599		errorClass: "error",
46600		pendingClass: "pending",
46601		validClass: "valid",
46602		errorElement: "label",
46603		focusCleanup: false,
46604		focusInvalid: true,
46605		errorContainer: $( [] ),
46606		errorLabelContainer: $( [] ),
46607		onsubmit: true,
46608		ignore: ":hidden",
46609		ignoreTitle: false
vendor: 5,102 bytes, lines 46609-46756
46609,
46610		onfocusin: function( element ) {
46611			this.lastActive = element;
46612
46613			// Hide error label and remove error class on focus if enabled
46614			if ( this.settings.focusCleanup ) {
46615				if ( this.settings.unhighlight ) {
46616					this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
46617				}
46618				this.hideThese( this.errorsFor( element ) );
46619			}
46620		},
46621		onfocusout: function( element ) {
46622			if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) {
46623				this.element( element );
46624			}
46625		},
46626		onkeyup: function( element, event ) {
46627
46628			// Avoid revalidate the field when pressing one of the following keys
46629			// Shift       => 16
46630			// Ctrl        => 17
46631			// Alt         => 18
46632			// Caps lock   => 20
46633			// End         => 35
46634			// Home        => 36
46635			// Left arrow  => 37
46636			// Up arrow    => 38
46637			// Right arrow => 39
46638			// Down arrow  => 40
46639			// Insert      => 45
46640			// Num lock    => 144
46641			// AltGr key   => 225
46642			var excludedKeys = [
46643				16, 17, 18, 20, 35, 36, 37,
46644				38, 39, 40, 45, 144, 225
46645			];
46646
46647			if ( event.which === 9 && this.elementValue( element ) === "" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) {
46648				return;
46649			} else if ( element.name in this.submitted || element.name in this.invalid ) {
46650				this.element( element );
46651			}
46652		},
46653		onclick: function( element ) {
46654
46655			// Click on selects, radiobuttons and checkboxes
46656			if ( element.name in this.submitted ) {
46657				this.element( element );
46658
46659			// Or option elements, check parent select in that case
46660			} else if ( element.parentNode.name in this.submitted ) {
46661				this.element( element.parentNode );
46662			}
46663		},
46664		highlight: function( element, errorClass, validClass ) {
46665			if ( element.type === "radio" ) {
46666				this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );
46667			} else {
46668				$( element ).addClass( errorClass ).removeClass( validClass );
46669			}
46670		},
46671		unhighlight: function( element, errorClass, validClass ) {
46672			if ( element.type === "radio" ) {
46673				this.findByName( element.name ).removeClass( errorClass ).addClass( validClass );
46674			} else {
46675				$( element ).removeClass( errorClass ).addClass( validClass );
46676			}
46677		}
46678	},
46679
46680	// https://jqueryvalidation.org/jQuery.validator.setDefaults/
46681	setDefaults: function( settings ) {
46682		$.extend( $.validator.defaults, settings );
46683	},
46684
46685	messages: {
46686		required: "This field is required.",
46687		remote: "Please fix this field.",
46688		email: "Please enter a valid email address.",
46689		url: "Please enter a valid URL.",
46690		date: "Please enter a valid date.",
46691		dateISO: "Please enter a valid date (ISO).",
46692		number: "Please enter a valid number.",
46693		digits: "Please enter only digits.",
46694		equalTo: "Please enter the same value again.",
46695		maxlength: $.validator.format( "Please enter no more than {0} characters." ),
46696		minlength: $.validator.format( "Please enter at least {0} characters." ),
46697		rangelength: $.validator.format( "Please enter a value between {0} and {1} characters long." ),
46698		range: $.validator.format( "Please enter a value between {0} and {1}." ),
46699		max: $.validator.format( "Please enter a value less than or equal to {0}." ),
46700		min: $.validator.format( "Please enter a value greater than or equal to {0}." ),
46701		step: $.validator.format( "Please enter a multiple of {0}." )
46702	},
46703
46704	autoCreateRanges: false,
46705
46706	prototype: {
46707
46708		init: function() {
46709			this.labelContainer = $( this.settings.errorLabelContainer );
46710			this.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm );
46711			this.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer );
46712			this.submitted = {};
46713			this.valueCache = {};
46714			this.pendingRequest = 0;
46715			this.pending = {};
46716			this.invalid = {};
46717			this.reset();
46718
46719			var currentForm = this.currentForm,
46720				groups = ( this.groups = {} ),
46721				rules;
46722			$.each( this.settings.groups, function( key, value ) {
46723				if ( typeof value === "string" ) {
46724					value = value.split( /\s/ );
46725				}
46726				$.each( value, function( index, name ) {
46727					groups[ name ] = key;
46728				} );
46729			} );
46730			rules = this.settings.rules;
46731			$.each( rules, function( key, value ) {
46732				rules[ key ] = $.validator.normalizeRule( value );
46733			} );
46734
46735			function delegate( event ) {
46736				var isContentEditable = typeof $( this ).attr( "contenteditable" ) !== "undefined" && $( this ).attr( "contenteditable" ) !== "false";
46737
46738				// Set form expando on contenteditable
46739				if ( !this.form && isContentEditable ) {
46740					this.form = $( this ).closest( "form" )[ 0 ];
46741					this.name = $( this ).attr( "name" );
46742				}
46743
46744				// Ignore the element if it belongs to another form. This will happen mainly
46745				// when setting the `form` attribute of an input to the id of another form.
46746				if ( currentForm !== this.form ) {
46747					return;
46748				}
46749
46750				var validator = $.data( this.form, "validator" ),
46751					eventType = "on" + event.type.replace( /^validate/, "" ),
46752					settings = validator.settings;
46753				if ( settings[ eventType ] && !$( this ).is( settings.ignore ) ) {
46754					settings[ eventType ].call( validator, this, event );
46755				}
46756			}
vendor: 38,513 bytes, lines 46757-48001
46757
46758			$( this.currentForm )
46759				.on( "focusin.validate focusout.validate keyup.validate",
46760					":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], " +
46761					"[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], " +
46762					"[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], " +
46763					"[type='radio'], [type='checkbox'], [contenteditable], [type='button']", delegate )
46764
46765				// Support: Chrome, oldIE
46766				// "select" is provided as event.target when clicking a option
46767				.on( "click.validate", "select, option, [type='radio'], [type='checkbox']", delegate );
46768
46769			if ( this.settings.invalidHandler ) {
46770				$( this.currentForm ).on( "invalid-form.validate", this.settings.invalidHandler );
46771			}
46772		},
46773
46774		// https://jqueryvalidation.org/Validator.form/
46775		form: function() {
46776			this.checkForm();
46777			$.extend( this.submitted, this.errorMap );
46778			this.invalid = $.extend( {}, this.errorMap );
46779			if ( !this.valid() ) {
46780				$( this.currentForm ).triggerHandler( "invalid-form", [ this ] );
46781			}
46782			this.showErrors();
46783			return this.valid();
46784		},
46785
46786		checkForm: function() {
46787			this.prepareForm();
46788			for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) {
46789				this.check( elements[ i ] );
46790			}
46791			return this.valid();
46792		},
46793
46794		// https://jqueryvalidation.org/Validator.element/
46795		element: function( element ) {
46796			var cleanElement = this.clean( element ),
46797				checkElement = this.validationTargetFor( cleanElement ),
46798				v = this,
46799				result = true,
46800				rs, group;
46801
46802			if ( checkElement === undefined ) {
46803				delete this.invalid[ cleanElement.name ];
46804			} else {
46805				this.prepareElement( checkElement );
46806				this.currentElements = $( checkElement );
46807
46808				// If this element is grouped, then validate all group elements already
46809				// containing a value
46810				group = this.groups[ checkElement.name ];
46811				if ( group ) {
46812					$.each( this.groups, function( name, testgroup ) {
46813						if ( testgroup === group && name !== checkElement.name ) {
46814							cleanElement = v.validationTargetFor( v.clean( v.findByName( name ) ) );
46815							if ( cleanElement && cleanElement.name in v.invalid ) {
46816								v.currentElements.push( cleanElement );
46817								result = v.check( cleanElement ) && result;
46818							}
46819						}
46820					} );
46821				}
46822
46823				rs = this.check( checkElement ) !== false;
46824				result = result && rs;
46825				if ( rs ) {
46826					this.invalid[ checkElement.name ] = false;
46827				} else {
46828					this.invalid[ checkElement.name ] = true;
46829				}
46830
46831				if ( !this.numberOfInvalids() ) {
46832
46833					// Hide error containers on last error
46834					this.toHide = this.toHide.add( this.containers );
46835				}
46836				this.showErrors();
46837
46838				// Add aria-invalid status for screen readers
46839				$( element ).attr( "aria-invalid", !rs );
46840			}
46841
46842			return result;
46843		},
46844
46845		// https://jqueryvalidation.org/Validator.showErrors/
46846		showErrors: function( errors ) {
46847			if ( errors ) {
46848				var validator = this;
46849
46850				// Add items to error list and map
46851				$.extend( this.errorMap, errors );
46852				this.errorList = $.map( this.errorMap, function( message, name ) {
46853					return {
46854						message: message,
46855						element: validator.findByName( name )[ 0 ]
46856					};
46857				} );
46858
46859				// Remove items from success list
46860				this.successList = $.grep( this.successList, function( element ) {
46861					return !( element.name in errors );
46862				} );
46863			}
46864			if ( this.settings.showErrors ) {
46865				this.settings.showErrors.call( this, this.errorMap, this.errorList );
46866			} else {
46867				this.defaultShowErrors();
46868			}
46869		},
46870
46871		// https://jqueryvalidation.org/Validator.resetForm/
46872		resetForm: function() {
46873			if ( $.fn.resetForm ) {
46874				$( this.currentForm ).resetForm();
46875			}
46876			this.invalid = {};
46877			this.submitted = {};
46878			this.prepareForm();
46879			this.hideErrors();
46880			var elements = this.elements()
46881				.removeData( "previousValue" )
46882				.removeAttr( "aria-invalid" );
46883
46884			this.resetElements( elements );
46885		},
46886
46887		resetElements: function( elements ) {
46888			var i;
46889
46890			if ( this.settings.unhighlight ) {
46891				for ( i = 0; elements[ i ]; i++ ) {
46892					this.settings.unhighlight.call( this, elements[ i ],
46893						this.settings.errorClass, "" );
46894					this.findByName( elements[ i ].name ).removeClass( this.settings.validClass );
46895				}
46896			} else {
46897				elements
46898					.removeClass( this.settings.errorClass )
46899					.removeClass( this.settings.validClass );
46900			}
46901		},
46902
46903		numberOfInvalids: function() {
46904			return this.objectLength( this.invalid );
46905		},
46906
46907		objectLength: function( obj ) {
46908			/* jshint unused: false */
46909			var count = 0,
46910				i;
46911			for ( i in obj ) {
46912
46913				// This check allows counting elements with empty error
46914				// message as invalid elements
46915				if ( obj[ i ] !== undefined && obj[ i ] !== null && obj[ i ] !== false ) {
46916					count++;
46917				}
46918			}
46919			return count;
46920		},
46921
46922		hideErrors: function() {
46923			this.hideThese( this.toHide );
46924		},
46925
46926		hideThese: function( errors ) {
46927			errors.not( this.containers ).text( "" );
46928			this.addWrapper( errors ).hide();
46929		},
46930
46931		valid: function() {
46932			return this.size() === 0;
46933		},
46934
46935		size: function() {
46936			return this.errorList.length;
46937		},
46938
46939		focusInvalid: function() {
46940			if ( this.settings.focusInvalid ) {
46941				try {
46942					$( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [] )
46943					.filter( ":visible" )
46944					.focus()
46945
46946					// Manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
46947					.trigger( "focusin" );
46948				} catch ( e ) {
46949
46950					// Ignore IE throwing errors when focusing hidden elements
46951				}
46952			}
46953		},
46954
46955		findLastActive: function() {
46956			var lastActive = this.lastActive;
46957			return lastActive && $.grep( this.errorList, function( n ) {
46958				return n.element.name === lastActive.name;
46959			} ).length === 1 && lastActive;
46960		},
46961
46962		elements: function() {
46963			var validator = this,
46964				rulesCache = {};
46965
46966			// Select all valid inputs inside the form (no submit or reset buttons)
46967			return $( this.currentForm )
46968			.find( "input, select, textarea, [contenteditable]" )
46969			.not( ":submit, :reset, :image, :disabled" )
46970			.not( this.settings.ignore )
46971			.filter( function() {
46972				var name = this.name || $( this ).attr( "name" ); // For contenteditable
46973				var isContentEditable = typeof $( this ).attr( "contenteditable" ) !== "undefined" && $( this ).attr( "contenteditable" ) !== "false";
46974
46975				if ( !name && validator.settings.debug && window.console ) {
46976					console.error( "%o has no name assigned", this );
46977				}
46978
46979				// Set form expando on contenteditable
46980				if ( isContentEditable ) {
46981					this.form = $( this ).closest( "form" )[ 0 ];
46982					this.name = name;
46983				}
46984
46985				// Ignore elements that belong to other/nested forms
46986				if ( this.form !== validator.currentForm ) {
46987					return false;
46988				}
46989
46990				// Select only the first element for each name, and only those with rules specified
46991				if ( name in rulesCache || !validator.objectLength( $( this ).rules() ) ) {
46992					return false;
46993				}
46994
46995				rulesCache[ name ] = true;
46996				return true;
46997			} );
46998		},
46999
47000		clean: function( selector ) {
47001			return $( selector )[ 0 ];
47002		},
47003
47004		errors: function() {
47005			var errorClass = this.settings.errorClass.split( " " ).join( "." );
47006			return $( this.settings.errorElement + "." + errorClass, this.errorContext );
47007		},
47008
47009		resetInternals: function() {
47010			this.successList = [];
47011			this.errorList = [];
47012			this.errorMap = {};
47013			this.toShow = $( [] );
47014			this.toHide = $( [] );
47015		},
47016
47017		reset: function() {
47018			this.resetInternals();
47019			this.currentElements = $( [] );
47020		},
47021
47022		prepareForm: function() {
47023			this.reset();
47024			this.toHide = this.errors().add( this.containers );
47025		},
47026
47027		prepareElement: function( element ) {
47028			this.reset();
47029			this.toHide = this.errorsFor( element );
47030		},
47031
47032		elementValue: function( element ) {
47033			var $element = $( element ),
47034				type = element.type,
47035				isContentEditable = typeof $element.attr( "contenteditable" ) !== "undefined" && $element.attr( "contenteditable" ) !== "false",
47036				val, idx;
47037
47038			if ( type === "radio" || type === "checkbox" ) {
47039				return this.findByName( element.name ).filter( ":checked" ).val();
47040			} else if ( type === "number" && typeof element.validity !== "undefined" ) {
47041				return element.validity.badInput ? "NaN" : $element.val();
47042			}
47043
47044			if ( isContentEditable ) {
47045				val = $element.text();
47046			} else {
47047				val = $element.val();
47048			}
47049
47050			if ( type === "file" ) {
47051
47052				// Modern browser (chrome & safari)
47053				if ( val.substr( 0, 12 ) === "C:\\fakepath\\" ) {
47054					return val.substr( 12 );
47055				}
47056
47057				// Legacy browsers
47058				// Unix-based path
47059				idx = val.lastIndexOf( "/" );
47060				if ( idx >= 0 ) {
47061					return val.substr( idx + 1 );
47062				}
47063
47064				// Windows-based path
47065				idx = val.lastIndexOf( "\\" );
47066				if ( idx >= 0 ) {
47067					return val.substr( idx + 1 );
47068				}
47069
47070				// Just the file name
47071				return val;
47072			}
47073
47074			if ( typeof val === "string" ) {
47075				return val.replace( /\r/g, "" );
47076			}
47077			return val;
47078		},
47079
47080		check: function( element ) {
47081			element = this.validationTargetFor( this.clean( element ) );
47082
47083			var rules = $( element ).rules(),
47084				rulesCount = $.map( rules, function( n, i ) {
47085					return i;
47086				} ).length,
47087				dependencyMismatch = false,
47088				val = this.elementValue( element ),
47089				result, method, rule, normalizer;
47090
47091			// Prioritize the local normalizer defined for this element over the global one
47092			// if the former exists, otherwise user the global one in case it exists.
47093			if ( typeof rules.normalizer === "function" ) {
47094				normalizer = rules.normalizer;
47095			} else if (	typeof this.settings.normalizer === "function" ) {
47096				normalizer = this.settings.normalizer;
47097			}
47098
47099			// If normalizer is defined, then call it to retreive the changed value instead
47100			// of using the real one.
47101			// Note that `this` in the normalizer is `element`.
47102			if ( normalizer ) {
47103				val = normalizer.call( element, val );
47104
47105				// Delete the normalizer from rules to avoid treating it as a pre-defined method.
47106				delete rules.normalizer;
47107			}
47108
47109			for ( method in rules ) {
47110				rule = { method: method, parameters: rules[ method ] };
47111				try {
47112					result = $.validator.methods[ method ].call( this, val, element, rule.parameters );
47113
47114					// If a method indicates that the field is optional and therefore valid,
47115					// don't mark it as valid when there are no other rules
47116					if ( result === "dependency-mismatch" && rulesCount === 1 ) {
47117						dependencyMismatch = true;
47118						continue;
47119					}
47120					dependencyMismatch = false;
47121
47122					if ( result === "pending" ) {
47123						this.toHide = this.toHide.not( this.errorsFor( element ) );
47124						return;
47125					}
47126
47127					if ( !result ) {
47128						this.formatAndAdd( element, rule );
47129						return false;
47130					}
47131				} catch ( e ) {
47132					if ( this.settings.debug && window.console ) {
47133						console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e );
47134					}
47135					if ( e instanceof TypeError ) {
47136						e.message += ".  Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.";
47137					}
47138
47139					throw e;
47140				}
47141			}
47142			if ( dependencyMismatch ) {
47143				return;
47144			}
47145			if ( this.objectLength( rules ) ) {
47146				this.successList.push( element );
47147			}
47148			return true;
47149		},
47150
47151		// Return the custom message for the given element and validation method
47152		// specified in the element's HTML5 data attribute
47153		// return the generic message if present and no method specific message is present
47154		customDataMessage: function( element, method ) {
47155			return $( element ).data( "msg" + method.charAt( 0 ).toUpperCase() +
47156				method.substring( 1 ).toLowerCase() ) || $( element ).data( "msg" );
47157		},
47158
47159		// Return the custom message for the given element name and validation method
47160		customMessage: function( name, method ) {
47161			var m = this.settings.messages[ name ];
47162			return m && ( m.constructor === String ? m : m[ method ] );
47163		},
47164
47165		// Return the first defined argument, allowing empty strings
47166		findDefined: function() {
47167			for ( var i = 0; i < arguments.length; i++ ) {
47168				if ( arguments[ i ] !== undefined ) {
47169					return arguments[ i ];
47170				}
47171			}
47172			return undefined;
47173		},
47174
47175		// The second parameter 'rule' used to be a string, and extended to an object literal
47176		// of the following form:
47177		// rule = {
47178		//     method: "method name",
47179		//     parameters: "the given method parameters"
47180		// }
47181		//
47182		// The old behavior still supported, kept to maintain backward compatibility with
47183		// old code, and will be removed in the next major release.
47184		defaultMessage: function( element, rule ) {
47185			if ( typeof rule === "string" ) {
47186				rule = { method: rule };
47187			}
47188
47189			var message = this.findDefined(
47190					this.customMessage( element.name, rule.method ),
47191					this.customDataMessage( element, rule.method ),
47192
47193					// 'title' is never undefined, so handle empty string as undefined
47194					!this.settings.ignoreTitle && element.title || undefined,
47195					$.validator.messages[ rule.method ],
47196					"<strong>Warning: No message defined for " + element.name + "</strong>"
47197				),
47198				theregex = /\$?\{(\d+)\}/g;
47199			if ( typeof message === "function" ) {
47200				message = message.call( this, rule.parameters, element );
47201			} else if ( theregex.test( message ) ) {
47202				message = $.validator.format( message.replace( theregex, "{$1}" ), rule.parameters );
47203			}
47204
47205			return message;
47206		},
47207
47208		formatAndAdd: function( element, rule ) {
47209			var message = this.defaultMessage( element, rule );
47210
47211			this.errorList.push( {
47212				message: message,
47213				element: element,
47214				method: rule.method
47215			} );
47216
47217			this.errorMap[ element.name ] = message;
47218			this.submitted[ element.name ] = message;
47219		},
47220
47221		addWrapper: function( toToggle ) {
47222			if ( this.settings.wrapper ) {
47223				toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
47224			}
47225			return toToggle;
47226		},
47227
47228		defaultShowErrors: function() {
47229			var i, elements, error;
47230			for ( i = 0; this.errorList[ i ]; i++ ) {
47231				error = this.errorList[ i ];
47232				if ( this.settings.highlight ) {
47233					this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
47234				}
47235				this.showLabel( error.element, error.message );
47236			}
47237			if ( this.errorList.length ) {
47238				this.toShow = this.toShow.add( this.containers );
47239			}
47240			if ( this.settings.success ) {
47241				for ( i = 0; this.successList[ i ]; i++ ) {
47242					this.showLabel( this.successList[ i ] );
47243				}
47244			}
47245			if ( this.settings.unhighlight ) {
47246				for ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) {
47247					this.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.validClass );
47248				}
47249			}
47250			this.toHide = this.toHide.not( this.toShow );
47251			this.hideErrors();
47252			this.addWrapper( this.toShow ).show();
47253		},
47254
47255		validElements: function() {
47256			return this.currentElements.not( this.invalidElements() );
47257		},
47258
47259		invalidElements: function() {
47260			return $( this.errorList ).map( function() {
47261				return this.element;
47262			} );
47263		},
47264
47265		showLabel: function( element, message ) {
47266			var place, group, errorID, v,
47267				error = this.errorsFor( element ),
47268				elementID = this.idOrName( element ),
47269				describedBy = $( element ).attr( "aria-describedby" );
47270
47271			if ( error.length ) {
47272
47273				// Refresh error/success class
47274				error.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );
47275
47276				// Replace message on existing label
47277				error.html( message );
47278			} else {
47279
47280				// Create error element
47281				error = $( "<" + this.settings.errorElement + ">" )
47282					.attr( "id", elementID + "-error" )
47283					.addClass( this.settings.errorClass )
47284					.html( message || "" );
47285
47286				// Maintain reference to the element to be placed into the DOM
47287				place = error;
47288				if ( this.settings.wrapper ) {
47289
47290					// Make sure the element is visible, even in IE
47291					// actually showing the wrapped element is handled elsewhere
47292					place = error.hide().show().wrap( "<" + this.settings.wrapper + "/>" ).parent();
47293				}
47294				if ( this.labelContainer.length ) {
47295					this.labelContainer.append( place );
47296				} else if ( this.settings.errorPlacement ) {
47297					this.settings.errorPlacement.call( this, place, $( element ) );
47298				} else {
47299					place.insertAfter( element );
47300				}
47301
47302				// Link error back to the element
47303				if ( error.is( "label" ) ) {
47304
47305					// If the error is a label, then associate using 'for'
47306					error.attr( "for", elementID );
47307
47308					// If the element is not a child of an associated label, then it's necessary
47309					// to explicitly apply aria-describedby
47310				} else if ( error.parents( "label[for='" + this.escapeCssMeta( elementID ) + "']" ).length === 0 ) {
47311					errorID = error.attr( "id" );
47312
47313					// Respect existing non-error aria-describedby
47314					if ( !describedBy ) {
47315						describedBy = errorID;
47316					} else if ( !describedBy.match( new RegExp( "\\b" + this.escapeCssMeta( errorID ) + "\\b" ) ) ) {
47317
47318						// Add to end of list if not already present
47319						describedBy += " " + errorID;
47320					}
47321					$( element ).attr( "aria-describedby", describedBy );
47322
47323					// If this element is grouped, then assign to all elements in the same group
47324					group = this.groups[ element.name ];
47325					if ( group ) {
47326						v = this;
47327						$.each( v.groups, function( name, testgroup ) {
47328							if ( testgroup === group ) {
47329								$( "[name='" + v.escapeCssMeta( name ) + "']", v.currentForm )
47330									.attr( "aria-describedby", error.attr( "id" ) );
47331							}
47332						} );
47333					}
47334				}
47335			}
47336			if ( !message && this.settings.success ) {
47337				error.text( "" );
47338				if ( typeof this.settings.success === "string" ) {
47339					error.addClass( this.settings.success );
47340				} else {
47341					this.settings.success( error, element );
47342				}
47343			}
47344			this.toShow = this.toShow.add( error );
47345		},
47346
47347		errorsFor: function( element ) {
47348			var name = this.escapeCssMeta( this.idOrName( element ) ),
47349				describer = $( element ).attr( "aria-describedby" ),
47350				selector = "label[for='" + name + "'], label[for='" + name + "'] *";
47351
47352			// 'aria-describedby' should directly reference the error element
47353			if ( describer ) {
47354				selector = selector + ", #" + this.escapeCssMeta( describer )
47355					.replace( /\s+/g, ", #" );
47356			}
47357
47358			return this
47359				.errors()
47360				.filter( selector );
47361		},
47362
47363		// See https://api.jquery.com/category/selectors/, for CSS
47364		// meta-characters that should be escaped in order to be used with JQuery
47365		// as a literal part of a name/id or any selector.
47366		escapeCssMeta: function( string ) {
47367			return string.replace( /([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g, "\\$1" );
47368		},
47369
47370		idOrName: function( element ) {
47371			return this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.id || element.name );
47372		},
47373
47374		validationTargetFor: function( element ) {
47375
47376			// If radio/checkbox, validate first element in group instead
47377			if ( this.checkable( element ) ) {
47378				element = this.findByName( element.name );
47379			}
47380
47381			// Always apply ignore filter
47382			return $( element ).not( this.settings.ignore )[ 0 ];
47383		},
47384
47385		checkable: function( element ) {
47386			return ( /radio|checkbox/i ).test( element.type );
47387		},
47388
47389		findByName: function( name ) {
47390			return $( this.currentForm ).find( "[name='" + this.escapeCssMeta( name ) + "']" );
47391		},
47392
47393		getLength: function( value, element ) {
47394			switch ( element.nodeName.toLowerCase() ) {
47395			case "select":
47396				return $( "option:selected", element ).length;
47397			case "input":
47398				if ( this.checkable( element ) ) {
47399					return this.findByName( element.name ).filter( ":checked" ).length;
47400				}
47401			}
47402			return value.length;
47403		},
47404
47405		depend: function( param, element ) {
47406			return this.dependTypes[ typeof param ] ? this.dependTypes[ typeof param ]( param, element ) : true;
47407		},
47408
47409		dependTypes: {
47410			"boolean": function( param ) {
47411				return param;
47412			},
47413			"string": function( param, element ) {
47414				return !!$( param, element.form ).length;
47415			},
47416			"function": function( param, element ) {
47417				return param( element );
47418			}
47419		},
47420
47421		optional: function( element ) {
47422			var val = this.elementValue( element );
47423			return !$.validator.methods.required.call( this, val, element ) && "dependency-mismatch";
47424		},
47425
47426		startRequest: function( element ) {
47427			if ( !this.pending[ element.name ] ) {
47428				this.pendingRequest++;
47429				$( element ).addClass( this.settings.pendingClass );
47430				this.pending[ element.name ] = true;
47431			}
47432		},
47433
47434		stopRequest: function( element, valid ) {
47435			this.pendingRequest--;
47436
47437			// Sometimes synchronization fails, make sure pendingRequest is never < 0
47438			if ( this.pendingRequest < 0 ) {
47439				this.pendingRequest = 0;
47440			}
47441			delete this.pending[ element.name ];
47442			$( element ).removeClass( this.settings.pendingClass );
47443			if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) {
47444				$( this.currentForm ).submit();
47445
47446				// Remove the hidden input that was used as a replacement for the
47447				// missing submit button. The hidden input is added by `handle()`
47448				// to ensure that the value of the used submit button is passed on
47449				// for scripted submits triggered by this method
47450				if ( this.submitButton ) {
47451					$( "input:hidden[name='" + this.submitButton.name + "']", this.currentForm ).remove();
47452				}
47453
47454				this.formSubmitted = false;
47455			} else if ( !valid && this.pendingRequest === 0 && this.formSubmitted ) {
47456				$( this.currentForm ).triggerHandler( "invalid-form", [ this ] );
47457				this.formSubmitted = false;
47458			}
47459		},
47460
47461		previousValue: function( element, method ) {
47462			method = typeof method === "string" && method || "remote";
47463
47464			return $.data( element, "previousValue" ) || $.data( element, "previousValue", {
47465				old: null,
47466				valid: true,
47467				message: this.defaultMessage( element, { method: method } )
47468			} );
47469		},
47470
47471		// Cleans up all forms and elements, removes validator-specific events
47472		destroy: function() {
47473			this.resetForm();
47474
47475			$( this.currentForm )
47476				.off( ".validate" )
47477				.removeData( "validator" )
47478				.find( ".validate-equalTo-blur" )
47479					.off( ".validate-equalTo" )
47480					.removeClass( "validate-equalTo-blur" )
47481				.find( ".validate-lessThan-blur" )
47482					.off( ".validate-lessThan" )
47483					.removeClass( "validate-lessThan-blur" )
47484				.find( ".validate-lessThanEqual-blur" )
47485					.off( ".validate-lessThanEqual" )
47486					.removeClass( "validate-lessThanEqual-blur" )
47487				.find( ".validate-greaterThanEqual-blur" )
47488					.off( ".validate-greaterThanEqual" )
47489					.removeClass( "validate-greaterThanEqual-blur" )
47490				.find( ".validate-greaterThan-blur" )
47491					.off( ".validate-greaterThan" )
47492					.removeClass( "validate-greaterThan-blur" );
47493		}
47494
47495	},
47496
47497	classRuleSettings: {
47498		required: { required: true },
47499		email: { email: true },
47500		url: { url: true },
47501		date: { date: true },
47502		dateISO: { dateISO: true },
47503		number: { number: true },
47504		digits: { digits: true },
47505		creditcard: { creditcard: true }
47506	},
47507
47508	addClassRules: function( className, rules ) {
47509		if ( className.constructor === String ) {
47510			this.classRuleSettings[ className ] = rules;
47511		} else {
47512			$.extend( this.classRuleSettings, className );
47513		}
47514	},
47515
47516	classRules: function( element ) {
47517		var rules = {},
47518			classes = $( element ).attr( "class" );
47519
47520		if ( classes ) {
47521			$.each( classes.split( " " ), function() {
47522				if ( this in $.validator.classRuleSettings ) {
47523					$.extend( rules, $.validator.classRuleSettings[ this ] );
47524				}
47525			} );
47526		}
47527		return rules;
47528	},
47529
47530	normalizeAttributeRule: function( rules, type, method, value ) {
47531
47532		// Convert the value to a number for number inputs, and for text for backwards compability
47533		// allows type="date" and others to be compared as strings
47534		if ( /min|max|step/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) {
47535			value = Number( value );
47536
47537			// Support Opera Mini, which returns NaN for undefined minlength
47538			if ( isNaN( value ) ) {
47539				value = undefined;
47540			}
47541		}
47542
47543		if ( value || value === 0 ) {
47544			rules[ method ] = value;
47545		} else if ( type === method && type !== "range" ) {
47546
47547			// Exception: the jquery validate 'range' method
47548			// does not test for the html5 'range' type
47549			rules[ method ] = true;
47550		}
47551	},
47552
47553	attributeRules: function( element ) {
47554		var rules = {},
47555			$element = $( element ),
47556			type = element.getAttribute( "type" ),
47557			method, value;
47558
47559		for ( method in $.validator.methods ) {
47560
47561			// Support for <input required> in both html5 and older browsers
47562			if ( method === "required" ) {
47563				value = element.getAttribute( method );
47564
47565				// Some browsers return an empty string for the required attribute
47566				// and non-HTML5 browsers might have required="" markup
47567				if ( value === "" ) {
47568					value = true;
47569				}
47570
47571				// Force non-HTML5 browsers to return bool
47572				value = !!value;
47573			} else {
47574				value = $element.attr( method );
47575			}
47576
47577			this.normalizeAttributeRule( rules, type, method, value );
47578		}
47579
47580		// 'maxlength' may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs
47581		if ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) {
47582			delete rules.maxlength;
47583		}
47584
47585		return rules;
47586	},
47587
47588	dataRules: function( element ) {
47589		var rules = {},
47590			$element = $( element ),
47591			type = element.getAttribute( "type" ),
47592			method, value;
47593
47594		for ( method in $.validator.methods ) {
47595			value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() );
47596
47597			// Cast empty attributes like `data-rule-required` to `true`
47598			if ( value === "" ) {
47599				value = true;
47600			}
47601
47602			this.normalizeAttributeRule( rules, type, method, value );
47603		}
47604		return rules;
47605	},
47606
47607	staticRules: function( element ) {
47608		var rules = {},
47609			validator = $.data( element.form, "validator" );
47610
47611		if ( validator.settings.rules ) {
47612			rules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {};
47613		}
47614		return rules;
47615	},
47616
47617	normalizeRules: function( rules, element ) {
47618
47619		// Handle dependency check
47620		$.each( rules, function( prop, val ) {
47621
47622			// Ignore rule when param is explicitly false, eg. required:false
47623			if ( val === false ) {
47624				delete rules[ prop ];
47625				return;
47626			}
47627			if ( val.param || val.depends ) {
47628				var keepRule = true;
47629				switch ( typeof val.depends ) {
47630				case "string":
47631					keepRule = !!$( val.depends, element.form ).length;
47632					break;
47633				case "function":
47634					keepRule = val.depends.call( element, element );
47635					break;
47636				}
47637				if ( keepRule ) {
47638					rules[ prop ] = val.param !== undefined ? val.param : true;
47639				} else {
47640					$.data( element.form, "validator" ).resetElements( $( element ) );
47641					delete rules[ prop ];
47642				}
47643			}
47644		} );
47645
47646		// Evaluate parameters
47647		$.each( rules, function( rule, parameter ) {
47648			rules[ rule ] = $.isFunction( parameter ) && rule !== "normalizer" ? parameter( element ) : parameter;
47649		} );
47650
47651		// Clean number parameters
47652		$.each( [ "minlength", "maxlength" ], function() {
47653			if ( rules[ this ] ) {
47654				rules[ this ] = Number( rules[ this ] );
47655			}
47656		} );
47657		$.each( [ "rangelength", "range" ], function() {
47658			var parts;
47659			if ( rules[ this ] ) {
47660				if ( $.isArray( rules[ this ] ) ) {
47661					rules[ this ] = [ Number( rules[ this ][ 0 ] ), Number( rules[ this ][ 1 ] ) ];
47662				} else if ( typeof rules[ this ] === "string" ) {
47663					parts = rules[ this ].replace( /[\[\]]/g, "" ).split( /[\s,]+/ );
47664					rules[ this ] = [ Number( parts[ 0 ] ), Number( parts[ 1 ] ) ];
47665				}
47666			}
47667		} );
47668
47669		if ( $.validator.autoCreateRanges ) {
47670
47671			// Auto-create ranges
47672			if ( rules.min != null && rules.max != null ) {
47673				rules.range = [ rules.min, rules.max ];
47674				delete rules.min;
47675				delete rules.max;
47676			}
47677			if ( rules.minlength != null && rules.maxlength != null ) {
47678				rules.rangelength = [ rules.minlength, rules.maxlength ];
47679				delete rules.minlength;
47680				delete rules.maxlength;
47681			}
47682		}
47683
47684		return rules;
47685	},
47686
47687	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
47688	normalizeRule: function( data ) {
47689		if ( typeof data === "string" ) {
47690			var transformed = {};
47691			$.each( data.split( /\s/ ), function() {
47692				transformed[ this ] = true;
47693			} );
47694			data = transformed;
47695		}
47696		return data;
47697	},
47698
47699	// https://jqueryvalidation.org/jQuery.validator.addMethod/
47700	addMethod: function( name, method, message ) {
47701		$.validator.methods[ name ] = method;
47702		$.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ];
47703		if ( method.length < 3 ) {
47704			$.validator.addClassRules( name, $.validator.normalizeRule( name ) );
47705		}
47706	},
47707
47708	// https://jqueryvalidation.org/jQuery.validator.methods/
47709	methods: {
47710
47711		// https://jqueryvalidation.org/required-method/
47712		required: function( value, element, param ) {
47713
47714			// Check if dependency is met
47715			if ( !this.depend( param, element ) ) {
47716				return "dependency-mismatch";
47717			}
47718			if ( element.nodeName.toLowerCase() === "select" ) {
47719
47720				// Could be an array for select-multiple or a string, both are fine this way
47721				var val = $( element ).val();
47722				return val && val.length > 0;
47723			}
47724			if ( this.checkable( element ) ) {
47725				return this.getLength( value, element ) > 0;
47726			}
47727			return value !== undefined && value !== null && value.length > 0;
47728		},
47729
47730		// https://jqueryvalidation.org/email-method/
47731		email: function( value, element ) {
47732
47733			// From https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address
47734			// Retrieved 2014-01-14
47735			// If you have a problem with this implementation, report a bug against the above spec
47736			// Or use custom methods to implement your own email validation
47737			return this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value );
47738		},
47739
47740		// https://jqueryvalidation.org/url-method/
47741		url: function( value, element ) {
47742
47743			// Copyright (c) 2010-2013 Diego Perini, MIT licensed
47744			// https://gist.github.com/dperini/729294
47745			// see also https://mathiasbynens.be/demo/url-regex
47746			// modified to allow protocol-relative URLs
47747			return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value );
47748		},
47749
47750		// https://jqueryvalidation.org/date-method/
47751		date: ( function() {
47752			var called = false;
47753
47754			return function( value, element ) {
47755				if ( !called ) {
47756					called = true;
47757					if ( this.settings.debug && window.console ) {
47758						console.warn(
47759							"The `date` method is deprecated and will be removed in version '2.0.0'.\n" +
47760							"Please don't use it, since it relies on the Date constructor, which\n" +
47761							"behaves very differently across browsers and locales. Use `dateISO`\n" +
47762							"instead or one of the locale specific methods in `localizations/`\n" +
47763							"and `additional-methods.js`."
47764						);
47765					}
47766				}
47767
47768				return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() );
47769			};
47770		}() ),
47771
47772		// https://jqueryvalidation.org/dateISO-method/
47773		dateISO: function( value, element ) {
47774			return this.optional( element ) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test( value );
47775		},
47776
47777		// https://jqueryvalidation.org/number-method/
47778		number: function( value, element ) {
47779			return this.optional( element ) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test( value );
47780		},
47781
47782		// https://jqueryvalidation.org/digits-method/
47783		digits: function( value, element ) {
47784			return this.optional( element ) || /^\d+$/.test( value );
47785		},
47786
47787		// https://jqueryvalidation.org/minlength-method/
47788		minlength: function( value, element, param ) {
47789			var length = $.isArray( value ) ? value.length : this.getLength( value, element );
47790			return this.optional( element ) || length >= param;
47791		},
47792
47793		// https://jqueryvalidation.org/maxlength-method/
47794		maxlength: function( value, element, param ) {
47795			var length = $.isArray( value ) ? value.length : this.getLength( value, element );
47796			return this.optional( element ) || length <= param;
47797		},
47798
47799		// https://jqueryvalidation.org/rangelength-method/
47800		rangelength: function( value, element, param ) {
47801			var length = $.isArray( value ) ? value.length : this.getLength( value, element );
47802			return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] );
47803		},
47804
47805		// https://jqueryvalidation.org/min-method/
47806		min: function( value, element, param ) {
47807			return this.optional( element ) || value >= param;
47808		},
47809
47810		// https://jqueryvalidation.org/max-method/
47811		max: function( value, element, param ) {
47812			return this.optional( element ) || value <= param;
47813		},
47814
47815		// https://jqueryvalidation.org/range-method/
47816		range: function( value, element, param ) {
47817			return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );
47818		},
47819
47820		// https://jqueryvalidation.org/step-method/
47821		step: function( value, element, param ) {
47822			var type = $( element ).attr( "type" ),
47823				errorMessage = "Step attribute on input type " + type + " is not supported.",
47824				supportedTypes = [ "text", "number", "range" ],
47825				re = new RegExp( "\\b" + type + "\\b" ),
47826				notSupported = type && !re.test( supportedTypes.join() ),
47827				decimalPlaces = function( num ) {
47828					var match = ( "" + num ).match( /(?:\.(\d+))?$/ );
47829					if ( !match ) {
47830						return 0;
47831					}
47832
47833					// Number of digits right of decimal point.
47834					return match[ 1 ] ? match[ 1 ].length : 0;
47835				},
47836				toInt = function( num ) {
47837					return Math.round( num * Math.pow( 10, decimals ) );
47838				},
47839				valid = true,
47840				decimals;
47841
47842			// Works only for text, number and range input types
47843			// TODO find a way to support input types date, datetime, datetime-local, month, time and week
47844			if ( notSupported ) {
47845				throw new Error( errorMessage );
47846			}
47847
47848			decimals = decimalPlaces( param );
47849
47850			// Value can't have too many decimals
47851			if ( decimalPlaces( value ) > decimals || toInt( value ) % toInt( param ) !== 0 ) {
47852				valid = false;
47853			}
47854
47855			return this.optional( element ) || valid;
47856		},
47857
47858		// https://jqueryvalidation.org/equalTo-method/
47859		equalTo: function( value, element, param ) {
47860
47861			// Bind to the blur event of the target in order to revalidate whenever the target field is updated
47862			var target = $( param );
47863			if ( this.settings.onfocusout && target.not( ".validate-equalTo-blur" ).length ) {
47864				target.addClass( "validate-equalTo-blur" ).on( "blur.validate-equalTo", function() {
47865					$( element ).valid();
47866				} );
47867			}
47868			return value === target.val();
47869		},
47870
47871		// https://jqueryvalidation.org/remote-method/
47872		remote: function( value, element, param, method ) {
47873			if ( this.optional( element ) ) {
47874				return "dependency-mismatch";
47875			}
47876
47877			method = typeof method === "string" && method || "remote";
47878
47879			var previous = this.previousValue( element, method ),
47880				validator, data, optionDataString;
47881
47882			if ( !this.settings.messages[ element.name ] ) {
47883				this.settings.messages[ element.name ] = {};
47884			}
47885			previous.originalMessage = previous.originalMessage || this.settings.messages[ element.name ][ method ];
47886			this.settings.messages[ element.name ][ method ] = previous.message;
47887
47888			param = typeof param === "string" && { url: param } || param;
47889			optionDataString = $.param( $.extend( { data: value }, param.data ) );
47890			if ( previous.old === optionDataString ) {
47891				return previous.valid;
47892			}
47893
47894			previous.old = optionDataString;
47895			validator = this;
47896			this.startRequest( element );
47897			data = {};
47898			data[ element.name ] = value;
47899			$.ajax( $.extend( true, {
47900				mode: "abort",
47901				port: "validate" + element.name,
47902				dataType: "json",
47903				data: data,
47904				context: validator.currentForm,
47905				success: function( response ) {
47906					var valid = response === true || response === "true",
47907						errors, message, submitted;
47908
47909					validator.settings.messages[ element.name ][ method ] = previous.originalMessage;
47910					if ( valid ) {
47911						submitted = validator.formSubmitted;
47912						validator.resetInternals();
47913						validator.toHide = validator.errorsFor( element );
47914						validator.formSubmitted = submitted;
47915						validator.successList.push( element );
47916						validator.invalid[ element.name ] = false;
47917						validator.showErrors();
47918					} else {
47919						errors = {};
47920						message = response || validator.defaultMessage( element, { method: method, parameters: value } );
47921						errors[ element.name ] = previous.message = message;
47922						validator.invalid[ element.name ] = true;
47923						validator.showErrors( errors );
47924					}
47925					previous.valid = valid;
47926					validator.stopRequest( element, valid );
47927				}
47928			}, param ) );
47929			return "pending";
47930		}
47931	}
47932
47933} );
47934
47935// Ajax mode: abort
47936// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
47937// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
47938
47939var pendingRequests = {},
47940	ajax;
47941
47942// Use a prefilter if available (1.5+)
47943if ( $.ajaxPrefilter ) {
47944	$.ajaxPrefilter( function( settings, _, xhr ) {
47945		var port = settings.port;
47946		if ( settings.mode === "abort" ) {
47947			if ( pendingRequests[ port ] ) {
47948				pendingRequests[ port ].abort();
47949			}
47950			pendingRequests[ port ] = xhr;
47951		}
47952	} );
47953} else {
47954
47955	// Proxy ajax
47956	ajax = $.ajax;
47957	$.ajax = function( settings ) {
47958		var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
47959			port = ( "port" in settings ? settings : $.ajaxSettings ).port;
47960		if ( mode === "abort" ) {
47961			if ( pendingRequests[ port ] ) {
47962				pendingRequests[ port ].abort();
47963			}
47964			pendingRequests[ port ] = ajax.apply( this, arguments );
47965			return pendingRequests[ port ];
47966		}
47967		return ajax.apply( this, arguments );
47968	};
47969}
47970return $;
47971}));
47972/*!
47973 * jQuery Validation Plugin v1.19.0
47974 *
47975 * https://jqueryvalidation.org/
47976 *
47977 * Copyright (c) 2018 Jörn Zaefferer
47978 * Released under the MIT license
47979 */
47980(function( factory ) {
47981	if ( typeof define === "function" && define.amd ) {
47982		define( ["jquery", "./jquery.validate"], factory );
47983	} else if (typeof module === "object" && module.exports) {
47984		module.exports = factory( require( "jquery" ) );
47985	} else {
47986		factory( jQuery );
47987	}
47988}(function( $ ) {
47989
47990( function() {
47991
47992	function stripHtml( value ) {
47993
47994		// Remove html tags and space chars
47995		return value.replace( /<.[^<>]*?>/g, " " ).replace( /&nbsp;|&#160;/gi, " " )
47996
47997		// Remove punctuation
47998		.replace( /[.(),;:!?%#$'\"_+=\/\-“”’]*/g, "" );
47999	}
48000
48001	$.validator.addMethod( "maxWords", function( value, element, params ) {
vendor: 4,587 bytes, lines 48002-48134
48002		return this.optional( element ) || stripHtml( value ).match( /\b\w+\b/g ).length <= params;
48003	}, $.validator.format( "Please enter {0} words or less." ) );
48004
48005	$.validator.addMethod( "minWords", function( value, element, params ) {
48006		return this.optional( element ) || stripHtml( value ).match( /\b\w+\b/g ).length >= params;
48007	}, $.validator.format( "Please enter at least {0} words." ) );
48008
48009	$.validator.addMethod( "rangeWords", function( value, element, params ) {
48010		var valueStripped = stripHtml( value ),
48011			regex = /\b\w+\b/g;
48012		return this.optional( element ) || valueStripped.match( regex ).length >= params[ 0 ] && valueStripped.match( regex ).length <= params[ 1 ];
48013	}, $.validator.format( "Please enter between {0} and {1} words." ) );
48014
48015}() );
48016
48017/**
48018 * This is used in the United States to process payments, deposits,
48019 * or transfers using the Automated Clearing House (ACH) or Fedwire
48020 * systems. A very common use case would be to validate a form for
48021 * an ACH bill payment.
48022 */
48023$.validator.addMethod( "abaRoutingNumber", function( value ) {
48024	var checksum = 0;
48025	var tokens = value.split( "" );
48026	var length = tokens.length;
48027
48028	// Length Check
48029	if ( length !== 9 ) {
48030		return false;
48031	}
48032
48033	// Calc the checksum
48034	// https://en.wikipedia.org/wiki/ABA_routing_transit_number
48035	for ( var i = 0; i < length; i += 3 ) {
48036		checksum +=	parseInt( tokens[ i ], 10 )     * 3 +
48037					parseInt( tokens[ i + 1 ], 10 ) * 7 +
48038					parseInt( tokens[ i + 2 ], 10 );
48039	}
48040
48041	// If not zero and divisible by 10 then valid
48042	if ( checksum !== 0 && checksum % 10 === 0 ) {
48043		return true;
48044	}
48045
48046	return false;
48047}, "Please enter a valid routing number." );
48048
48049// Accept a value from a file input based on a required mimetype
48050$.validator.addMethod( "accept", function( value, element, param ) {
48051
48052	// Split mime on commas in case we have multiple types we can accept
48053	var typeParam = typeof param === "string" ? param.replace( /\s/g, "" ) : "image/*",
48054		optionalValue = this.optional( element ),
48055		i, file, regex;
48056
48057	// Element is optional
48058	if ( optionalValue ) {
48059		return optionalValue;
48060	}
48061
48062	if ( $( element ).attr( "type" ) === "file" ) {
48063
48064		// Escape string to be used in the regex
48065		// see: https://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
48066		// Escape also "/*" as "/.*" as a wildcard
48067		typeParam = typeParam
48068				.replace( /[\-\[\]\/\{\}\(\)\+\?\.\\\^\$\|]/g, "\\$&" )
48069				.replace( /,/g, "|" )
48070				.replace( /\/\*/g, "/.*" );
48071
48072		// Check if the element has a FileList before checking each file
48073		if ( element.files && element.files.length ) {
48074			regex = new RegExp( ".?(" + typeParam + ")$", "i" );
48075			for ( i = 0; i < element.files.length; i++ ) {
48076				file = element.files[ i ];
48077
48078				// Grab the mimetype from the loaded file, verify it matches
48079				if ( !file.type.match( regex ) ) {
48080					return false;
48081				}
48082			}
48083		}
48084	}
48085
48086	// Either return true because we've validated each file, or because the
48087	// browser does not support element.files and the FileList feature
48088	return true;
48089}, $.validator.format( "Please enter a value with a valid mimetype." ) );
48090
48091$.validator.addMethod( "alphanumeric", function( value, element ) {
48092	return this.optional( element ) || /^\w+$/i.test( value );
48093}, "Letters, numbers, and underscores only please" );
48094
48095/*
48096 * Dutch bank account numbers (not 'giro' numbers) have 9 digits
48097 * and pass the '11 check'.
48098 * We accept the notation with spaces, as that is common.
48099 * acceptable: 123456789 or 12 34 56 789
48100 */
48101$.validator.addMethod( "bankaccountNL", function( value, element ) {
48102	if ( this.optional( element ) ) {
48103		return true;
48104	}
48105	if ( !( /^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test( value ) ) ) {
48106		return false;
48107	}
48108
48109	// Now '11 check'
48110	var account = value.replace( / /g, "" ), // Remove spaces
48111		sum = 0,
48112		len = account.length,
48113		pos, factor, digit;
48114	for ( pos = 0; pos < len; pos++ ) {
48115		factor = len - pos;
48116		digit = account.substring( pos, pos + 1 );
48117		sum = sum + factor * digit;
48118	}
48119	return sum % 11 === 0;
48120}, "Please specify a valid bank account number" );
48121
48122$.validator.addMethod( "bankorgiroaccountNL", function( value, element ) {
48123	return this.optional( element ) ||
48124			( $.validator.methods.bankaccountNL.call( this, value, element ) ) ||
48125			( $.validator.methods.giroaccountNL.call( this, value, element ) );
48126}, "Please specify a valid bank or giro account number" );
48127
48128/**
48129 * BIC is the business identifier code (ISO 9362). This BIC check is not a guarantee for authenticity.
48130 *
48131 * BIC pattern: BBBBCCLLbbb (8 or 11 characters long; bbb is optional)
48132 *
48133 * Validation is case-insensitive. Please make sure to normalize input yourself.
48134 *
48135 * BIC definition in detail:
48136 * - First 4 characters - bank code (only letters)
48137 * - Next 2 characters - ISO 3166-1 alpha-2 country code (only letters)
48138 * - Next 2 characters - location code (letters and digits)
48139 *   a. shall not start with '0' or '1'
48140 *   b. second character must be a letter ('O' is not allowed) or digit ('0' for test (therefore not allowed), '1' denoting passive participant, '2' typically reverse-billing)
48141 * - Last 3 characters - branch code, optional (shall not start with 'X' except in case of 'XXX' for primary office) (letters and digits)
48142 */
48143$.validator.addMethod( "bic", function( value, element ) {
48144    return this.optional( element ) || /^([A-Z]{6}[A-Z2-9][A-NP-Z1-9])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test( value.toUpperCase() );
48145}, "Please specify a valid BIC code" );
48146
48147/*
48148 * Código de identificación fiscal ( CIF ) is the tax identification code for Spanish legal entities
48149 * Further rules can be found in Spanish on http://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal
48150 *
48151 * Spanish CIF structure:
48152 *
48153 * [ T ][ P ][ P ][ N ][ N ][ N ][ N ][ N ][ C ]
48154 *
48155 * Where:
48156 *
48157 * T: 1 character. Kind of Organization Letter: [ABCDEFGHJKLMNPQRSUVW]
48158 * P: 2 characters. Province.
48159 * N: 5 characters. Secuencial Number within the province.
48160 * C: 1 character. Control Digit: [0-9A-J].
48161 *
48162 * [ T ]: Kind of Organizations. Possible values:
48163 *
48164 *   A. Corporations
48165 *   B. LLCs
48166 *   C. General partnerships
48167 *   D. Companies limited partnerships
48168 *   E. Communities of goods
48169 *   F. Cooperative Societies
48170 *   G. Associations
48171 *   H. Communities of homeowners in horizontal property regime
48172 *   J. Civil Societies
48173 *   K. Old format
48174 *   L. Old format
48175 *   M. Old format
48176 *   N. Nonresident entities
48177 *   P. Local authorities
48178 *   Q. Autonomous bodies, state or not, and the like, and congregations and religious institutions
48179 *   R. Congregations and religious institutions (since 2008 ORDER EHA/451/2008)
48180 *   S. Organs of State Administration and regions
48181 *   V. Agrarian Transformation
48182 *   W. Permanent establishments of non-resident in Spain
48183 *
48184 * [ C ]: Control Digit. It can be a number or a letter depending on T value:
48185 * [ T ]  -->  [ C ]
48186 * ------    ----------
48187 *   A         Number
48188 *   B         Number
48189 *   E         Number
48190 *   H         Number
48191 *   K         Letter
48192 *   P         Letter
48193 *   Q         Letter
48194 *   S         Letter
48195 *
48196 */
48197$.validator.addMethod( "cifES", function( value, element ) {
48198	"use strict";
48199
48200	if ( this.optional( element ) ) {
48201		return true;
48202	}
48203
48204	var cifRegEx = new RegExp( /^([ABCDEFGHJKLMNPQRSUVW])(\d{7})([0-9A-J])$/gi );
48205	var letter  = value.substring( 0, 1 ), // [ T ]
48206		number  = value.substring( 1, 8 ), // [ P ][ P ][ N ][ N ][ N ][ N ][ N ]
48207		control = value.substring( 8, 9 ), // [ C ]
48208		all_sum = 0,
48209		even_sum = 0,
48210		odd_sum = 0,
48211		i, n,
48212		control_digit,
48213		control_letter;
48214
48215	function isOdd( n ) {
48216		return n % 2 === 0;
48217	}
48218
48219	// Quick format test
48220	if ( value.length !== 9 || !cifRegEx.test( value ) ) {
48221		return false;
48222	}
48223
48224	for ( i = 0; i < number.length; i++ ) {
48225		n = parseInt( number[ i ], 10 );
48226
48227		// Odd positions
48228		if ( isOdd( i ) ) {
48229
48230			// Odd positions are multiplied first.
48231			n *= 2;
48232
48233			// If the multiplication is bigger than 10 we need to adjust
48234			odd_sum += n < 10 ? n : n - 9;
48235
48236		// Even positions
48237		// Just sum them
48238		} else {
48239			even_sum += n;
48240		}
48241	}
48242
48243	all_sum = even_sum + odd_sum;
48244	control_digit = ( 10 - ( all_sum ).toString().substr( -1 ) ).toString();
48245	control_digit = parseInt( control_digit, 10 ) > 9 ? "0" : control_digit;
48246	control_letter = "JABCDEFGHI".substr( control_digit, 1 ).toString();
48247
48248	// Control must be a digit
48249	if ( letter.match( /[ABEH]/ ) ) {
48250		return control === control_digit;
48251
48252	// Control must be a letter
48253	} else if ( letter.match( /[KPQS]/ ) ) {
48254		return control === control_letter;
48255	}
48256
48257	// Can be either
48258	return control === control_digit || control === control_letter;
48259
48260}, "Please specify a valid CIF number." );
48261
48262/*
48263 * Brazillian CNH number (Carteira Nacional de Habilitacao) is the License Driver number.
48264 * CNH numbers have 11 digits in total: 9 numbers followed by 2 check numbers that are being used for validation.
48265 */
48266$.validator.addMethod( "cnhBR", function( value ) {
48267
48268  // Removing special characters from value
48269  value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" );
48270
48271  // Checking value to have 11 digits only
48272  if ( value.length !== 11 ) {
48273    return false;
vendor: 28,037 bytes, lines 48274-49165
48274  }
48275
48276  var sum = 0, dsc = 0, firstChar,
48277		firstCN, secondCN, i, j, v;
48278
48279  firstChar = value.charAt( 0 );
48280
48281  if ( new Array( 12 ).join( firstChar ) === value ) {
48282    return false;
48283  }
48284
48285  // Step 1 - using first Check Number:
48286  for ( i = 0, j = 9, v = 0; i < 9; ++i, --j ) {
48287    sum += +( value.charAt( i ) * j );
48288  }
48289
48290  firstCN = sum % 11;
48291  if ( firstCN >= 10 ) {
48292    firstCN = 0;
48293    dsc = 2;
48294  }
48295
48296  sum = 0;
48297  for ( i = 0, j = 1, v = 0; i < 9; ++i, ++j ) {
48298    sum += +( value.charAt( i ) * j );
48299  }
48300
48301  secondCN = sum % 11;
48302  if ( secondCN >= 10 ) {
48303    secondCN = 0;
48304  } else {
48305    secondCN = secondCN - dsc;
48306  }
48307
48308  return ( String( firstCN ).concat( secondCN ) === value.substr( -2 ) );
48309
48310}, "Please specify a valid CNH number" );
48311
48312/*
48313 * Brazillian value number (Cadastrado de Pessoas Juridica).
48314 * value numbers have 14 digits in total: 12 numbers followed by 2 check numbers that are being used for validation.
48315 */
48316$.validator.addMethod( "cnpjBR", function( value, element ) {
48317	"use strict";
48318
48319	if ( this.optional( element ) ) {
48320		return true;
48321	}
48322
48323	// Removing no number
48324	value = value.replace( /[^\d]+/g, "" );
48325
48326	// Checking value to have 14 digits only
48327	if ( value.length !== 14 ) {
48328		return false;
48329	}
48330
48331	// Elimina values invalidos conhecidos
48332	if ( value === "00000000000000" ||
48333		value === "11111111111111" ||
48334		value === "22222222222222" ||
48335		value === "33333333333333" ||
48336		value === "44444444444444" ||
48337		value === "55555555555555" ||
48338		value === "66666666666666" ||
48339		value === "77777777777777" ||
48340		value === "88888888888888" ||
48341		value === "99999999999999" ) {
48342		return false;
48343	}
48344
48345	// Valida DVs
48346	var tamanho = ( value.length - 2 );
48347	var numeros = value.substring( 0, tamanho );
48348	var digitos = value.substring( tamanho );
48349	var soma = 0;
48350	var pos = tamanho - 7;
48351
48352	for ( var i = tamanho; i >= 1; i-- ) {
48353		soma += numeros.charAt( tamanho - i ) * pos--;
48354		if ( pos < 2 ) {
48355			pos = 9;
48356		}
48357	}
48358
48359	var resultado = soma % 11 < 2 ? 0 : 11 - soma % 11;
48360
48361	if ( resultado !== parseInt( digitos.charAt( 0 ), 10 ) ) {
48362		return false;
48363	}
48364
48365	tamanho = tamanho + 1;
48366	numeros = value.substring( 0, tamanho );
48367	soma = 0;
48368	pos = tamanho - 7;
48369
48370	for ( var il = tamanho; il >= 1; il-- ) {
48371		soma += numeros.charAt( tamanho - il ) * pos--;
48372		if ( pos < 2 ) {
48373			pos = 9;
48374		}
48375	}
48376
48377	resultado = soma % 11 < 2 ? 0 : 11 - soma % 11;
48378
48379	if ( resultado !== parseInt( digitos.charAt( 1 ), 10 ) ) {
48380		return false;
48381	}
48382
48383	return true;
48384
48385}, "Please specify a CNPJ value number" );
48386
48387/*
48388 * Brazillian CPF number (Cadastrado de Pessoas Físicas) is the equivalent of a Brazilian tax registration number.
48389 * CPF numbers have 11 digits in total: 9 numbers followed by 2 check numbers that are being used for validation.
48390 */
48391$.validator.addMethod( "cpfBR", function( value, element ) {
48392	"use strict";
48393
48394	if ( this.optional( element ) ) {
48395		return true;
48396	}
48397
48398	// Removing special characters from value
48399	value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" );
48400
48401	// Checking value to have 11 digits only
48402	if ( value.length !== 11 ) {
48403		return false;
48404	}
48405
48406	var sum = 0,
48407		firstCN, secondCN, checkResult, i;
48408
48409	firstCN = parseInt( value.substring( 9, 10 ), 10 );
48410	secondCN = parseInt( value.substring( 10, 11 ), 10 );
48411
48412	checkResult = function( sum, cn ) {
48413		var result = ( sum * 10 ) % 11;
48414		if ( ( result === 10 ) || ( result === 11 ) ) {
48415			result = 0;
48416		}
48417		return ( result === cn );
48418	};
48419
48420	// Checking for dump data
48421	if ( value === "" ||
48422		value === "00000000000" ||
48423		value === "11111111111" ||
48424		value === "22222222222" ||
48425		value === "33333333333" ||
48426		value === "44444444444" ||
48427		value === "55555555555" ||
48428		value === "66666666666" ||
48429		value === "77777777777" ||
48430		value === "88888888888" ||
48431		value === "99999999999"
48432	) {
48433		return false;
48434	}
48435
48436	// Step 1 - using first Check Number:
48437	for ( i = 1; i <= 9; i++ ) {
48438		sum = sum + parseInt( value.substring( i - 1, i ), 10 ) * ( 11 - i );
48439	}
48440
48441	// If first Check Number (CN) is valid, move to Step 2 - using second Check Number:
48442	if ( checkResult( sum, firstCN ) ) {
48443		sum = 0;
48444		for ( i = 1; i <= 10; i++ ) {
48445			sum = sum + parseInt( value.substring( i - 1, i ), 10 ) * ( 12 - i );
48446		}
48447		return checkResult( sum, secondCN );
48448	}
48449	return false;
48450
48451}, "Please specify a valid CPF number" );
48452
48453// https://jqueryvalidation.org/creditcard-method/
48454// based on https://en.wikipedia.org/wiki/Luhn_algorithm
48455$.validator.addMethod( "creditcard", function( value, element ) {
48456	if ( this.optional( element ) ) {
48457		return "dependency-mismatch";
48458	}
48459
48460	// Accept only spaces, digits and dashes
48461	if ( /[^0-9 \-]+/.test( value ) ) {
48462		return false;
48463	}
48464
48465	var nCheck = 0,
48466		nDigit = 0,
48467		bEven = false,
48468		n, cDigit;
48469
48470	value = value.replace( /\D/g, "" );
48471
48472	// Basing min and max length on
48473	// https://dev.ean.com/general-info/valid-card-types/
48474	if ( value.length < 13 || value.length > 19 ) {
48475		return false;
48476	}
48477
48478	for ( n = value.length - 1; n >= 0; n-- ) {
48479		cDigit = value.charAt( n );
48480		nDigit = parseInt( cDigit, 10 );
48481		if ( bEven ) {
48482			if ( ( nDigit *= 2 ) > 9 ) {
48483				nDigit -= 9;
48484			}
48485		}
48486
48487		nCheck += nDigit;
48488		bEven = !bEven;
48489	}
48490
48491	return ( nCheck % 10 ) === 0;
48492}, "Please enter a valid credit card number." );
48493
48494/* NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator
48495 * Redistributed under the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0
48496 * Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings)
48497 */
48498$.validator.addMethod( "creditcardtypes", function( value, element, param ) {
48499	if ( /[^0-9\-]+/.test( value ) ) {
48500		return false;
48501	}
48502
48503	value = value.replace( /\D/g, "" );
48504
48505	var validTypes = 0x0000;
48506
48507	if ( param.mastercard ) {
48508		validTypes |= 0x0001;
48509	}
48510	if ( param.visa ) {
48511		validTypes |= 0x0002;
48512	}
48513	if ( param.amex ) {
48514		validTypes |= 0x0004;
48515	}
48516	if ( param.dinersclub ) {
48517		validTypes |= 0x0008;
48518	}
48519	if ( param.enroute ) {
48520		validTypes |= 0x0010;
48521	}
48522	if ( param.discover ) {
48523		validTypes |= 0x0020;
48524	}
48525	if ( param.jcb ) {
48526		validTypes |= 0x0040;
48527	}
48528	if ( param.unknown ) {
48529		validTypes |= 0x0080;
48530	}
48531	if ( param.all ) {
48532		validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080;
48533	}
48534	if ( validTypes & 0x0001 && ( /^(5[12345])/.test( value ) || /^(2[234567])/.test( value ) ) ) { // Mastercard
48535		return value.length === 16;
48536	}
48537	if ( validTypes & 0x0002 && /^(4)/.test( value ) ) { // Visa
48538		return value.length === 16;
48539	}
48540	if ( validTypes & 0x0004 && /^(3[47])/.test( value ) ) { // Amex
48541		return value.length === 15;
48542	}
48543	if ( validTypes & 0x0008 && /^(3(0[012345]|[68]))/.test( value ) ) { // Dinersclub
48544		return value.length === 14;
48545	}
48546	if ( validTypes & 0x0010 && /^(2(014|149))/.test( value ) ) { // Enroute
48547		return value.length === 15;
48548	}
48549	if ( validTypes & 0x0020 && /^(6011)/.test( value ) ) { // Discover
48550		return value.length === 16;
48551	}
48552	if ( validTypes & 0x0040 && /^(3)/.test( value ) ) { // Jcb
48553		return value.length === 16;
48554	}
48555	if ( validTypes & 0x0040 && /^(2131|1800)/.test( value ) ) { // Jcb
48556		return value.length === 15;
48557	}
48558	if ( validTypes & 0x0080 ) { // Unknown
48559		return true;
48560	}
48561	return false;
48562}, "Please enter a valid credit card number." );
48563
48564/**
48565 * Validates currencies with any given symbols by @jameslouiz
48566 * Symbols can be optional or required. Symbols required by default
48567 *
48568 * Usage examples:
48569 *  currency: ["£", false] - Use false for soft currency validation
48570 *  currency: ["$", false]
48571 *  currency: ["RM", false] - also works with text based symbols such as "RM" - Malaysia Ringgit etc
48572 *
48573 *  <input class="currencyInput" name="currencyInput">
48574 *
48575 * Soft symbol checking
48576 *  currencyInput: {
48577 *     currency: ["$", false]
48578 *  }
48579 *
48580 * Strict symbol checking (default)
48581 *  currencyInput: {
48582 *     currency: "$"
48583 *     //OR
48584 *     currency: ["$", true]
48585 *  }
48586 *
48587 * Multiple Symbols
48588 *  currencyInput: {
48589 *     currency: "$,£,¢"
48590 *  }
48591 */
48592$.validator.addMethod( "currency", function( value, element, param ) {
48593    var isParamString = typeof param === "string",
48594        symbol = isParamString ? param : param[ 0 ],
48595        soft = isParamString ? true : param[ 1 ],
48596        regex;
48597
48598    symbol = symbol.replace( /,/g, "" );
48599    symbol = soft ? symbol + "]" : symbol + "]?";
48600    regex = "^[" + symbol + "([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$";
48601    regex = new RegExp( regex );
48602    return this.optional( element ) || regex.test( value );
48603
48604}, "Please specify a valid currency" );
48605
48606$.validator.addMethod( "dateFA", function( value, element ) {
48607	return this.optional( element ) || /^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test( value );
48608}, $.validator.messages.date );
48609
48610/**
48611 * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy.
48612 *
48613 * @example $.validator.methods.date("01/01/1900")
48614 * @result true
48615 *
48616 * @example $.validator.methods.date("01/13/1990")
48617 * @result false
48618 *
48619 * @example $.validator.methods.date("01.01.1900")
48620 * @result false
48621 *
48622 * @example <input name="pippo" class="{dateITA:true}" />
48623 * @desc Declares an optional input element whose value must be a valid date.
48624 *
48625 * @name $.validator.methods.dateITA
48626 * @type Boolean
48627 * @cat Plugins/Validate/Methods
48628 */
48629$.validator.addMethod( "dateITA", function( value, element ) {
48630	var check = false,
48631		re = /^\d{1,2}\/\d{1,2}\/\d{4}$/,
48632		adata, gg, mm, aaaa, xdata;
48633	if ( re.test( value ) ) {
48634		adata = value.split( "/" );
48635		gg = parseInt( adata[ 0 ], 10 );
48636		mm = parseInt( adata[ 1 ], 10 );
48637		aaaa = parseInt( adata[ 2 ], 10 );
48638		xdata = new Date( Date.UTC( aaaa, mm - 1, gg, 12, 0, 0, 0 ) );
48639		if ( ( xdata.getUTCFullYear() === aaaa ) && ( xdata.getUTCMonth() === mm - 1 ) && ( xdata.getUTCDate() === gg ) ) {
48640			check = true;
48641		} else {
48642			check = false;
48643		}
48644	} else {
48645		check = false;
48646	}
48647	return this.optional( element ) || check;
48648}, $.validator.messages.date );
48649
48650$.validator.addMethod( "dateNL", function( value, element ) {
48651	return this.optional( element ) || /^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test( value );
48652}, $.validator.messages.date );
48653
48654// Older "accept" file extension method. Old docs: http://docs.jquery.com/Plugins/Validation/Methods/accept
48655$.validator.addMethod( "extension", function( value, element, param ) {
48656	param = typeof param === "string" ? param.replace( /,/g, "|" ) : "png|jpe?g|gif";
48657	return this.optional( element ) || value.match( new RegExp( "\\.(" + param + ")$", "i" ) );
48658}, $.validator.format( "Please enter a value with a valid extension." ) );
48659
48660/**
48661 * Dutch giro account numbers (not bank numbers) have max 7 digits
48662 */
48663$.validator.addMethod( "giroaccountNL", function( value, element ) {
48664	return this.optional( element ) || /^[0-9]{1,7}$/.test( value );
48665}, "Please specify a valid giro account number" );
48666
48667$.validator.addMethod( "greaterThan", function( value, element, param ) {
48668    var target = $( param );
48669
48670    if ( this.settings.onfocusout && target.not( ".validate-greaterThan-blur" ).length ) {
48671        target.addClass( "validate-greaterThan-blur" ).on( "blur.validate-greaterThan", function() {
48672            $( element ).valid();
48673        } );
48674    }
48675
48676    return value > target.val();
48677}, "Please enter a greater value." );
48678
48679$.validator.addMethod( "greaterThanEqual", function( value, element, param ) {
48680    var target = $( param );
48681
48682    if ( this.settings.onfocusout && target.not( ".validate-greaterThanEqual-blur" ).length ) {
48683        target.addClass( "validate-greaterThanEqual-blur" ).on( "blur.validate-greaterThanEqual", function() {
48684            $( element ).valid();
48685        } );
48686    }
48687
48688    return value >= target.val();
48689}, "Please enter a greater value." );
48690
48691/**
48692 * IBAN is the international bank account number.
48693 * It has a country - specific format, that is checked here too
48694 *
48695 * Validation is case-insensitive. Please make sure to normalize input yourself.
48696 */
48697$.validator.addMethod( "iban", function( value, element ) {
48698
48699	// Some quick simple tests to prevent needless work
48700	if ( this.optional( element ) ) {
48701		return true;
48702	}
48703
48704	// Remove spaces and to upper case
48705	var iban = value.replace( / /g, "" ).toUpperCase(),
48706		ibancheckdigits = "",
48707		leadingZeroes = true,
48708		cRest = "",
48709		cOperator = "",
48710		countrycode, ibancheck, charAt, cChar, bbanpattern, bbancountrypatterns, ibanregexp, i, p;
48711
48712	// Check for IBAN code length.
48713	// It contains:
48714	// country code ISO 3166-1 - two letters,
48715	// two check digits,
48716	// Basic Bank Account Number (BBAN) - up to 30 chars
48717	var minimalIBANlength = 5;
48718	if ( iban.length < minimalIBANlength ) {
48719		return false;
48720	}
48721
48722	// Check the country code and find the country specific format
48723	countrycode = iban.substring( 0, 2 );
48724	bbancountrypatterns = {
48725		"AL": "\\d{8}[\\dA-Z]{16}",
48726		"AD": "\\d{8}[\\dA-Z]{12}",
48727		"AT": "\\d{16}",
48728		"AZ": "[\\dA-Z]{4}\\d{20}",
48729		"BE": "\\d{12}",
48730		"BH": "[A-Z]{4}[\\dA-Z]{14}",
48731		"BA": "\\d{16}",
48732		"BR": "\\d{23}[A-Z][\\dA-Z]",
48733		"BG": "[A-Z]{4}\\d{6}[\\dA-Z]{8}",
48734		"CR": "\\d{17}",
48735		"HR": "\\d{17}",
48736		"CY": "\\d{8}[\\dA-Z]{16}",
48737		"CZ": "\\d{20}",
48738		"DK": "\\d{14}",
48739		"DO": "[A-Z]{4}\\d{20}",
48740		"EE": "\\d{16}",
48741		"FO": "\\d{14}",
48742		"FI": "\\d{14}",
48743		"FR": "\\d{10}[\\dA-Z]{11}\\d{2}",
48744		"GE": "[\\dA-Z]{2}\\d{16}",
48745		"DE": "\\d{18}",
48746		"GI": "[A-Z]{4}[\\dA-Z]{15}",
48747		"GR": "\\d{7}[\\dA-Z]{16}",
48748		"GL": "\\d{14}",
48749		"GT": "[\\dA-Z]{4}[\\dA-Z]{20}",
48750		"HU": "\\d{24}",
48751		"IS": "\\d{22}",
48752		"IE": "[\\dA-Z]{4}\\d{14}",
48753		"IL": "\\d{19}",
48754		"IT": "[A-Z]\\d{10}[\\dA-Z]{12}",
48755		"KZ": "\\d{3}[\\dA-Z]{13}",
48756		"KW": "[A-Z]{4}[\\dA-Z]{22}",
48757		"LV": "[A-Z]{4}[\\dA-Z]{13}",
48758		"LB": "\\d{4}[\\dA-Z]{20}",
48759		"LI": "\\d{5}[\\dA-Z]{12}",
48760		"LT": "\\d{16}",
48761		"LU": "\\d{3}[\\dA-Z]{13}",
48762		"MK": "\\d{3}[\\dA-Z]{10}\\d{2}",
48763		"MT": "[A-Z]{4}\\d{5}[\\dA-Z]{18}",
48764		"MR": "\\d{23}",
48765		"MU": "[A-Z]{4}\\d{19}[A-Z]{3}",
48766		"MC": "\\d{10}[\\dA-Z]{11}\\d{2}",
48767		"MD": "[\\dA-Z]{2}\\d{18}",
48768		"ME": "\\d{18}",
48769		"NL": "[A-Z]{4}\\d{10}",
48770		"NO": "\\d{11}",
48771		"PK": "[\\dA-Z]{4}\\d{16}",
48772		"PS": "[\\dA-Z]{4}\\d{21}",
48773		"PL": "\\d{24}",
48774		"PT": "\\d{21}",
48775		"RO": "[A-Z]{4}[\\dA-Z]{16}",
48776		"SM": "[A-Z]\\d{10}[\\dA-Z]{12}",
48777		"SA": "\\d{2}[\\dA-Z]{18}",
48778		"RS": "\\d{18}",
48779		"SK": "\\d{20}",
48780		"SI": "\\d{15}",
48781		"ES": "\\d{20}",
48782		"SE": "\\d{20}",
48783		"CH": "\\d{5}[\\dA-Z]{12}",
48784		"TN": "\\d{20}",
48785		"TR": "\\d{5}[\\dA-Z]{17}",
48786		"AE": "\\d{3}\\d{16}",
48787		"GB": "[A-Z]{4}\\d{14}",
48788		"VG": "[\\dA-Z]{4}\\d{16}"
48789	};
48790
48791	bbanpattern = bbancountrypatterns[ countrycode ];
48792
48793	// As new countries will start using IBAN in the
48794	// future, we only check if the countrycode is known.
48795	// This prevents false negatives, while almost all
48796	// false positives introduced by this, will be caught
48797	// by the checksum validation below anyway.
48798	// Strict checking should return FALSE for unknown
48799	// countries.
48800	if ( typeof bbanpattern !== "undefined" ) {
48801		ibanregexp = new RegExp( "^[A-Z]{2}\\d{2}" + bbanpattern + "$", "" );
48802		if ( !( ibanregexp.test( iban ) ) ) {
48803			return false; // Invalid country specific format
48804		}
48805	}
48806
48807	// Now check the checksum, first convert to digits
48808	ibancheck = iban.substring( 4, iban.length ) + iban.substring( 0, 4 );
48809	for ( i = 0; i < ibancheck.length; i++ ) {
48810		charAt = ibancheck.charAt( i );
48811		if ( charAt !== "0" ) {
48812			leadingZeroes = false;
48813		}
48814		if ( !leadingZeroes ) {
48815			ibancheckdigits += "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf( charAt );
48816		}
48817	}
48818
48819	// Calculate the result of: ibancheckdigits % 97
48820	for ( p = 0; p < ibancheckdigits.length; p++ ) {
48821		cChar = ibancheckdigits.charAt( p );
48822		cOperator = "" + cRest + "" + cChar;
48823		cRest = cOperator % 97;
48824	}
48825	return cRest === 1;
48826}, "Please specify a valid IBAN" );
48827
48828$.validator.addMethod( "integer", function( value, element ) {
48829	return this.optional( element ) || /^-?\d+$/.test( value );
48830}, "A positive or negative non-decimal number please" );
48831
48832$.validator.addMethod( "ipv4", function( value, element ) {
48833	return this.optional( element ) || /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test( value );
48834}, "Please enter a valid IP v4 address." );
48835
48836$.validator.addMethod( "ipv6", function( value, element ) {
48837	return this.optional( element ) || /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test( value );
48838}, "Please enter a valid IP v6 address." );
48839
48840$.validator.addMethod( "lessThan", function( value, element, param ) {
48841    var target = $( param );
48842
48843    if ( this.settings.onfocusout && target.not( ".validate-lessThan-blur" ).length ) {
48844        target.addClass( "validate-lessThan-blur" ).on( "blur.validate-lessThan", function() {
48845            $( element ).valid();
48846        } );
48847    }
48848
48849    return value < target.val();
48850}, "Please enter a lesser value." );
48851
48852$.validator.addMethod( "lessThanEqual", function( value, element, param ) {
48853    var target = $( param );
48854
48855    if ( this.settings.onfocusout && target.not( ".validate-lessThanEqual-blur" ).length ) {
48856        target.addClass( "validate-lessThanEqual-blur" ).on( "blur.validate-lessThanEqual", function() {
48857            $( element ).valid();
48858        } );
48859    }
48860
48861    return value <= target.val();
48862}, "Please enter a lesser value." );
48863
48864$.validator.addMethod( "lettersonly", function( value, element ) {
48865	return this.optional( element ) || /^[a-z]+$/i.test( value );
48866}, "Letters only please" );
48867
48868$.validator.addMethod( "letterswithbasicpunc", function( value, element ) {
48869	return this.optional( element ) || /^[a-z\-.,()'"\s]+$/i.test( value );
48870}, "Letters or punctuation only please" );
48871
48872// Limit the number of files in a FileList.
48873$.validator.addMethod( "maxfiles", function( value, element, param ) {
48874	if ( this.optional( element ) ) {
48875		return true;
48876	}
48877
48878	if ( $( element ).attr( "type" ) === "file" ) {
48879		if ( element.files && element.files.length > param ) {
48880			return false;
48881		}
48882	}
48883
48884	return true;
48885}, $.validator.format( "Please select no more than {0} files." ) );
48886
48887// Limit the size of each individual file in a FileList.
48888$.validator.addMethod( "maxsize", function( value, element, param ) {
48889	if ( this.optional( element ) ) {
48890		return true;
48891	}
48892
48893	if ( $( element ).attr( "type" ) === "file" ) {
48894		if ( element.files && element.files.length ) {
48895			for ( var i = 0; i < element.files.length; i++ ) {
48896				if ( element.files[ i ].size > param ) {
48897					return false;
48898				}
48899			}
48900		}
48901	}
48902
48903	return true;
48904}, $.validator.format( "File size must not exceed {0} bytes each." ) );
48905
48906// Limit the size of all files in a FileList.
48907$.validator.addMethod( "maxsizetotal", function( value, element, param ) {
48908	if ( this.optional( element ) ) {
48909		return true;
48910	}
48911
48912	if ( $( element ).attr( "type" ) === "file" ) {
48913		if ( element.files && element.files.length ) {
48914			var totalSize = 0;
48915
48916			for ( var i = 0; i < element.files.length; i++ ) {
48917				totalSize += element.files[ i ].size;
48918				if ( totalSize > param ) {
48919					return false;
48920				}
48921			}
48922		}
48923	}
48924
48925	return true;
48926}, $.validator.format( "Total size of all files must not exceed {0} bytes." ) );
48927
48928
48929$.validator.addMethod( "mobileNL", function( value, element ) {
48930	return this.optional( element ) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test( value );
48931}, "Please specify a valid mobile number" );
48932
48933$.validator.addMethod( "mobileRU", function( phone_number, element ) {
48934	var ruPhone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
48935	return this.optional( element ) || ruPhone_number.length > 9 && /^((\+7|7|8)+([0-9]){10})$/.test( ruPhone_number );
48936}, "Please specify a valid mobile number" );
48937
48938/* For UK phone functions, do the following server side processing:
48939 * Compare original input with this RegEx pattern:
48940 * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
48941 * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
48942 * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
48943 * A number of very detailed GB telephone number RegEx patterns can also be found at:
48944 * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
48945 */
48946$.validator.addMethod( "mobileUK", function( phone_number, element ) {
48947	phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
48948	return this.optional( element ) || phone_number.length > 9 &&
48949		phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/ );
48950}, "Please specify a valid mobile number" );
48951
48952$.validator.addMethod( "netmask", function( value, element ) {
48953    return this.optional( element ) || /^(254|252|248|240|224|192|128)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(254|252|248|240|224|192|128|0)/i.test( value );
48954}, "Please enter a valid netmask." );
48955
48956/*
48957 * The NIE (Número de Identificación de Extranjero) is a Spanish tax identification number assigned by the Spanish
48958 * authorities to any foreigner.
48959 *
48960 * The NIE is the equivalent of a Spaniards Número de Identificación Fiscal (NIF) which serves as a fiscal
48961 * identification number. The CIF number (Certificado de Identificación Fiscal) is equivalent to the NIF, but applies to
48962 * companies rather than individuals. The NIE consists of an 'X' or 'Y' followed by 7 or 8 digits then another letter.
48963 */
48964$.validator.addMethod( "nieES", function( value, element ) {
48965	"use strict";
48966
48967	if ( this.optional( element ) ) {
48968		return true;
48969	}
48970
48971	var nieRegEx = new RegExp( /^[MXYZ]{1}[0-9]{7,8}[TRWAGMYFPDXBNJZSQVHLCKET]{1}$/gi );
48972	var validChars = "TRWAGMYFPDXBNJZSQVHLCKET",
48973		letter = value.substr( value.length - 1 ).toUpperCase(),
48974		number;
48975
48976	value = value.toString().toUpperCase();
48977
48978	// Quick format test
48979	if ( value.length > 10 || value.length < 9 || !nieRegEx.test( value ) ) {
48980		return false;
48981	}
48982
48983	// X means same number
48984	// Y means number + 10000000
48985	// Z means number + 20000000
48986	value = value.replace( /^[X]/, "0" )
48987		.replace( /^[Y]/, "1" )
48988		.replace( /^[Z]/, "2" );
48989
48990	number = value.length === 9 ? value.substr( 0, 8 ) : value.substr( 0, 9 );
48991
48992	return validChars.charAt( parseInt( number, 10 ) % 23 ) === letter;
48993
48994}, "Please specify a valid NIE number." );
48995
48996/*
48997 * The Número de Identificación Fiscal ( NIF ) is the way tax identification used in Spain for individuals
48998 */
48999$.validator.addMethod( "nifES", function( value, element ) {
49000	"use strict";
49001
49002	if ( this.optional( element ) ) {
49003		return true;
49004	}
49005
49006	value = value.toUpperCase();
49007
49008	// Basic format test
49009	if ( !value.match( "((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)" ) ) {
49010		return false;
49011	}
49012
49013	// Test NIF
49014	if ( /^[0-9]{8}[A-Z]{1}$/.test( value ) ) {
49015		return ( "TRWAGMYFPDXBNJZSQVHLCKE".charAt( value.substring( 8, 0 ) % 23 ) === value.charAt( 8 ) );
49016	}
49017
49018	// Test specials NIF (starts with K, L or M)
49019	if ( /^[KLM]{1}/.test( value ) ) {
49020		return ( value[ 8 ] === "TRWAGMYFPDXBNJZSQVHLCKE".charAt( value.substring( 8, 1 ) % 23 ) );
49021	}
49022
49023	return false;
49024
49025}, "Please specify a valid NIF number." );
49026
49027/*
49028 * Numer identyfikacji podatkowej ( NIP ) is the way tax identification used in Poland for companies
49029 */
49030$.validator.addMethod( "nipPL", function( value ) {
49031	"use strict";
49032
49033	value = value.replace( /[^0-9]/g, "" );
49034
49035	if ( value.length !== 10 ) {
49036		return false;
49037	}
49038
49039	var arrSteps = [ 6, 5, 7, 2, 3, 4, 5, 6, 7 ];
49040	var intSum = 0;
49041	for ( var i = 0; i < 9; i++ ) {
49042		intSum += arrSteps[ i ] * value[ i ];
49043	}
49044	var int2 = intSum % 11;
49045	var intControlNr = ( int2 === 10 ) ? 0 : int2;
49046
49047	return ( intControlNr === parseInt( value[ 9 ], 10 ) );
49048}, "Please specify a valid NIP number." );
49049
49050/**
49051 * Created for project jquery-validation.
49052 * @Description Brazillian PIS or NIS number (Número de Identificação Social Pis ou Pasep) is the equivalent of a
49053 * Brazilian tax registration number NIS of PIS numbers have 11 digits in total: 10 numbers followed by 1 check numbers
49054 * that are being used for validation.
49055 * @copyright (c) 21/08/2018 13:14, Cleiton da Silva Mendonça
49056 * @author Cleiton da Silva Mendonça <[email protected]>
49057 * @link http://gitlab.com/csmendonca Gitlab of Cleiton da Silva Mendonça
49058 * @link http://github.com/csmendonca Github of Cleiton da Silva Mendonça
49059 */
49060$.validator.addMethod( "nisBR", function( value ) {
49061	var number;
49062	var cn;
49063	var sum = 0;
49064	var dv;
49065	var count;
49066	var multiplier;
49067
49068	// Removing special characters from value
49069	value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" );
49070
49071	// Checking value to have 11 digits only
49072	if ( value.length !== 11 ) {
49073		return false;
49074	}
49075
49076	//Get check number of value
49077	cn = parseInt( value.substring( 10, 11 ), 10 );
49078
49079	//Get number with 10 digits of the value
49080	number = parseInt( value.substring( 0, 10 ), 10 );
49081
49082	for ( count = 2; count < 12; count++ ) {
49083		multiplier = count;
49084		if ( count === 10 ) {
49085			multiplier = 2;
49086		}
49087		if ( count === 11 ) {
49088			multiplier = 3;
49089		}
49090		sum += ( ( number % 10 ) * multiplier );
49091		number = parseInt( number / 10, 10 );
49092	}
49093	dv = ( sum % 11 );
49094
49095	if ( dv > 1 ) {
49096		dv = ( 11 - dv );
49097	} else {
49098		dv = 0;
49099	}
49100
49101	if ( cn === dv ) {
49102		return true;
49103	} else {
49104		return false;
49105	}
49106}, "Please specify a valid NIS/PIS number" );
49107
49108$.validator.addMethod( "notEqualTo", function( value, element, param ) {
49109	return this.optional( element ) || !$.validator.methods.equalTo.call( this, value, element, param );
49110}, "Please enter a different value, values must not be the same." );
49111
49112$.validator.addMethod( "nowhitespace", function( value, element ) {
49113	return this.optional( element ) || /^\S+$/i.test( value );
49114}, "No white space please" );
49115
49116/**
49117* Return true if the field value matches the given format RegExp
49118*
49119* @example $.validator.methods.pattern("AR1004",element,/^AR\d{4}$/)
49120* @result true
49121*
49122* @example $.validator.methods.pattern("BR1004",element,/^AR\d{4}$/)
49123* @result false
49124*
49125* @name $.validator.methods.pattern
49126* @type Boolean
49127* @cat Plugins/Validate/Methods
49128*/
49129$.validator.addMethod( "pattern", function( value, element, param ) {
49130	if ( this.optional( element ) ) {
49131		return true;
49132	}
49133	if ( typeof param === "string" ) {
49134		param = new RegExp( "^(?:" + param + ")$" );
49135	}
49136	return param.test( value );
49137}, "Invalid format." );
49138
49139/**
49140 * Dutch phone numbers have 10 digits (or 11 and start with +31).
49141 */
49142$.validator.addMethod( "phoneNL", function( value, element ) {
49143	return this.optional( element ) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test( value );
49144}, "Please specify a valid phone number." );
49145
49146/**
49147 * Polish telephone numbers have 9 digits.
49148 *
49149 * Mobile phone numbers starts with following digits:
49150 * 45, 50, 51, 53, 57, 60, 66, 69, 72, 73, 78, 79, 88.
49151 *
49152 * Fixed-line numbers starts with area codes:
49153 * 12, 13, 14, 15, 16, 17, 18, 22, 23, 24, 25, 29, 32, 33,
49154 * 34, 41, 42, 43, 44, 46, 48, 52, 54, 55, 56, 58, 59, 61,
49155 * 62, 63, 65, 67, 68, 71, 74, 75, 76, 77, 81, 82, 83, 84,
49156 * 85, 86, 87, 89, 91, 94, 95.
49157 *
49158 * Ministry of National Defence numbers and VoIP numbers starts with 26 and 39.
49159 *
49160 * Excludes intelligent networks (premium rate, shared cost, free phone numbers).
49161 *
49162 * Poland National Numbering Plan http://www.itu.int/oth/T02020000A8/en
49163 */
49164$.validator.addMethod( "phonePL", function( phone_number, element ) {
49165	phone_number = phone_number.replace( /\s+/g, "" );
49166	var regexp = /^(?:(?:(?:\+|00)?48)|(?:\(\+?48\)))?(?:1[2-8]|2[2-69]|3[2-49]|4[1-68]|5[0-9]|6[0-35-9]|[7-8][1-9]|9[145])\d{7}$/;
49167	return this.optional( element ) || regexp.test( phone_number );
49168}, "Please specify a valid phone number" );
49169
49170/* For UK phone functions, do the following server side processing:
49171 * Compare original input with this RegEx pattern:
49172 * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
49173 * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
49174 * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
49175 * A number of very detailed GB telephone number RegEx patterns can also be found at:
49176 * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
49177 */
49178
49179// Matches UK landline + mobile, accepting only 01-3 for landline or 07 for mobile to exclude many premium numbers
49180$.validator.addMethod( "phonesUK", function( phone_number, element ) {
49181	phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
49182	return this.optional( element ) || phone_number.length > 9 &&
49183		phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/ );
49184}, "Please specify a valid uk phone number" );
49185
49186/* For UK phone functions, do the following server side processing:
49187 * Compare original input with this RegEx pattern:
49188 * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
49189 * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
49190 * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
49191 * A number of very detailed GB telephone number RegEx patterns can also be found at:
49192 * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
49193 */
49194$.validator.addMethod( "phoneUK", function( phone_number, element ) {
49195	phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
49196	return this.optional( element ) || phone_number.length > 9 &&
49197		phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/ );
49198}, "Please specify a valid phone number" );
49199
49200/**
49201 * Matches US phone number format
49202 *
49203 * where the area code may not start with 1 and the prefix may not start with 1
49204 * allows '-' or ' ' as a separator and allows parens around area code
49205 * some people may want to put a '1' in front of their number
49206 *
49207 * 1(212)-999-2345 or
49208 * 212 999 2344 or
49209 * 212-999-0983
49210 *
49211 * but not
49212 * 111-123-5434
49213 * and not
49214 * 212 123 4567
49215 */
49216$.validator.addMethod( "phoneUS", function( phone_number, element ) {
49217	phone_number = phone_number.replace( /\s+/g, "" );
49218	return this.optional( element ) || phone_number.length > 9 &&
49219		phone_number.match( /^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]\d{2}-?\d{4}$/ );
49220}, "Please specify a valid phone number" );
49221
49222/*
49223* Valida CEPs do brasileiros:
49224*
49225* Formatos aceitos:
49226* 99999-999
49227* 99.999-999
49228* 99999999
49229*/
49230$.validator.addMethod( "postalcodeBR", function( cep_value, element ) {
49231	return this.optional( element ) || /^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test( cep_value );
49232}, "Informe um CEP válido." );
49233
49234/**
49235 * Matches a valid Canadian Postal Code
49236 *
49237 * @example jQuery.validator.methods.postalCodeCA( "H0H 0H0", element )
49238 * @result true
49239 *
49240 * @example jQuery.validator.methods.postalCodeCA( "H0H0H0", element )
49241 * @result false
49242 *
49243 * @name jQuery.validator.methods.postalCodeCA
49244 * @type Boolean
49245 * @cat Plugins/Validate/Methods
49246 */
49247$.validator.addMethod( "postalCodeCA", function( value, element ) {
49248	return this.optional( element ) || /^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ] *\d[ABCEGHJKLMNPRSTVWXYZ]\d$/i.test( value );
49249}, "Please specify a valid postal code" );
49250
49251/* Matches Italian postcode (CAP) */
49252$.validator.addMethod( "postalcodeIT", function( value, element ) {
49253	return this.optional( element ) || /^\d{5}$/.test( value );
49254}, "Please specify a valid postal code" );
49255
49256$.validator.addMethod( "postalcodeNL", function( value, element ) {
49257	return this.optional( element ) || /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test( value );
49258}, "Please specify a valid postal code" );
49259
49260// Matches UK postcode. Does not match to UK Channel Islands that have their own postcodes (non standard UK)
49261$.validator.addMethod( "postcodeUK", function( value, element ) {
49262	return this.optional( element ) || /^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test( value );
49263}, "Please specify a valid UK postcode" );
49264
49265/*
49266 * Lets you say "at least X inputs that match selector Y must be filled."
49267 *
49268 * The end result is that neither of these inputs:
49269 *
49270 *	<input class="productinfo" name="partnumber">
49271 *	<input class="productinfo" name="description">
49272 *
49273 *	...will validate unless at least one of them is filled.
49274 *
49275 * partnumber:	{require_from_group: [1,".productinfo"]},
49276 * description: {require_from_group: [1,".productinfo"]}
49277 *
49278 * options[0]: number of fields that must be filled in the group
49279 * options[1]: CSS selector that defines the group of conditionally required fields
49280 */
49281$.validator.addMethod( "require_from_group", function( value, element, options ) {
49282	var $fields = $( options[ 1 ], element.form ),
49283		$fieldsFirst = $fields.eq( 0 ),
49284		validator = $fieldsFirst.data( "valid_req_grp" ) ? $fieldsFirst.data( "valid_req_grp" ) : $.extend( {}, this ),
49285		isValid = $fields.filter( function() {
49286			return validator.elementValue( this );
49287		} ).length >= options[ 0 ];
49288
49289	// Store the cloned validator for future validation
49290	$fieldsFirst.data( "valid_req_grp", validator );
49291
49292	// If element isn't being validated, run each require_from_group field's validation rules
49293	if ( !$( element ).data( "being_validated" ) ) {
49294		$fields.data( "being_validated", true );
49295		$fields.each( function() {
49296			validator.element( this );
49297		} );
49298		$fields.data( "being_validated", false );
49299	}
49300	return isValid;
49301}, $.validator.format( "Please fill at least {0} of these fields." ) );
49302
49303/*
49304 * Lets you say "either at least X inputs that match selector Y must be filled,
49305 * OR they must all be skipped (left blank)."
49306 *
49307 * The end result, is that none of these inputs:
49308 *
49309 *	<input class="productinfo" name="partnumber">
49310 *	<input class="productinfo" name="description">
49311 *	<input class="productinfo" name="color">
49312 *
49313 *	...will validate unless either at least two of them are filled,
49314 *	OR none of them are.
49315 *
49316 * partnumber:	{skip_or_fill_minimum: [2,".productinfo"]},
49317 * description: {skip_or_fill_minimum: [2,".productinfo"]},
49318 * color:		{skip_or_fill_minimum: [2,".productinfo"]}
49319 *
49320 * options[0]: number of fields that must be filled in the group
49321 * options[1]: CSS selector that defines the group of conditionally required fields
49322 *
49323 */
49324$.validator.addMethod( "skip_or_fill_minimum", function( value, element, options ) {
49325	var $fields = $( options[ 1 ], element.form ),
49326		$fieldsFirst = $fields.eq( 0 ),
49327		validator = $fieldsFirst.data( "valid_skip" ) ? $fieldsFirst.data( "valid_skip" ) : $.extend( {}, this ),
49328		numberFilled = $fields.filter( function() {
49329			return validator.elementValue( this );
49330		} ).length,
49331		isValid = numberFilled === 0 || numberFilled >= options[ 0 ];
49332
49333	// Store the cloned validator for future validation
49334	$fieldsFirst.data( "valid_skip", validator );
49335
49336	// If element isn't being validated, run each skip_or_fill_minimum field's validation rules
49337	if ( !$( element ).data( "being_validated" ) ) {
49338		$fields.data( "being_validated", true );
49339		$fields.each( function() {
49340			validator.element( this );
49341		} );
49342		$fields.data( "being_validated", false );
49343	}
49344	return isValid;
49345}, $.validator.format( "Please either skip these fields or fill at least {0} of them." ) );
49346
49347/* Validates US States and/or Territories by @jdforsythe
49348 * Can be case insensitive or require capitalization - default is case insensitive
49349 * Can include US Territories or not - default does not
49350 * Can include US Military postal abbreviations (AA, AE, AP) - default does not
49351 *
49352 * Note: "States" always includes DC (District of Colombia)
49353 *
49354 * Usage examples:
49355 *
49356 *  This is the default - case insensitive, no territories, no military zones
49357 *  stateInput: {
49358 *     caseSensitive: false,
49359 *     includeTerritories: false,
49360 *     includeMilitary: false
49361 *  }
49362 *
49363 *  Only allow capital letters, no territories, no military zones
49364 *  stateInput: {
49365 *     caseSensitive: false
49366 *  }
49367 *
49368 *  Case insensitive, include territories but not military zones
49369 *  stateInput: {
49370 *     includeTerritories: true
49371 *  }
49372 *
49373 *  Only allow capital letters, include territories and military zones
49374 *  stateInput: {
49375 *     caseSensitive: true,
49376 *     includeTerritories: true,
49377 *     includeMilitary: true
49378 *  }
49379 *
49380 */
49381$.validator.addMethod( "stateUS", function( value, element, options ) {
49382	var isDefault = typeof options === "undefined",
vendor: 4,127 bytes, lines 49383-49441
49383		caseSensitive = ( isDefault || typeof options.caseSensitive === "undefined" ) ? false : options.caseSensitive,
49384		includeTerritories = ( isDefault || typeof options.includeTerritories === "undefined" ) ? false : options.includeTerritories,
49385		includeMilitary = ( isDefault || typeof options.includeMilitary === "undefined" ) ? false : options.includeMilitary,
49386		regex;
49387
49388	if ( !includeTerritories && !includeMilitary ) {
49389		regex = "^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$";
49390	} else if ( includeTerritories && includeMilitary ) {
49391		regex = "^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$";
49392	} else if ( includeTerritories ) {
49393		regex = "^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$";
49394	} else {
49395		regex = "^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$";
49396	}
49397
49398	regex = caseSensitive ? new RegExp( regex ) : new RegExp( regex, "i" );
49399	return this.optional( element ) || regex.test( value );
49400}, "Please specify a valid state" );
49401
49402// TODO check if value starts with <, otherwise don't try stripping anything
49403$.validator.addMethod( "strippedminlength", function( value, element, param ) {
49404	return $( value ).text().length >= param;
49405}, $.validator.format( "Please enter at least {0} characters" ) );
49406
49407$.validator.addMethod( "time", function( value, element ) {
49408	return this.optional( element ) || /^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test( value );
49409}, "Please enter a valid time, between 00:00 and 23:59" );
49410
49411$.validator.addMethod( "time12h", function( value, element ) {
49412	return this.optional( element ) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test( value );
49413}, "Please enter a valid time in 12-hour am/pm format" );
49414
49415// Same as url, but TLD is optional
49416$.validator.addMethod( "url2", function( value, element ) {
49417	return this.optional( element ) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test( value );
49418}, $.validator.messages.url );
49419
49420/**
49421 * Return true, if the value is a valid vehicle identification number (VIN).
49422 *
49423 * Works with all kind of text inputs.
49424 *
49425 * @example <input type="text" size="20" name="VehicleID" class="{required:true,vinUS:true}" />
49426 * @desc Declares a required input element whose value must be a valid vehicle identification number.
49427 *
49428 * @name $.validator.methods.vinUS
49429 * @type Boolean
49430 * @cat Plugins/Validate/Methods
49431 */
49432$.validator.addMethod( "vinUS", function( v ) {
49433	if ( v.length !== 17 ) {
49434		return false;
49435	}
49436
49437	var LL = [ "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" ],
49438		VL = [ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 7, 9, 2, 3, 4, 5, 6, 7, 8, 9 ],
49439		FL = [ 8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2 ],
49440		rs = 0,
49441		i, n, d, f, cd, cdv;
vendor: 11,592 bytes, lines 49442-49545
49442
49443	for ( i = 0; i < 17; i++ ) {
49444		f = FL[ i ];
49445		d = v.slice( i, i + 1 );
49446		if ( i === 8 ) {
49447			cdv = d;
49448		}
49449		if ( !isNaN( d ) ) {
49450			d *= f;
49451		} else {
49452			for ( n = 0; n < LL.length; n++ ) {
49453				if ( d.toUpperCase() === LL[ n ] ) {
49454					d = VL[ n ];
49455					d *= f;
49456					if ( isNaN( cdv ) && n === 8 ) {
49457						cdv = LL[ n ];
49458					}
49459					break;
49460				}
49461			}
49462		}
49463		rs += d;
49464	}
49465	cd = rs % 11;
49466	if ( cd === 10 ) {
49467		cd = "X";
49468	}
49469	if ( cd === cdv ) {
49470		return true;
49471	}
49472	return false;
49473}, "The specified vehicle identification number (VIN) is invalid." );
49474
49475$.validator.addMethod( "zipcodeUS", function( value, element ) {
49476	return this.optional( element ) || /^\d{5}(-\d{4})?$/.test( value );
49477}, "The specified US ZIP Code is invalid" );
49478
49479$.validator.addMethod( "ziprange", function( value, element ) {
49480	return this.optional( element ) || /^90[2-5]\d\{2\}-\d{4}$/.test( value );
49481}, "Your ZIP-code must be in the range 902xx-xxxx to 905xx-xxxx" );
49482return $;
49483}));
49484jQuery.validator.setDefaults({
49485    errorElement: 'div', //default input error message container
49486    errorClass: 'form-control-feedback', // default input error message class
49487    focusInvalid: false, // do not focus the last invalid input
49488    ignore: "",  // validate all fields including form hidden input
49489
49490    errorPlacement: function(error, element) { // render error placement for each input type
49491        var group = $(element).closest('.m-form__group-sub').length > 0 ? $(element).closest('.m-form__group-sub') : $(element).closest('.m-form__group');
49492        var help = group.find('.m-form__help');
49493
49494        if (group.find('.form-control-feedback').length !== 0) {
49495            return;
49496        }
49497
49498        if (help.length > 0) {
49499            help.before(error);
49500        } else {
49501            if ($(element).closest('.input-group').length > 0) {
49502                $(element).closest('.input-group').after(error);
49503            } else {
49504                if ($(element).is(':checkbox')) {
49505                    $(element).closest('.m-checkbox').find('>span').after(error);
49506                } else {
49507                    $(element).after(error);
49508                }                
49509            }            
49510        }
49511    },
49512
49513    highlight: function(element) { // hightlight error inputs
49514        var group = $(element).closest('.m-form__group-sub').length > 0  ? $(element).closest('.m-form__group-sub') : $(element).closest('.m-form__group');
49515        group.addClass('has-danger'); // set error class to the control groupx
49516    },
49517
49518    unhighlight: function(element) { // revert the change done by hightlight
49519        var group = $(element).closest('.m-form__group-sub').length > 0  ? $(element).closest('.m-form__group-sub') : $(element).closest('.m-form__group');
49520
49521        group.removeClass('has-danger'); // set error class to the control group
49522    },
49523
49524    success: function(label, element) {
49525        var group = $(label).closest('.m-form__group-sub').length > 0  ? $(label).closest('.m-form__group-sub') : $(label).closest('.m-form__group');
49526
49527        //group.addClass('has-success').removeClass('has-danger'); // set success class and hide error class
49528        group.removeClass('has-danger'); // hide error class
49529        group.find('.form-control-feedback').remove();
49530    }
49531});
49532
49533jQuery.validator.addMethod("email", function(value, element) {
49534    if (/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(value)) {
49535        return true;
49536    } else {
49537        return false;
49538    }
49539}, "Please enter a valid Email.");
49540!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){function b(b,d,e){var d={content:{message:"object"==typeof d?d.message:d,title:d.title?d.title:"",icon:d.icon?d.icon:"",url:d.url?d.url:"#",target:d.target?d.target:"-"}};e=a.extend(!0,{},d,e),this.settings=a.extend(!0,{},c,e),this._defaults=c,"-"==this.settings.content.target&&(this.settings.content.target=this.settings.url_target),this.animations={start:"webkitAnimationStart oanimationstart MSAnimationStart animationstart",end:"webkitAnimationEnd oanimationend MSAnimationEnd animationend"},"number"==typeof this.settings.offset&&(this.settings.offset={x:this.settings.offset,y:this.settings.offset}),this.init()}var c={element:"body",position:null,type:"info",allow_dismiss:!0,newest_on_top:!1,showProgressbar:!1,placement:{from:"top",align:"right"},offset:20,spacing:10,z_index:1031,delay:5e3,timer:1e3,url_target:"_blank",mouse_over:null,animate:{enter:"animated fadeInDown",exit:"animated fadeOutUp"},onShow:null,onShown:null,onClose:null,onClosed:null,icon_type:"class",template:'<div data-notify="container" class="col-xs-11 col-sm-4 alert alert-{0}" role="alert"><button type="button" aria-hidden="true" class="close" data-notify="dismiss">&times;</button><span data-notify="icon"></span> <span data-notify="title">{1}</span> <span data-notify="message">{2}</span><div class="progress" data-notify="progressbar"><div class="progress-bar progress-bar-{0}" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div></div><a href="{3}" target="{4}" data-notify="url"></a></div>'};String.format=function(){for(var a=arguments[0],b=1;b<arguments.length;b++)a=a.replace(RegExp("\\{"+(b-1)+"\\}","gm"),arguments[b]);return a},a.extend(b.prototype,{init:function(){var a=this;this.buildNotify(),this.settings.content.icon&&this.setIcon(),"#"!=this.settings.content.url&&this.styleURL(),this.styleDismiss(),this.placement(),this.bind(),this.notify={$ele:this.$ele,update:function(b,c){var d={};"string"==typeof b?d[b]=c:d=b;for(var b in d)switch(b){case"type":this.$ele.removeClass("alert-"+a.settings.type),this.$ele.find('[data-notify="progressbar"] > .progress-bar').removeClass("progress-bar-"+a.settings.type),a.settings.type=d[b],this.$ele.addClass("alert-"+d[b]).find('[data-notify="progressbar"] > .progress-bar').addClass("progress-bar-"+d[b]);break;case"icon":var e=this.$ele.find('[data-notify="icon"]');"class"==a.settings.icon_type.toLowerCase()?e.removeClass(a.settings.content.icon).addClass(d[b]):(e.is("img")||e.find("img"),e.attr("src",d[b]));break;case"progress":var f=a.settings.delay-a.settings.delay*(d[b]/100);this.$ele.data("notify-delay",f),this.$ele.find('[data-notify="progressbar"] > div').attr("aria-valuenow",d[b]).css("width",d[b]+"%");break;case"url":this.$ele.find('[data-notify="url"]').attr("href",d[b]);break;case"target":this.$ele.find('[data-notify="url"]').attr("target",d[b]);break;default:this.$ele.find('[data-notify="'+b+'"]').html(d[b])}var g=this.$ele.outerHeight()+parseInt(a.settings.spacing)+parseInt(a.settings.offset.y);a.reposition(g)},close:function(){a.close()}}},buildNotify:function(){var b=this.settings.content;this.$ele=a(String.format(this.settings.template,this.settings.type,b.title,b.message,b.url,b.target)),this.$ele.attr("data-notify-position",this.settings.placement.from+"-"+this.settings.placement.align),this.settings.allow_dismiss||this.$ele.find('[data-notify="dismiss"]').css("display","none"),(this.settings.delay<=0&&!this.settings.showProgressbar||!this.settings.showProgressbar)&&this.$ele.find('[data-notify="progressbar"]').remove()},setIcon:function(){"class"==this.settings.icon_type.toLowerCase()?this.$ele.find('[data-notify="icon"]').addClass(this.settings.content.icon):this.$ele.find('[data-notify="icon"]').is("img")?this.$ele.find('[data-notify="icon"]').attr("src",this.settings.content.icon):this.$ele.find('[data-notify="icon"]').append('<img src="'+this.settings.content.icon+'" alt="Notify Icon" />')},styleDismiss:function(){this.$ele.find('[data-notify="dismiss"]').css({position:"absolute",right:"10px",top:"5px",zIndex:this.settings.z_index+2})},styleURL:function(){this.$ele.find('[data-notify="url"]').css({backgroundImage:"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)",height:"100%",left:"0px",position:"absolute",top:"0px",width:"100%",zIndex:this.settings.z_index+1})},placement:function(){var b=this,c=this.settings.offset.y,d={display:"inline-block",margin:"0px auto",position:this.settings.position?this.settings.position:"body"===this.settings.element?"fixed":"absolute",transition:"all .5s ease-in-out",zIndex:this.settings.z_index},e=!1,f=this.settings;switch(a('[data-notify-position="'+this.settings.placement.from+"-"+this.settings.placement.align+'"]:not([data-closing="true"])').each(function(){return c=Math.max(c,parseInt(a(this).css(f.placement.from))+parseInt(a(this).outerHeight())+parseInt(f.spacing))}),1==this.settings.newest_on_top&&(c=this.settings.offset.y),d[this.settings.placement.from]=c+"px",this.settings.placement.align){case"left":case"right":d[this.settings.placement.align]=this.settings.offset.x+"px";break;case"center":d.left=0,d.right=0}this.$ele.css(d).addClass(this.settings.animate.enter),a.each(Array("webkit","moz","o","ms",""),function(a,c){b.$ele[0].style[c+"AnimationIterationCount"]=1}),a(this.settings.element).append(this.$ele),1==this.settings.newest_on_top&&(c=parseInt(c)+parseInt(this.settings.spacing)+this.$ele.outerHeight(),this.reposition(c)),a.isFunction(b.settings.onShow)&&b.settings.onShow.call(this.$ele),this.$ele.one(this.animations.start,function(a){e=!0}).one(this.animations.end,function(c){a.isFunction(b.settings.onShown)&&b.settings.onShown.call(this)}),setTimeout(function(){e||a.isFunction(b.settings.onShown)&&b.settings.onShown.call(this)},600)},bind:function(){var b=this;if(this.$ele.find('[data-notify="dismiss"]').on("click",function(){b.close()}),this.$ele.mouseover(function(b){a(this).data("data-hover","true")}).mouseout(function(b){a(this).data("data-hover","false")}),this.$ele.data("data-hover","false"),this.settings.delay>0){b.$ele.data("notify-delay",b.settings.delay);var c=setInterval(function(){var a=parseInt(b.$ele.data("notify-delay"))-b.settings.timer;if("false"===b.$ele.data("data-hover")&&"pause"==b.settings.mouse_over||"pause"!=b.settings.mouse_over){var d=(b.settings.delay-a)/b.settings.delay*100;b.$ele.data("notify-delay",a),b.$ele.find('[data-notify="progressbar"] > div').attr("aria-valuenow",d).css("width",d+"%")}a<=-b.settings.timer&&(clearInterval(c),b.close())},b.settings.timer)}},close:function(){var b=this,c=parseInt(this.$ele.css(this.settings.placement.from)),d=!1;this.$ele.data("closing","true").addClass(this.settings.animate.exit),b.reposition(c),a.isFunction(b.settings.onClose)&&b.settings.onClose.call(this.$ele),this.$ele.one(this.animations.start,function(a){d=!0}).one(this.animations.end,function(c){a(this).remove(),a.isFunction(b.settings.onClosed)&&b.settings.onClosed.call(this)}),setTimeout(function(){d||(b.$ele.remove(),b.settings.onClosed&&b.settings.onClosed(b.$ele))},600)},reposition:function(b){var c=this,d='[data-notify-position="'+this.settings.placement.from+"-"+this.settings.placement.align+'"]:not([data-closing="true"])',e=this.$ele.nextAll(d);1==this.settings.newest_on_top&&(e=this.$ele.prevAll(d)),e.each(function(){a(this).css(c.settings.placement.from,b),b=parseInt(b)+parseInt(c.settings.spacing)+a(this).outerHeight()})}}),a.notify=function(a,c){var d=new b(this,a,c);return d.notify},a.notifyDefaults=function(b){return c=a.extend(!0,{},c,b)},a.notifyClose=function(b){"undefined"==typeof b||"all"==b?a("[data-notify]").find('[data-notify="dismiss"]').trigger("click"):a('[data-notify-position="'+b+'"]').find('[data-notify="dismiss"]').trigger("click")}});
49541//== Set defaults
49542
49543$.notifyDefaults({
49544	template: '' +
49545	'<div data-notify="container" class="alert alert-{0} m-alert" role="alert">
vendor: 4,105 bytes, lines 49545-49556
49545' +
49546	'<button type="button" aria-hidden="true" class="close" data-notify="dismiss"></button>' +
49547	'<span data-notify="icon"></span>' +
49548	'<span data-notify="title">{1}</span>' +
49549	'<span data-notify="message">{2}</span>' +
49550	'<div class="progress" data-notify="progressbar">' +
49551	'<div class="progress-bar progress-bar-animated bg-{0}" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div>' +
49552	'</div>' +
49553	'<a href="{3}" target="{4}" data-notify="url"></a>' +
49554	'</div>'
49555});
49556!function(e){e(["jquery"],function(e){return function(){function t(e,t,n){return g({type:O.error,iconClass:m().iconClasses.error,message:e,optionsOverride:n,title:t})}function n(t,n){return t||(t=m()),v=e("#"+t.containerId),v.length?v:(n&&(v=d(t)),v)}function o(e,t,n){return g({type:O.info,iconClass:m().iconClasses.info,message:e,optionsOverride:n,title:t})}function s(e){C=e}function i(e,t,n){return g({type:O.success,iconClass:m().iconClasses.success,message:e,optionsOverride:n,title:t})}function a(e,t,n){return g({type:O.warning,iconClass:m().iconClasses.warning,message:e,optionsOverride:n,title:t})}function r(e,t){var o=m();v||n(o),u(e,o,t)||l(o)}function c(t){var o=m();return v||n(o),t&&0===e(":focus",t).length?void h(t):void(v.children().length&&v.remove())}function l(t){for(var n=v.children(),o=n.length-1;o>=0;o--)u(e(n[o]),t)}function u(t,n,o){var s=!(!o||!o.force)&&o.force;return!(!t||!s&&0!==e(":focus",t).length)&&(t[n.hideMethod]({duration:n.hideDuration,easing:n.hideEasing,complete:function(){h(t)}}),!0)}function d(t){return v=e("<div/>").attr("id",t.containerId).addClass(t.positionClass),v.appendTo(e(t.target)),v}function p(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:void 0,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:void 0,closeMethod:!1,closeDuration:!1,closeEasing:!1,closeOnHover:!0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",escapeHtml:!1,target:"body",closeHtml:'<button type="button">&times;</button>',closeClass:"toast-close-button",newestOnTop:!0,preventDuplicates:!1,progressBar:!1,progressClass:"toast-progress",rtl:!1}}function f(e){C&&C(e)}function g(t){function o(e){return null==e&&(e=""),e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/'/g,"&#39;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function s(){c(),u(),d(),p(),g(),C(),l(),i()}function i(){var e="";switch(t.iconClass){case"toast-success":case"toast-info":e="polite";break;default:e="assertive"}I.attr("aria-live",e)}function a(){E.closeOnHover&&I.hover(H,D),!E.onclick&&E.tapToDismiss&&I.click(b),E.closeButton&&j&&j.click(function(e){e.stopPropagation?e.stopPropagation():void 0!==e.cancelBubble&&e.cancelBubble!==!0&&(e.cancelBubble=!0),E.onCloseClick&&E.onCloseClick(e),b(!0)}),E.onclick&&I.click(function(e){E.onclick(e),b()})}function r(){I.hide(),I[E.showMethod]({duration:E.showDuration,easing:E.showEasing,complete:E.onShown}),E.timeOut>0&&(k=setTimeout(b,E.timeOut),F.maxHideTime=parseFloat(E.timeOut),F.hideEta=(new Date).getTime()+F.maxHideTime,E.progressBar&&(F.intervalId=setInterval(x,10)))}function c(){t.iconClass&&I.addClass(E.toastClass).addClass(y)}function l(){E.newestOnTop?v.prepend(I):v.append(I)}function u(){if(t.title){var e=t.title;E.escapeHtml&&(e=o(t.title)),M.append(e).addClass(E.titleClass),I.append(M)}}function d(){if(t.message){var e=t.message;E.escapeHtml&&(e=o(t.message)),B.append(e).addClass(E.messageClass),I.append(B)}}function p(){E.closeButton&&(j.addClass(E.closeClass).attr("role","button"),I.prepend(j))}function g(){E.progressBar&&(q.addClass(E.progressClass),I.prepend(q))}function C(){E.rtl&&I.addClass("rtl")}function O(e,t){if(e.preventDuplicates){if(t.message===w)return!0;w=t.message}return!1}function b(t){var n=t&&E.closeMethod!==!1?E.closeMethod:E.hideMethod,o=t&&E.closeDuration!==!1?
49556E.closeDuration:E.hideDuration,s=t&&E.closeEasing!==!1?E.closeEasing:E.hideEasing;if(!e(":focus",I).length||t)return clearTimeout(F.intervalId),I[n]({duration:o,easing:s,complete:function(){h(I),clearTimeout(k),E.onHidden&&"hidden"!==P.state&&E.onHidden(),P.state="hidden",P.endTime=new Date,f(P)}})}function D(){(E.timeOut>0||E.extendedTimeOut>0)&&(k=setTimeout(b,E.extendedTimeOut),F.maxHideTime=parseFloat(E.extendedTimeOut),F.hideEta=(new Date).getTime()+F.maxHideTime)}function H(){clearTimeout(k),F.hideEta=0,I.stop(!0,!0)[E.showMethod]({duration:E.showDuration,easing:E.showEasing})}function x(){var e=(F.hideEta-(new Date).getTime())/F.maxHideTime*100;q.width(e+"%")}var E=m(),y=t.iconClass||E.iconClass;if("undefined"!=typeof t.optionsOverride&&(E=e.extend(E,t.optionsOverride),y=t.optionsOverride.iconClass||y),!O(E,t)){T++,v=n(E,!0);var k=null,I=e("<div/>"),M=e("<div/>"),B=e("<div/>"),q=e("<div/>"),j=e(E.closeHtml),F={intervalId:null,hideEta:null,maxHideTime:null},P={toastId:T,state:"visible",startTime:new Date,options:E,map:t};return s(),r(),a(),f(P),E.debug&&console&&console.log(P),I}}function m(){return e.extend({},p(),b.options)}function h(e){v||(v=n()),e.is(":visible")||(e.remove(),e=null,0===v.children().length&&(v.remove(),w=void 0))}var v,C,w,T=0,O={error:"error",info:"info",success:"success",warning:"warning"},b={clear:r,remove:c,error:t,getContainer:n,info:o,options:{},subscribe:s,success:i,version:"2.1.4",warning:a};return b}()})}("function"==typeof define&&define.amd?define:function(e,t){"undefined"!=typeof module&&module.exports?module.exports=t(require("jquery")):window.toastr=t(window.jQuery)});
49557//# sourceMappingURL=toastr.js.map
49558
49559/*globals jQuery, define, module, exports, require, window, document, postMessage */
49560(function (factory) {
49561	"use strict";
49562	if (typeof define === 'function' && define.amd) {
49563		define(['jquery'], factory);
49564	}
49565	else if(typeof module !== 'undefined' && module.exports) {
49566		module.exports = factory(require('jquery'));
49567	}
49568	else {
49569		factory(jQuery);
49570	}
49571}(function ($, undefined) {
49572	"use strict";
49573/*!
49574 * jsTree 3.3.7
49575 * http://jstree.com/
49576 *
49577 * Copyright (c) 2014 Ivan Bozhanov (http://vakata.com)
49578 *
49579 * Licensed same as jquery - under the terms of the MIT License
49580 *   http://www.opensource.org/licenses/mit-license.php
49581 */
49582/*!
49583 * if using jslint please allow for the jQuery global and use following options:
49584 * jslint: loopfunc: true, browser: true, ass: true, bitwise: true, continue: true, nomen: true, plusplus: true, regexp: true, unparam: true, todo: true, white: true
49585 */
49586/*jshint -W083 */
49587
49588	// prevent another load? maybe there is a better way?
49589	if($.jstree) {
49590		return;
49591	}
49592
49593	/**
49594	 * ### jsTree core functionality
49595	 */
49596
49597	// internal variables
49598	var instance_counter = 0,
49599		ccp_node = false,
49600		ccp_mode = false,
49601		ccp_inst = false,
49602		themes_loaded = [],
49603		src = $('script:last').attr('src'),
49604		document = window.document; // local variable is always faster to access then a global
49605
49606	/**
49607	 * holds all jstree related functions and variables, including the actual class and methods to create, access and manipulate instances.
49608	 * @name $.jstree
49609	 */
49610	$.jstree = {
49611		/**
49612		 * specifies the jstree version in use
49613		 * @name $.jstree.version
49614		 */
49615		version : '3.3.7',
49616		/**
49617		 * holds all the default options used when creating new instances
49618		 * @name $.jstree.defaults
49619		 */
49620		defaults : {
49621			/**
49622			 * configure which plugins will be active on an instance. Should be an array of strings, where each element is a plugin name. The default is `[]`
49623			 * @name $.jstree.defaults.plugins
49624			 */
49625			plugins : []
49626		},
49627		/**
49628		 * stores all loaded jstree plugins (used internally)
49629		 * @name $.jstree.plugins
49630		 */
49631		plugins : {},
49632		path : src && src.indexOf('/') !== -1 ? src.replace(/\/[^\/]+$/,'') : '',
49633		idregex : /[\\:&!^|()\[\]<>@*'+~#";.,=\- \/${}%?`]/g,
49634		root : '#'
49635	};
49636	
49637	/**
49638	 * creates a jstree instance
49639	 * @name $.jstree.create(el [, options])
49640	 * @param {DOMElement|jQuery|String} el the element to create the instance on, can be jQuery extended or a selector
49641	 * @param {Object} options options for this instance (extends `$.jstree.defaults`)
49642	 * @return {jsTree} the new instance
49643	 */
49644	$.jstree.create = function (el, options) {
49645		var tmp = new $.jstree.core(++instance_counter),
49646			opt = options;
49647		options = $.extend(true, {}, $.jstree.defaults, options);
49648		if(opt && opt.plugins) {
49649			options.plugins = opt.plugins;
49650		}
49651		$.each(options.plugins, function (i, k) {
49652			if(i !== 'core') {
49653				tmp = tmp.plugin(k, options[k]);
49654			}
49655		});
49656		$(el).data('jstree', tmp);
49657		tmp.init(el, options);
49658		return tmp;
49659	};
49660	/**
49661	 * remove all traces of jstree from the DOM and destroy all instances
49662	 * @name $.jstree.destroy()
49663	 */
49664	$.jstree.destroy = function () {
49665		$('.jstree:jstree').jstree('destroy');
49666		$(document).off('.jstree');
49667	};
49668	/**
49669	 * the jstree class constructor, used only internally
49670	 * @private
49671	 * @name $.jstree.core(id)
49672	 * @param {Number} id this instance's index
49673	 */
49674	$.jstree.core = function (id) {
49675		this._id = id;
49676		this._cnt = 0;
49677		this._wrk = null;
49678		this._data = {
49679			core : {
49680				themes : {
49681					name : false,
49682					dots : false,
49683					icons : false,
49684					ellipsis : false
49685				},
49686				selected : [],
49687				last_error : {},
49688				working : false,
49689				worker_queue : [],
49690				focused : null
49691			}
49692		};
49693	};
49694	/**
49695	 * get a reference to an existing instance
49696	 *
49697	 * __Examples__
49698	 *
49699	 *	// provided a container with an ID of "tree", and a nested node with an ID of "branch"
49700	 *	// all of there will return the same instance
49701	 *	$.jstree.reference('tree');
49702	 *	$.jstree.reference('#tree');
vendor: 4,787 bytes, lines 49703-49826
49703	 *	$.jstree.reference($('#tree'));
49704	 *	$.jstree.reference(document.getElementByID('tree'));
49705	 *	$.jstree.reference('branch');
49706	 *	$.jstree.reference('#branch');
49707	 *	$.jstree.reference($('#branch'));
49708	 *	$.jstree.reference(document.getElementByID('branch'));
49709	 *
49710	 * @name $.jstree.reference(needle)
49711	 * @param {DOMElement|jQuery|String} needle
49712	 * @return {jsTree|null} the instance or `null` if not found
49713	 */
49714	$.jstree.reference = function (needle) {
49715		var tmp = null,
49716			obj = null;
49717		if(needle && needle.id && (!needle.tagName || !needle.nodeType)) { needle = needle.id; }
49718
49719		if(!obj || !obj.length) {
49720			try { obj = $(needle); } catch (ignore) { }
49721		}
49722		if(!obj || !obj.length) {
49723			try { obj = $('#' + needle.replace($.jstree.idregex,'\\$&')); } catch (ignore) { }
49724		}
49725		if(obj && obj.length && (obj = obj.closest('.jstree')).length && (obj = obj.data('jstree'))) {
49726			tmp = obj;
49727		}
49728		else {
49729			$('.jstree').each(function () {
49730				var inst = $(this).data('jstree');
49731				if(inst && inst._model.data[needle]) {
49732					tmp = inst;
49733					return false;
49734				}
49735			});
49736		}
49737		return tmp;
49738	};
49739	/**
49740	 * Create an instance, get an instance or invoke a command on a instance.
49741	 *
49742	 * If there is no instance associated with the current node a new one is created and `arg` is used to extend `$.jstree.defaults` for this new instance. There would be no return value (chaining is not broken).
49743	 *
49744	 * If there is an existing instance and `arg` is a string the command specified by `arg` is executed on the instance, with any additional arguments passed to the function. If the function returns a value it will be returned (chaining could break depending on function).
49745	 *
49746	 * If there is an existing instance and `arg` is not a string the instance itself is returned (similar to `$.jstree.reference`).
49747	 *
49748	 * In any other case - nothing is returned and chaining is not broken.
49749	 *
49750	 * __Examples__
49751	 *
49752	 *	$('#tree1').jstree(); // creates an instance
49753	 *	$('#tree2').jstree({ plugins : [] }); // create an instance with some options
49754	 *	$('#tree1').jstree('open_node', '#branch_1'); // call a method on an existing instance, passing additional arguments
49755	 *	$('#tree2').jstree(); // get an existing instance (or create an instance)
49756	 *	$('#tree2').jstree(true); // get an existing instance (will not create new instance)
49757	 *	$('#branch_1').jstree().select_node('#branch_1'); // get an instance (using a nested element and call a method)
49758	 *
49759	 * @name $().jstree([arg])
49760	 * @param {String|Object} arg
49761	 * @return {Mixed}
49762	 */
49763	$.fn.jstree = function (arg) {
49764		// check for string argument
49765		var is_method	= (typeof arg === 'string'),
49766			args		= Array.prototype.slice.call(arguments, 1),
49767			result		= null;
49768		if(arg === true && !this.length) { return false; }
49769		this.each(function () {
49770			// get the instance (if there is one) and method (if it exists)
49771			var instance = $.jstree.reference(this),
49772				method = is_method && instance ? instance[arg] : null;
49773			// if calling a method, and method is available - execute on the instance
49774			result = is_method && method ?
49775				method.apply(instance, args) :
49776				null;
49777			// if there is no instance and no method is being called - create one
49778			if(!instance && !is_method && (arg === undefined || $.isPlainObject(arg))) {
49779				$.jstree.create(this, arg);
49780			}
49781			// if there is an instance and no method is called - return the instance
49782			if( (instance && !is_method) || arg === true ) {
49783				result = instance || false;
49784			}
49785			// if there was a method call which returned a result - break and return the value
49786			if(result !== null && result !== undefined) {
49787				return false;
49788			}
49789		});
49790		// if there was a method call with a valid return value - return that, otherwise continue the chain
49791		return result !== null && result !== undefined ?
49792			result : this;
49793	};
49794	/**
49795	 * used to find elements containing an instance
49796	 *
49797	 * __Examples__
49798	 *
49799	 *	$('div:jstree').each(function () {
49800	 *		$(this).jstree('destroy');
49801	 *	});
49802	 *
49803	 * @name $(':jstree')
49804	 * @return {jQuery}
49805	 */
49806	$.expr.pseudos.jstree = $.expr.createPseudo(function(search) {
49807		return function(a) {
49808			return $(a).hasClass('jstree') &&
49809				$(a).data('jstree') !== undefined;
49810		};
49811	});
49812
49813	/**
49814	 * stores all defaults for the core
49815	 * @name $.jstree.defaults.core
49816	 */
49817	$.jstree.defaults.core = {
49818		/**
49819		 * data configuration
49820		 *
49821		 * If left as `false` the HTML inside the jstree container element is used to populate the tree (that should be an unordered list with list items).
49822		 *
49823		 * You can also pass in a HTML string or a JSON array here.
49824		 *
49825		 * It is possible to pass in a standard jQuery-like AJAX config and jstree will automatically determine if the response is JSON or HTML and use that to populate the tree.
49826		 * In addition to the standard jQuery ajax options here you can supp
vendor: 6,170 bytes, lines 49826-50006
49826y functions for `data` and `url`, the functions will be run in the current instance's scope and a param will be passed indicating which node is being loaded, the return value of those functions will be used.
49827		 *
49828		 * The last option is to specify a function, that function will receive the node being loaded as argument and a second param which is a function which should be called with the result.
49829		 *
49830		 * __Examples__
49831		 *
49832		 *	// AJAX
49833		 *	$('#tree').jstree({
49834		 *		'core' : {
49835		 *			'data' : {
49836		 *				'url' : '/get/children/',
49837		 *				'data' : function (node) {
49838		 *					return { 'id' : node.id };
49839		 *				}
49840		 *			}
49841		 *		});
49842		 *
49843		 *	// direct data
49844		 *	$('#tree').jstree({
49845		 *		'core' : {
49846		 *			'data' : [
49847		 *				'Simple root node',
49848		 *				{
49849		 *					'id' : 'node_2',
49850		 *					'text' : 'Root node with options',
49851		 *					'state' : { 'opened' : true, 'selected' : true },
49852		 *					'children' : [ { 'text' : 'Child 1' }, 'Child 2']
49853		 *				}
49854		 *			]
49855		 *		}
49856		 *	});
49857		 *
49858		 *	// function
49859		 *	$('#tree').jstree({
49860		 *		'core' : {
49861		 *			'data' : function (obj, callback) {
49862		 *				callback.call(this, ['Root 1', 'Root 2']);
49863		 *			}
49864		 *		});
49865		 *
49866		 * @name $.jstree.defaults.core.data
49867		 */
49868		data			: false,
49869		/**
49870		 * configure the various strings used throughout the tree
49871		 *
49872		 * You can use an object where the key is the string you need to replace and the value is your replacement.
49873		 * Another option is to specify a function which will be called with an argument of the needed string and should return the replacement.
49874		 * If left as `false` no replacement is made.
49875		 *
49876		 * __Examples__
49877		 *
49878		 *	$('#tree').jstree({
49879		 *		'core' : {
49880		 *			'strings' : {
49881		 *				'Loading ...' : 'Please wait ...'
49882		 *			}
49883		 *		}
49884		 *	});
49885		 *
49886		 * @name $.jstree.defaults.core.strings
49887		 */
49888		strings			: false,
49889		/**
49890		 * determines what happens when a user tries to modify the structure of the tree
49891		 * If left as `false` all operations like create, rename, delete, move or copy are prevented.
49892		 * You can set this to `true` to allow all interactions or use a function to have better control.
49893		 *
49894		 * __Examples__
49895		 *
49896		 *	$('#tree').jstree({
49897		 *		'core' : {
49898		 *			'check_callback' : function (operation, node, node_parent, node_position, more) {
49899		 *				// operation can be 'create_node', 'rename_node', 'delete_node', 'move_node', 'copy_node' or 'edit'
49900		 *				// in case of 'rename_node' node_position is filled with the new node name
49901		 *				return operation === 'rename_node' ? true : false;
49902		 *			}
49903		 *		}
49904		 *	});
49905		 *
49906		 * @name $.jstree.defaults.core.check_callback
49907		 */
49908		check_callback	: false,
49909		/**
49910		 * a callback called with a single object parameter in the instance's scope when something goes wrong (operation prevented, ajax failed, etc)
49911		 * @name $.jstree.defaults.core.error
49912		 */
49913		error			: $.noop,
49914		/**
49915		 * the open / close animation duration in milliseconds - set this to `false` to disable the animation (default is `200`)
49916		 * @name $.jstree.defaults.core.animation
49917		 */
49918		animation		: 200,
49919		/**
49920		 * a boolean indicating if multiple nodes can be selected
49921		 * @name $.jstree.defaults.core.multiple
49922		 */
49923		multiple		: true,
49924		/**
49925		 * theme configuration object
49926		 * @name $.jstree.defaults.core.themes
49927		 */
49928		themes			: {
49929			/**
49930			 * the name of the theme to use (if left as `false` the default theme is used)
49931			 * @name $.jstree.defaults.core.themes.name
49932			 */
49933			name			: false,
49934			/**
49935			 * the URL of the theme's CSS file, leave this as `false` if you have manually included the theme CSS (recommended). You can set this to `true` too which will try to autoload the theme.
49936			 * @name $.jstree.defaults.core.themes.url
49937			 */
49938			url				: false,
49939			/**
49940			 * the location of all jstree themes - only used if `url` is set to `true`
49941			 * @name $.jstree.defaults.core.themes.dir
49942			 */
49943			dir				: false,
49944			/**
49945			 * a boolean indicating if connecting dots are shown
49946			 * @name $.jstree.defaults.core.themes.dots
49947			 */
49948			dots			: true,
49949			/**
49950			 * a boolean indicating if node icons are shown
49951			 * @name $.jstree.defaults.core.themes.icons
49952			 */
49953			icons			: true,
49954			/**
49955			 * a boolean indicating if node ellipsis should be shown - this only works with a fixed with on the container
49956			 * @name $.jstree.defaults.core.themes.ellipsis
49957			 */
49958			ellipsis		: false,
49959			/**
49960			 * a boolean indicating if the tree background is striped
49961			 * @name $.jstree.defaults.core.themes.stripes
49962			 */
49963			stripes			: false,
49964			/**
49965			 * a string (or boolean `false`) specifying the theme variant to use (if the theme supports variants)
49966			 * @name $.jstree.defaults.core.themes.variant
49967			 */
49968			variant			: false,
49969			/**
49970			 * a boolean specifying if a reponsive version of the theme should kick in on smaller screens (if the theme supports it). Defaults to `false`.
49971			 * @name $.jstree.defaults.core.themes.responsive
49972			 */
49973			responsive		: false
49974		},
49975		/**
49976		 * if left as `true` all parents of all selected nodes will be opened once the tree loads (so that all selected nodes are visible to the user)
49977		 * @name $.jstree.defaults.core.expand_selected_onload
49978		 */
49979		expand_selected_onload : true,
49980		/**
49981		 * if left as `true` web workers will be used to parse incoming JSON data where possible, so that the UI will not be blocked by large requests. Workers are however about 30% slower. Defaults to `true`
49982		 * @name $.jstree.defaults.core.worker
49983		 */
49984		worker : true,
49985		/**
49986		 * Force node text to plain text (and escape HTML). Defaults to `false`
49987		 * @name $.jstree.defaults.core.force_text
49988		 */
49989		force_text : false,
49990		/**
49991		 * Should the node be toggled if the text is double clicked. Defaults to `true`
49992		 * @name $.jstree.defaults.core.dblclick_toggle
49993		 */
49994		dblclick_toggle : true,
49995		/**
49996		 * Should the loaded nodes be part of the state. Defaults to `false`
49997		 * @name $.jstree.defaults.core.loaded_state
49998		 */
49999		loaded_state : false,
50000		/**
50001		 * Should the last active node be focused when the tree container is blurred and the focused again. This helps working with screen readers. Defaults to `true`
50002		 * @name $.jstree.defaults.core.restore_focus
50003		 */
50004		restore_focus : true,
50005		/**
50006		 * 
vendor: 13,228 bytes, lines 50006-50385
50006Default keyboard shortcuts (an object where each key is the button name or combo - like 'enter', 'ctrl-space', 'p', etc and the value is the function to execute in the instance's scope)
50007		 * @name $.jstree.defaults.core.keyboard
50008		 */
50009		keyboard : {
50010			'ctrl-space': function (e) {
50011				// aria defines space only with Ctrl
50012				e.type = "click";
50013				$(e.currentTarget).trigger(e);
50014			},
50015			'enter': function (e) {
50016				// enter
50017				e.type = "click";
50018				$(e.currentTarget).trigger(e);
50019			},
50020			'left': function (e) {
50021				// left
50022				e.preventDefault();
50023				if(this.is_open(e.currentTarget)) {
50024					this.close_node(e.currentTarget);
50025				}
50026				else {
50027					var o = this.get_parent(e.currentTarget);
50028					if(o && o.id !== $.jstree.root) { this.get_node(o, true).children('.jstree-anchor').focus(); }
50029				}
50030			},
50031			'up': function (e) {
50032				// up
50033				e.preventDefault();
50034				var o = this.get_prev_dom(e.currentTarget);
50035				if(o && o.length) { o.children('.jstree-anchor').focus(); }
50036			},
50037			'right': function (e) {
50038				// right
50039				e.preventDefault();
50040				if(this.is_closed(e.currentTarget)) {
50041					this.open_node(e.currentTarget, function (o) { this.get_node(o, true).children('.jstree-anchor').focus(); });
50042				}
50043				else if (this.is_open(e.currentTarget)) {
50044					var o = this.get_node(e.currentTarget, true).children('.jstree-children')[0];
50045					if(o) { $(this._firstChild(o)).children('.jstree-anchor').focus(); }
50046				}
50047			},
50048			'down': function (e) {
50049				// down
50050				e.preventDefault();
50051				var o = this.get_next_dom(e.currentTarget);
50052				if(o && o.length) { o.children('.jstree-anchor').focus(); }
50053			},
50054			'*': function (e) {
50055				// aria defines * on numpad as open_all - not very common
50056				this.open_all();
50057			},
50058			'home': function (e) {
50059				// home
50060				e.preventDefault();
50061				var o = this._firstChild(this.get_container_ul()[0]);
50062				if(o) { $(o).children('.jstree-anchor').filter(':visible').focus(); }
50063			},
50064			'end': function (e) {
50065				// end
50066				e.preventDefault();
50067				this.element.find('.jstree-anchor').filter(':visible').last().focus();
50068			},
50069			'f2': function (e) {
50070				// f2 - safe to include - if check_callback is false it will fail
50071				e.preventDefault();
50072				this.edit(e.currentTarget);
50073			}
50074		}
50075	};
50076	$.jstree.core.prototype = {
50077		/**
50078		 * used to decorate an instance with a plugin. Used internally.
50079		 * @private
50080		 * @name plugin(deco [, opts])
50081		 * @param  {String} deco the plugin to decorate with
50082		 * @param  {Object} opts options for the plugin
50083		 * @return {jsTree}
50084		 */
50085		plugin : function (deco, opts) {
50086			var Child = $.jstree.plugins[deco];
50087			if(Child) {
50088				this._data[deco] = {};
50089				Child.prototype = this;
50090				return new Child(opts, this);
50091			}
50092			return this;
50093		},
50094		/**
50095		 * initialize the instance. Used internally.
50096		 * @private
50097		 * @name init(el, optons)
50098		 * @param {DOMElement|jQuery|String} el the element we are transforming
50099		 * @param {Object} options options for this instance
50100		 * @trigger init.jstree, loading.jstree, loaded.jstree, ready.jstree, changed.jstree
50101		 */
50102		init : function (el, options) {
50103			this._model = {
50104				data : {},
50105				changed : [],
50106				force_full_redraw : false,
50107				redraw_timeout : false,
50108				default_state : {
50109					loaded : true,
50110					opened : false,
50111					selected : false,
50112					disabled : false
50113				}
50114			};
50115			this._model.data[$.jstree.root] = {
50116				id : $.jstree.root,
50117				parent : null,
50118				parents : [],
50119				children : [],
50120				children_d : [],
50121				state : { loaded : false }
50122			};
50123
50124			this.element = $(el).addClass('jstree jstree-' + this._id);
50125			this.settings = options;
50126
50127			this._data.core.ready = false;
50128			this._data.core.loaded = false;
50129			this._data.core.rtl = (this.element.css("direction") === "rtl");
50130			this.element[this._data.core.rtl ? 'addClass' : 'removeClass']("jstree-rtl");
50131			this.element.attr('role','tree');
50132			if(this.settings.core.multiple) {
50133				this.element.attr('aria-multiselectable', true);
50134			}
50135			if(!this.element.attr('tabindex')) {
50136				this.element.attr('tabindex','0');
50137			}
50138
50139			this.bind();
50140			/**
50141			 * triggered after all events are bound
50142			 * @event
50143			 * @name init.jstree
50144			 */
50145			this.trigger("init");
50146
50147			this._data.core.original_container_html = this.element.find(" > ul > li").clone(true);
50148			this._data.core.original_container_html
50149				.find("li").addBack()
50150				.contents().filter(function() {
50151					return this.nodeType === 3 && (!this.nodeValue || /^\s+$/.test(this.nodeValue));
50152				})
50153				.remove();
50154			this.element.html("<"+"ul class='jstree-container-ul jstree-children' role='group'><"+"li id='j"+this._id+"_loading' class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='tree-item'><i class='jstree-icon jstree-ocl'></i><"+"a class='jstree-anchor' href='#'><i class='jstree-icon jstree-themeicon-hidden'></i>" + this.get_string("Loading ...") + "</a></li></ul>");
50155			this.element.attr('aria-activedescendant','j' + this._id + '_loading');
50156			this._data.core.li_height = this.get_container_ul().children("li").first().outerHeight() || 24;
50157			this._data.core.node = this._create_prototype_node();
50158			/**
50159			 * triggered after the loading text is shown and before loading starts
50160			 * @event
50161			 * @name loading.jstree
50162			 */
50163			this.trigger("loading");
50164			this.load_node($.jstree.root);
50165		},
50166		/**
50167		 * destroy an instance
50168		 * @name destroy()
50169		 * @param  {Boolean} keep_html if not set to `true` the container will be emptied, otherwise the current DOM elements will be kept intact
50170		 */
50171		destroy : function (keep_html) {
50172			/**
50173			 * triggered before the tree is destroyed
50174			 * @event
50175			 * @name destroy.jstree
50176			 */
50177			this.trigger("destroy");
50178			if(this._wrk) {
50179				try {
50180					window.URL.revokeObjectURL(this._wrk);
50181					this._wrk = null;
50182				}
50183				catch (ignore) { }
50184			}
50185			if(!keep_html) { this.element.empty(); }
50186			this.teardown();
50187		},
50188		/**
50189		 * Create a prototype node
50190		 * @name _create_prototype_node()
50191		 * @return {DOMElement}
50192		 */
50193		_create_prototype_node : function () {
50194			var _node = document.createElement('LI'), _temp1, _temp2;
50195			_node.setAttribute('role', 'treeitem');
50196			_temp1 = document.createElement('I');
50197			_temp1.className = 'jstree-icon jstree-ocl';
50198			_temp1.setAttribute('role', 'presentation');
50199			_node.appendChild(_temp1);
50200			_temp1 = document.createElement('A');
50201			_temp1.className = 'jstree-anchor';
50202			_temp1.setAttribute('href','#');
50203			_temp1.setAttribute('tabindex','-1');
50204			_temp2 = document.createElement('I');
50205			_temp2.className = 'jstree-icon jstree-themeicon';
50206			_temp2.setAttribute('role', 'presentation');
50207			_temp1.appendChild(_temp2);
50208			_node.appendChild(_temp1);
50209			_temp1 = _temp2 = null;
50210
50211			return _node;
50212		},
50213		_kbevent_to_func : function (e) {
50214			var keys = {
50215				8: "Backspace", 9: "Tab", 13: "Return", 19: "Pause", 27: "Esc",
50216				32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", 36: "Home",
50217				37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "Print", 45: "Insert",
50218				46: "Delete", 96: "Numpad0", 97: "Numpad1", 98: "Numpad2", 99 : "Numpad3",
50219				100: "Numpad4", 101: "Numpad5", 102: "Numpad6", 103: "Numpad7",
50220				104: "Numpad8", 105: "Numpad9", '-13': "NumpadEnter", 112: "F1",
50221				113: "F2", 114: "F3", 115: "F4", 116: "F5", 117: "F6", 118: "F7",
50222				119: "F8", 120: "F9", 121: "F10", 122: "F11", 123: "F12", 144: "Numlock",
50223				145: "Scrolllock", 16: 'Shift', 17: 'Ctrl', 18: 'Alt',
50224				48: '0',  49: '1',  50: '2',  51: '3',  52: '4', 53:  '5',
50225				54: '6',  55: '7',  56: '8',  57: '9',  59: ';',  61: '=', 65:  'a',
50226				66: 'b',  67: 'c',  68: 'd',  69: 'e',  70: 'f',  71: 'g', 72:  'h',
50227				73: 'i',  74: 'j',  75: 'k',  76: 'l',  77: 'm',  78: 'n', 79:  'o',
50228				80: 'p',  81: 'q',  82: 'r',  83: 's',  84: 't',  85: 'u', 86:  'v',
50229				87: 'w',  88: 'x',  89: 'y',  90: 'z', 107: '+', 109: '-', 110: '.',
50230				186: ';', 187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`',
50231				219: '[', 220: '\\',221: ']', 222: "'", 111: '/', 106: '*', 173: '-'
50232			};
50233			var parts = [];
50234			if (e.ctrlKey) { parts.push('ctrl'); }
50235			if (e.altKey) { parts.push('alt'); }
50236			if (e.shiftKey) { parts.push('shift'); }
50237			parts.push(keys[e.which] || e.which);
50238			parts = parts.sort().join('-').toLowerCase();
50239
50240			var kb = this.settings.core.keyboard, i, tmp;
50241			for (i in kb) {
50242				if (kb.hasOwnProperty(i)) {
50243					tmp = i;
50244					if (tmp !== '-' && tmp !== '+') {
50245						tmp = tmp.replace('--', '-MINUS').replace('+-', '-MINUS').replace('++', '-PLUS').replace('-+', '-PLUS');
50246						tmp = tmp.split(/-|\+/).sort().join('-').replace('MINUS', '-').replace('PLUS', '+').toLowerCase();
50247					}
50248					if (tmp === parts) {
50249						return kb[i];
50250					}
50251				}
50252			}
50253			return null;
50254		},
50255		/**
50256		 * part of the destroying of an instance. Used internally.
50257		 * @private
50258		 * @name teardown()
50259		 */
50260		teardown : function () {
50261			this.unbind();
50262			this.element
50263				.removeClass('jstree')
50264				.removeData('jstree')
50265				.find("[class^='jstree']")
50266					.addBack()
50267					.attr("class", function () { return this.className.replace(/jstree[^ ]*|$/ig,''); });
50268			this.element = null;
50269		},
50270		/**
50271		 * bind all events. Used internally.
50272		 * @private
50273		 * @name bind()
50274		 */
50275		bind : function () {
50276			var word = '',
50277				tout = null,
50278				was_click = 0;
50279			this.element
50280				.on("dblclick.jstree", function (e) {
50281						if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; }
50282						if(document.selection && document.selection.empty) {
50283							document.selection.empty();
50284						}
50285						else {
50286							if(window.getSelection) {
50287								var sel = window.getSelection();
50288								try {
50289									sel.removeAllRanges();
50290									sel.collapse();
50291								} catch (ignore) { }
50292							}
50293						}
50294					})
50295				.on("mousedown.jstree", $.proxy(function (e) {
50296						if(e.target === this.element[0]) {
50297							e.preventDefault(); // prevent losing focus when clicking scroll arrows (FF, Chrome)
50298							was_click = +(new Date()); // ie does not allow to prevent losing focus
50299						}
50300					}, this))
50301				.on("mousedown.jstree", ".jstree-ocl", function (e) {
50302						e.preventDefault(); // prevent any node inside from losing focus when clicking the open/close icon
50303					})
50304				.on("click.jstree", ".jstree-ocl", $.proxy(function (e) {
50305						this.toggle_node(e.target);
50306					}, this))
50307				.on("dblclick.jstree", ".jstree-anchor", $.proxy(function (e) {
50308						if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; }
50309						if(this.settings.core.dblclick_toggle) {
50310							this.toggle_node(e.target);
50311						}
50312					}, this))
50313				.on("click.jstree", ".jstree-anchor", $.proxy(function (e) {
50314						e.preventDefault();
50315						if(e.currentTarget !== document.activeElement) { $(e.currentTarget).focus(); }
50316						this.activate_node(e.currentTarget, e);
50317					}, this))
50318				.on('keydown.jstree', '.jstree-anchor', $.proxy(function (e) {
50319						if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; }
50320						if(this._data.core.rtl) {
50321							if(e.which === 37) { e.which = 39; }
50322							else if(e.which === 39) { e.which = 37; }
50323						}
50324						var f = this._kbevent_to_func(e);
50325						if (f) {
50326							var r = f.call(this, e);
50327							if (r === false || r === true) {
50328								return r;
50329							}
50330						}
50331					}, this))
50332				.on("load_node.jstree", $.proxy(function (e, data) {
50333						if(data.status) {
50334							if(data.node.id === $.jstree.root && !this._data.core.loaded) {
50335								this._data.core.loaded = true;
50336								if(this._firstChild(this.get_container_ul()[0])) {
50337									this.element.attr('aria-activedescendant',this._firstChild(this.get_container_ul()[0]).id);
50338								}
50339								/**
50340								 * triggered after the root node is loaded for the first time
50341								 * @event
50342								 * @name loaded.jstree
50343								 */
50344								this.trigger("loaded");
50345							}
50346							if(!this._data.core.ready) {
50347								setTimeout($.proxy(function() {
50348									if(this.element && !this.get_container_ul().find('.jstree-loading').length) {
50349										this._data.core.ready = true;
50350										if(this._data.core.selected.length) {
50351											if(this.settings.core.expand_selected_onload) {
50352												var tmp = [], i, j;
50353												for(i = 0, j = this._data.core.selected.length; i < j; i++) {
50354													tmp = tmp.concat(this._model.data[this._data.core.selected[i]].parents);
50355												}
50356												tmp = $.vakata.array_unique(tmp);
50357												for(i = 0, j = tmp.length; i < j; i++) {
50358													this.open_node(tmp[i], false, 0);
50359												}
50360											}
50361											this.trigger('changed', { 'action' : 'ready', 'selected' : this._data.core.selected });
50362										}
50363										/**
50364										 * triggered after all nodes are finished loading
50365										 * @event
50366										 * @name ready.jstree
50367										 */
50368										this.trigger("ready");
50369									}
50370								}, this), 0);
50371							}
50372						}
50373					}, this))
50374				// quick searching when the tree is focused
50375				.on('keypress.jstree', $.proxy(function (e) {
50376						if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; }
50377						if(tout) { clearTimeout(tout); }
50378						tout = setTimeout(function () {
50379							word = '';
50380						}, 500);
50381
50382						var chr = String.fromCharCode(e.which).toLowerCase(),
50383							col = this.element.find('.jstree-anchor').filter(':visible'),
50384							ind = col.index(document.activeElement) || 0,
50385							end = false;
50386						word += chr;
50387
50388						// match for whole word from current node down (including the current node)
50389						if(word.length > 1) {
50390							col.slice(ind).each($.proxy(function (i, v) {
50391								if($(v).text().toLowerCase().indexOf(word) === 0) {
50392									$(v).focus();
50393									end = true;
50394									return false;
50395								}
50396							}, this));
50397							if(end) { return; }
50398
50399							// match for whole word from the beginning of the tree
50400							col.slice(0, ind).each($.proxy(function (i, v) {
50401								if($(v).text().toLowerCase().indexOf(word) === 0) {
50402									$(v).focus();
50403									end = true;
50404									return false;
50405								}
50406							}, this));
50407							if(end) { return; }
50408						}
50409						// list nodes that start with that letter (only if word consists of a single char)
50410						if(new RegExp('^' + chr.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '+$').test(word)) {
50411							// search for the next node starting with that letter
50412							col.slice(ind + 1).each($.proxy(function (i, v) {
50413								if($(v).text().toLowerCase().charAt(0) === chr) {
50414									$(v).focus();
50415									end = true;
50416									return false;
50417								}
50418							}, this));
50419							if(end) { return; }
50420
50421							// search from the beginning
50422							col.slice(0, ind + 1).each($.proxy(function (i, v) {
50423								if($(v).text().toLowerCase().charAt(0) === chr) {
50424									$(v).focus();
50425									end = true;
50426									return false;
50427								}
50428							}, this));
50429							if(end) { return; }
50430						}
50431					}, this))
50432				// THEME RELATED
50433				.on("init.jstree", $.proxy(function () {
50434						var s = this.settings.core.themes;
50435						this._data.core.themes.dots			= s.dots;
50436						this._data.core.themes.stripes		= s.stripes;
50437						this._data.core.themes.icons		= s.icons;
50438						this._data.core.themes.ellipsis		= s.ellipsis;
50439						this.set_theme(s.name || "default", s.url);
50440						this.set_theme_variant(s.variant);
50441					}, this))
50442				.on("loading.jstree", $.proxy(function () {
50443						this[ this._data.core.themes.dots ? "show_dots" : "hide_dots" ]();
50444						this[ this._data.core.themes.icons ? "show_icons" : "hide_icons" ]();
50445						this[ this._data.core.themes.stripes ? "show_stripes" : "hide_stripes" ]();
50446						this[ this._data.core.themes.ellipsis ? "show_ellipsis" : "hide_ellipsis" ]();
50447					}, this))
50448				.on('blur.jstree', '.jstree-anchor', $.proxy(function (e) {
50449						this._data.core.focused = null;
50450						$(e.currentTarget).filter('.jstree-hovered').mouseleave();
50451						this.element.attr('tabindex', '0');
50452					}, this))
50453				.on('focus.jstree', '.jstree-anchor', $.proxy(function (e) {
50454						var tmp = this.get_node(e.currentTarget);
50455						if(tmp && tmp.id) {
50456							this._data.core.focused = tmp.id;
50457						}
50458						this.element.find('.jstree-hovered').not(e.currentTarget).mouseleave();
50459						$(e.currentTarget).mouseenter();
50460						this.element.attr('tabindex', '-1');
50461					}, this))
50462				.on('focus.jstree', $.proxy(function () {
50463						if(+(new Date()) - was_click > 500 && !this._data.core.focused && this.settings.core.restore_focus) {
50464							was_click = 0;
50465							var act = this.get_node(this.element.attr('aria-activedescendant'), true);
50466							if(act) {
50467								act.find('> .jstree-anchor').focus();
50468							}
50469						}
50470					}, this))
50471				.on('mouseenter.jstree', '.jstree-anchor', $.proxy(function (e) {
50472						this.hover_node(e.currentTarget);
50473					}, this))
50474				.on('mouseleave.jstree', '.jstree-anchor', $.proxy(function (e) {
50475						this.dehover_node(e.currentTarget);
50476					}, this));
50477		},
50478		/**
50479		 * part of the destroying of an instance. Used internally.
50480		 * @private
50481		 * @name unbind()
50482		 */
50483		unbind : function () {
50484			this.element.off('.jstree');
50485			$(document).off('.jstree-' + this._id);
50486		},
50487		/**
50488		 * trigger an event. Used internally.
50489		 * @private
50490		 * @name trigger(ev [, data])
50491		 * @param  {String} ev the name of the event to trigger
50492		 * @param  {Object} data additional data to pass with the event
50493		 */
50494		trigger : function (ev, data) {
50495			if(!data) {
50496				data = {};
50497			}
50498			data.instance = this;
50499			this.element.triggerHandler(ev.replace('.jstree','') + '.jstree', data);
50500		},
50501		/**
50502		 * returns the jQuery extended instance container
50503		 * @name get_container()
50504		 * @return {jQuery}
50505		 */
50506		get_container : function () {
50507			return this.element;
50508		},
50509		/**
50510		 * returns the jQuery extended main UL node inside the instance container. Used internally.
50511		 * @private
50512		 * @name get_container_ul()
50513		 * @return {jQuery}
50514		 */
50515		get_container_ul : function () {
50516			return this.element.children(".jstree-children").first();
50517		},
50518		/**
50519		 * gets string replacements (localization). Used internally.
50520		 * @private
50521		 * @name get_string(key)
50522		 * @param  {String} key
50523		 * @return {String}
50524		 */
50525		get_string : function (key) {
50526			var a = this.settings.core.strings;
50527			if($.isFunction(a)) { return a.call(this, key); }
50528			if(a && a[key]) { return a[key]; }
50529			return key;
50530		},
50531		/**
50532		 * gets the first child of a DOM node. Used internally.
50533		 * @private
50534		 * @name _firstChild(dom)
50535		 * @param  {DOMElement} dom
50536		 * @return {DOMElement}
50537		 */
50538		_firstChild : function (dom) {
50539			dom = dom ? dom.firstChild : null;
50540			while(dom !== null && dom.nodeType !== 1) {
50541				dom = dom.nextSibling;
50542			}
50543			return dom;
50544		},
50545		/**
50546		 * gets the next sibling of a DOM node. Used internally.
50547		 * @private
50548		 * @name _nextSibling(dom)
50549		 * @param  {DOMElement} dom
50550		 * @return {DOMElement}
50551		 */
50552		_nextSibling : function (dom) {
50553			dom = dom ? dom.nextSibling : null;
50554			while(dom !== null && dom.nodeType !== 1) {
50555				dom = dom.nextSibling;
50556			}
50557			return dom;
50558		},
50559		/**
50560		 * gets the previous sibling of a DOM node. Used internally.
50561		 * @private
50562		 * @name _previousSibling(dom)
50563		 * @param  {DOMElement} dom
50564		 * @return {DOMElement}
50565		 */
50566		_previousSibling : function (dom) {
50567			dom = dom ? dom.previousSibling : null;
50568			while(dom !== null && dom.nodeType !== 1) {
50569				dom = dom.previousSibling;
50570			}
50571			return dom;
50572		},
50573		/**
50574		 * get the JSON representation of a node (or the actual jQuery extended DOM node) by using any input (child DOM element, ID string, selector, etc)
50575		 * @name get_node(obj [, as_dom])
50576		 * @param  {mixed} obj
50577		 * @param  {Boolean} as_dom
50578		 * @return {Object|jQuery}
50579		 */
50580		get_node : function (obj, as_dom) {
50581			if(obj && obj.id) {
50582				obj = obj.id;
50583			}
50584			if (obj instanceof jQuery
vendor: 7,159 bytes, lines 50584-50818
50584 && obj.length && obj[0].id) {
50585				obj = obj[0].id;
50586			}
50587			var dom;
50588			try {
50589				if(this._model.data[obj]) {
50590					obj = this._model.data[obj];
50591				}
50592				else if(typeof obj === "string" && this._model.data[obj.replace(/^#/, '')]) {
50593					obj = this._model.data[obj.replace(/^#/, '')];
50594				}
50595				else if(typeof obj === "string" && (dom = $('#' + obj.replace($.jstree.idregex,'\\$&'), this.element)).length && this._model.data[dom.closest('.jstree-node').attr('id')]) {
50596					obj = this._model.data[dom.closest('.jstree-node').attr('id')];
50597				}
50598				else if((dom = this.element.find(obj)).length && this._model.data[dom.closest('.jstree-node').attr('id')]) {
50599					obj = this._model.data[dom.closest('.jstree-node').attr('id')];
50600				}
50601				else if((dom = this.element.find(obj)).length && dom.hasClass('jstree')) {
50602					obj = this._model.data[$.jstree.root];
50603				}
50604				else {
50605					return false;
50606				}
50607
50608				if(as_dom) {
50609					obj = obj.id === $.jstree.root ? this.element : $('#' + obj.id.replace($.jstree.idregex,'\\$&'), this.element);
50610				}
50611				return obj;
50612			} catch (ex) { return false; }
50613		},
50614		/**
50615		 * get the path to a node, either consisting of node texts, or of node IDs, optionally glued together (otherwise an array)
50616		 * @name get_path(obj [, glue, ids])
50617		 * @param  {mixed} obj the node
50618		 * @param  {String} glue if you want the path as a string - pass the glue here (for example '/'), if a falsy value is supplied here, an array is returned
50619		 * @param  {Boolean} ids if set to true build the path using ID, otherwise node text is used
50620		 * @return {mixed}
50621		 */
50622		get_path : function (obj, glue, ids) {
50623			obj = obj.parents ? obj : this.get_node(obj);
50624			if(!obj || obj.id === $.jstree.root || !obj.parents) {
50625				return false;
50626			}
50627			var i, j, p = [];
50628			p.push(ids ? obj.id : obj.text);
50629			for(i = 0, j = obj.parents.length; i < j; i++) {
50630				p.push(ids ? obj.parents[i] : this.get_text(obj.parents[i]));
50631			}
50632			p = p.reverse().slice(1);
50633			return glue ? p.join(glue) : p;
50634		},
50635		/**
50636		 * get the next visible node that is below the `obj` node. If `strict` is set to `true` only sibling nodes are returned.
50637		 * @name get_next_dom(obj [, strict])
50638		 * @param  {mixed} obj
50639		 * @param  {Boolean} strict
50640		 * @return {jQuery}
50641		 */
50642		get_next_dom : function (obj, strict) {
50643			var tmp;
50644			obj = this.get_node(obj, true);
50645			if(obj[0] === this.element[0]) {
50646				tmp = this._firstChild(this.get_container_ul()[0]);
50647				while (tmp && tmp.offsetHeight === 0) {
50648					tmp = this._nextSibling(tmp);
50649				}
50650				return tmp ? $(tmp) : false;
50651			}
50652			if(!obj || !obj.length) {
50653				return false;
50654			}
50655			if(strict) {
50656				tmp = obj[0];
50657				do {
50658					tmp = this._nextSibling(tmp);
50659				} while (tmp && tmp.offsetHeight === 0);
50660				return tmp ? $(tmp) : false;
50661			}
50662			if(obj.hasClass("jstree-open")) {
50663				tmp = this._firstChild(obj.children('.jstree-children')[0]);
50664				while (tmp && tmp.offsetHeight === 0) {
50665					tmp = this._nextSibling(tmp);
50666				}
50667				if(tmp !== null) {
50668					return $(tmp);
50669				}
50670			}
50671			tmp = obj[0];
50672			do {
50673				tmp = this._nextSibling(tmp);
50674			} while (tmp && tmp.offsetHeight === 0);
50675			if(tmp !== null) {
50676				return $(tmp);
50677			}
50678			return obj.parentsUntil(".jstree",".jstree-node").nextAll(".jstree-node:visible").first();
50679		},
50680		/**
50681		 * get the previous visible node that is above the `obj` node. If `strict` is set to `true` only sibling nodes are returned.
50682		 * @name get_prev_dom(obj [, strict])
50683		 * @param  {mixed} obj
50684		 * @param  {Boolean} strict
50685		 * @return {jQuery}
50686		 */
50687		get_prev_dom : function (obj, strict) {
50688			var tmp;
50689			obj = this.get_node(obj, true);
50690			if(obj[0] === this.element[0]) {
50691				tmp = this.get_container_ul()[0].lastChild;
50692				while (tmp && tmp.offsetHeight === 0) {
50693					tmp = this._previousSibling(tmp);
50694				}
50695				return tmp ? $(tmp) : false;
50696			}
50697			if(!obj || !obj.length) {
50698				return false;
50699			}
50700			if(strict) {
50701				tmp = obj[0];
50702				do {
50703					tmp = this._previousSibling(tmp);
50704				} while (tmp && tmp.offsetHeight === 0);
50705				return tmp ? $(tmp) : false;
50706			}
50707			tmp = obj[0];
50708			do {
50709				tmp = this._previousSibling(tmp);
50710			} while (tmp && tmp.offsetHeight === 0);
50711			if(tmp !== null) {
50712				obj = $(tmp);
50713				while(obj.hasClass("jstree-open")) {
50714					obj = obj.children(".jstree-children").first().children(".jstree-node:visible:last");
50715				}
50716				return obj;
50717			}
50718			tmp = obj[0].parentNode.parentNode;
50719			return tmp && tmp.className && tmp.className.indexOf('jstree-node') !== -1 ? $(tmp) : false;
50720		},
50721		/**
50722		 * get the parent ID of a node
50723		 * @name get_parent(obj)
50724		 * @param  {mixed} obj
50725		 * @return {String}
50726		 */
50727		get_parent : function (obj) {
50728			obj = this.get_node(obj);
50729			if(!obj || obj.id === $.jstree.root) {
50730				return false;
50731			}
50732			return obj.parent;
50733		},
50734		/**
50735		 * get a jQuery collection of all the children of a node (node must be rendered), returns false on error
50736		 * @name get_children_dom(obj)
50737		 * @param  {mixed} obj
50738		 * @return {jQuery}
50739		 */
50740		get_children_dom : function (obj) {
50741			obj = this.get_node(obj, true);
50742			if(obj[0] === this.element[0]) {
50743				return this.get_container_ul().children(".jstree-node");
50744			}
50745			if(!obj || !obj.length) {
50746				return false;
50747			}
50748			return obj.children(".jstree-children").children(".jstree-node");
50749		},
50750		/**
50751		 * checks if a node has children
50752		 * @name is_parent(obj)
50753		 * @param  {mixed} obj
50754		 * @return {Boolean}
50755		 */
50756		is_parent : function (obj) {
50757			obj = this.get_node(obj);
50758			return obj && (obj.state.loaded === false || obj.children.length > 0);
50759		},
50760		/**
50761		 * checks if a node is loaded (its children are available)
50762		 * @name is_loaded(obj)
50763		 * @param  {mixed} obj
50764		 * @return {Boolean}
50765		 */
50766		is_loaded : function (obj) {
50767			obj = this.get_node(obj);
50768			return obj && obj.state.loaded;
50769		},
50770		/**
50771		 * check if a node is currently loading (fetching children)
50772		 * @name is_loading(obj)
50773		 * @param  {mixed} obj
50774		 * @return {Boolean}
50775		 */
50776		is_loading : function (obj) {
50777			obj = this.get_node(obj);
50778			return obj && obj.state && obj.state.loading;
50779		},
50780		/**
50781		 * check if a node is opened
50782		 * @name is_open(obj)
50783		 * @param  {mixed} obj
50784		 * @return {Boolean}
50785		 */
50786		is_open : function (obj) {
50787			obj = this.get_node(obj);
50788			return obj && obj.state.opened;
50789		},
50790		/**
50791		 * check if a node is in a closed state
50792		 * @name is_closed(obj)
50793		 * @param  {mixed} obj
50794		 * @return {Boolean}
50795		 */
50796		is_closed : function (obj) {
50797			obj = this.get_node(obj);
50798			return obj && this.is_parent(obj) && !obj.state.opened;
50799		},
50800		/**
50801		 * check if a node has no children
50802		 * @name is_leaf(obj)
50803		 * @param  {mixed} obj
50804		 * @return {Boolean}
50805		 */
50806		is_leaf : function (obj) {
50807			return !this.is_parent(obj);
50808		},
50809		/**
50810		 * loads a node (fetches its children using the `core.data` setting). Multiple nodes can be passed to by using an array.
50811		 * @name load_node(obj [, callback])
50812		 * @param  {mixed} obj
50813		 * @param  {function} callback a function to be executed once loading is complete, the function is executed in the instance's scope and receives two arguments - the node and a boolean status
50814		 * @return {Boolean}
50815		 * @trigger load_node.jstree
50816		 */
50817		load_node : function (obj, callback) {
50818			var 
vendor: 104,922 bytes, lines 50818-53951
50818k, l, i, j, c;
50819			if($.isArray(obj)) {
50820				this._load_nodes(obj.slice(), callback);
50821				return true;
50822			}
50823			obj = this.get_node(obj);
50824			if(!obj) {
50825				if(callback) { callback.call(this, obj, false); }
50826				return false;
50827			}
50828			// if(obj.state.loading) { } // the node is already loading - just wait for it to load and invoke callback? but if called implicitly it should be loaded again?
50829			if(obj.state.loaded) {
50830				obj.state.loaded = false;
50831				for(i = 0, j = obj.parents.length; i < j; i++) {
50832					this._model.data[obj.parents[i]].children_d = $.vakata.array_filter(this._model.data[obj.parents[i]].children_d, function (v) {
50833						return $.inArray(v, obj.children_d) === -1;
50834					});
50835				}
50836				for(k = 0, l = obj.children_d.length; k < l; k++) {
50837					if(this._model.data[obj.children_d[k]].state.selected) {
50838						c = true;
50839					}
50840					delete this._model.data[obj.children_d[k]];
50841				}
50842				if (c) {
50843					this._data.core.selected = $.vakata.array_filter(this._data.core.selected, function (v) {
50844						return $.inArray(v, obj.children_d) === -1;
50845					});
50846				}
50847				obj.children = [];
50848				obj.children_d = [];
50849				if(c) {
50850					this.trigger('changed', { 'action' : 'load_node', 'node' : obj, 'selected' : this._data.core.selected });
50851				}
50852			}
50853			obj.state.failed = false;
50854			obj.state.loading = true;
50855			this.get_node(obj, true).addClass("jstree-loading").attr('aria-busy',true);
50856			this._load_node(obj, $.proxy(function (status) {
50857				obj = this._model.data[obj.id];
50858				obj.state.loading = false;
50859				obj.state.loaded = status;
50860				obj.state.failed = !obj.state.loaded;
50861				var dom = this.get_node(obj, true), i = 0, j = 0, m = this._model.data, has_children = false;
50862				for(i = 0, j = obj.children.length; i < j; i++) {
50863					if(m[obj.children[i]] && !m[obj.children[i]].state.hidden) {
50864						has_children = true;
50865						break;
50866					}
50867				}
50868				if(obj.state.loaded && dom && dom.length) {
50869					dom.removeClass('jstree-closed jstree-open jstree-leaf');
50870					if (!has_children) {
50871						dom.addClass('jstree-leaf');
50872					}
50873					else {
50874						if (obj.id !== '#') {
50875							dom.addClass(obj.state.opened ? 'jstree-open' : 'jstree-closed');
50876						}
50877					}
50878				}
50879				dom.removeClass("jstree-loading").attr('aria-busy',false);
50880				/**
50881				 * triggered after a node is loaded
50882				 * @event
50883				 * @name load_node.jstree
50884				 * @param {Object} node the node that was loading
50885				 * @param {Boolean} status was the node loaded successfully
50886				 */
50887				this.trigger('load_node', { "node" : obj, "status" : status });
50888				if(callback) {
50889					callback.call(this, obj, status);
50890				}
50891			}, this));
50892			return true;
50893		},
50894		/**
50895		 * load an array of nodes (will also load unavailable nodes as soon as they appear in the structure). Used internally.
50896		 * @private
50897		 * @name _load_nodes(nodes [, callback])
50898		 * @param  {array} nodes
50899		 * @param  {function} callback a function to be executed once loading is complete, the function is executed in the instance's scope and receives one argument - the array passed to _load_nodes
50900		 */
50901		_load_nodes : function (nodes, callback, is_callback, force_reload) {
50902			var r = true,
50903				c = function () { this._load_nodes(nodes, callback, true); },
50904				m = this._model.data, i, j, tmp = [];
50905			for(i = 0, j = nodes.length; i < j; i++) {
50906				if(m[nodes[i]] && ( (!m[nodes[i]].state.loaded && !m[nodes[i]].state.failed) || (!is_callback && force_reload) )) {
50907					if(!this.is_loading(nodes[i])) {
50908						this.load_node(nodes[i], c);
50909					}
50910					r = false;
50911				}
50912			}
50913			if(r) {
50914				for(i = 0, j = nodes.length; i < j; i++) {
50915					if(m[nodes[i]] && m[nodes[i]].state.loaded) {
50916						tmp.push(nodes[i]);
50917					}
50918				}
50919				if(callback && !callback.done) {
50920					callback.call(this, tmp);
50921					callback.done = true;
50922				}
50923			}
50924		},
50925		/**
50926		 * loads all unloaded nodes
50927		 * @name load_all([obj, callback])
50928		 * @param {mixed} obj the node to load recursively, omit to load all nodes in the tree
50929		 * @param {function} callback a function to be executed once loading all the nodes is complete,
50930		 * @trigger load_all.jstree
50931		 */
50932		load_all : function (obj, callback) {
50933			if(!obj) { obj = $.jstree.root; }
50934			obj = this.get_node(obj);
50935			if(!obj) { return false; }
50936			var to_load = [],
50937				m = this._model.data,
50938				c = m[obj.id].children_d,
50939				i, j;
50940			if(obj.state && !obj.state.loaded) {
50941				to_load.push(obj.id);
50942			}
50943			for(i = 0, j = c.length; i < j; i++) {
50944				if(m[c[i]] && m[c[i]].state && !m[c[i]].state.loaded) {
50945					to_load.push(c[i]);
50946				}
50947			}
50948			if(to_load.length) {
50949				this._load_nodes(to_load, function () {
50950					this.load_all(obj, callback);
50951				});
50952			}
50953			else {
50954				/**
50955				 * triggered after a load_all call completes
50956				 * @event
50957				 * @name load_all.jstree
50958				 * @param {Object} node the recursively loaded node
50959				 */
50960				if(callback) { callback.call(this, obj); }
50961				this.trigger('load_all', { "node" : obj });
50962			}
50963		},
50964		/**
50965		 * handles the actual loading of a node. Used only internally.
50966		 * @private
50967		 * @name _load_node(obj [, callback])
50968		 * @param  {mixed} obj
50969		 * @param  {function} callback a function to be executed once loading is complete, the function is executed in the instance's scope and receives one argument - a boolean status
50970		 * @return {Boolean}
50971		 */
50972		_load_node : function (obj, callback) {
50973			var s = this.settings.core.data, t;
50974			var notTextOrCommentNode = function notTextOrCommentNode () {
50975				return this.nodeType !== 3 && this.nodeType !== 8;
50976			};
50977			// use original HTML
50978			if(!s) {
50979				if(obj.id === $.jstree.root) {
50980					return this._append_html_data(obj, this._data.core.original_container_html.clone(true), function (status) {
50981						callback.call(this, status);
50982					});
50983				}
50984				else {
50985					return callback.call(this, false);
50986				}
50987				// return callback.call(this, obj.id === $.jstree.root ? this._append_html_data(obj, this._data.core.original_container_html.clone(true)) : false);
50988			}
50989			if($.isFunction(s)) {
50990				return s.call(this, obj, $.proxy(function (d) {
50991					if(d === false) {
50992						callback.call(this, false);
50993					}
50994					else {
50995						this[typeof d === 'string' ? '_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ? $($.parseHTML(d)).filter(notTextOrCommentNode) : d, function (status) {
50996							callback.call(this, status);
50997						});
50998					}
50999					// return d === false ? callback.call(this, false) : callback.call(this, this[typeof d === 'string' ? '_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ? $(d) : d));
51000				}, this));
51001			}
51002			if(typeof s === 'object') {
51003				if(s.url) {
51004					s = $.extend(true, {}, s);
51005					if($.isFunction(s.url)) {
51006						s.url = s.url.call(this, obj);
51007					}
51008					if($.isFunction(s.data)) {
51009						s.data = s.data.call(this, obj);
51010					}
51011					return $.ajax(s)
51012						.done($.proxy(function (d,t,x) {
51013								var type = x.getResponseHeader('Content-Type');
51014								if((type && type.indexOf('json') !== -1) || typeof d === "object") {
51015									return this._append_json_data(obj, d, function (status) { callback.call(this, status); });
51016									//return callback.call(this, this._append_json_data(obj, d));
51017								}
51018								if((type && type.indexOf('html') !== -1) || typeof d === "string") {
51019									return this._append_html_data(obj, $($.parseHTML(d)).filter(notTextOrCommentNode), function (status) { callback.call(this, status); });
51020									// return callback.call(this, this._append_html_data(obj, $(d)));
51021								}
51022								this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'core', 'id' : 'core_04', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id, 'xhr' : x }) };
51023								this.settings.core.error.call(this, this._data.core.last_error);
51024								return callback.call(this, false);
51025							}, this))
51026						.fail($.proxy(function (f) {
51027								this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'core', 'id' : 'core_04', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id, 'xhr' : f }) };
51028								callback.call(this, false);
51029								this.settings.core.error.call(this, this._data.core.last_error);
51030							}, this));
51031				}
51032				if ($.isArray(s)) {
51033					t = $.extend(true, [], s);
51034				} else if ($.isPlainObject(s)) {
51035					t = $.extend(true, {}, s);
51036				} else {
51037					t = s;
51038				}
51039				if(obj.id === $.jstree.root) {
51040					return this._append_json_data(obj, t, function (status) {
51041						callback.call(this, status);
51042					});
51043				}
51044				else {
51045					this._data.core.last_error = { 'error' : 'nodata', 'plugin' : 'core', 'id' : 'core_05', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id }) };
51046					this.settings.core.error.call(this, this._data.core.last_error);
51047					return callback.call(this, false);
51048				}
51049				//return callback.call(this, (obj.id === $.jstree.root ? this._append_json_data(obj, t) : false) );
51050			}
51051			if(typeof s === 'string') {
51052				if(obj.id === $.jstree.root) {
51053					return this._append_html_data(obj, $($.parseHTML(s)).filter(notTextOrCommentNode), function (status) {
51054						callback.call(this, status);
51055					});
51056				}
51057				else {
51058					this._data.core.last_error = { 'error' : 'nodata', 'plugin' : 'core', 'id' : 'core_06', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id }) };
51059					this.settings.core.error.call(this, this._data.core.last_error);
51060					return callback.call(this, false);
51061				}
51062				//return callback.call(this, (obj.id === $.jstree.root ? this._append_html_data(obj, $(s)) : false) );
51063			}
51064			return callback.call(this, false);
51065		},
51066		/**
51067		 * adds a node to the list of nodes to redraw. Used only internally.
51068		 * @private
51069		 * @name _node_changed(obj [, callback])
51070		 * @param  {mixed} obj
51071		 */
51072		_node_changed : function (obj) {
51073			obj = this.get_node(obj);
51074      if (obj && $.inArray(obj.id, this._model.changed) === -1) {
51075				this._model.changed.push(obj.id);
51076			}
51077		},
51078		/**
51079		 * appends HTML content to the tree. Used internally.
51080		 * @private
51081		 * @name _append_html_data(obj, data)
51082		 * @param  {mixed} obj the node to append to
51083		 * @param  {String} data the HTML string to parse and append
51084		 * @trigger model.jstree, changed.jstree
51085		 */
51086		_append_html_data : function (dom, data, cb) {
51087			dom = this.get_node(dom);
51088			dom.children = [];
51089			dom.children_d = [];
51090			var dat = data.is('ul') ? data.children() : data,
51091				par = dom.id,
51092				chd = [],
51093				dpc = [],
51094				m = this._model.data,
51095				p = m[par],
51096				s = this._data.core.selected.length,
51097				tmp, i, j;
51098			dat.each($.proxy(function (i, v) {
51099				tmp = this._parse_model_from_html($(v), par, p.parents.concat());
51100				if(tmp) {
51101					chd.push(tmp);
51102					dpc.push(tmp);
51103					if(m[tmp].children_d.length) {
51104						dpc = dpc.concat(m[tmp].children_d);
51105					}
51106				}
51107			}, this));
51108			p.children = chd;
51109			p.children_d = dpc;
51110			for(i = 0, j = p.parents.length; i < j; i++) {
51111				m[p.parents[i]].children_d = m[p.parents[i]].children_d.concat(dpc);
51112			}
51113			/**
51114			 * triggered when new data is inserted to the tree model
51115			 * @event
51116			 * @name model.jstree
51117			 * @param {Array} nodes an array of node IDs
51118			 * @param {String} parent the parent ID of the nodes
51119			 */
51120			this.trigger('model', { "nodes" : dpc, 'parent' : par });
51121			if(par !== $.jstree.root) {
51122				this._node_changed(par);
51123				this.redraw();
51124			}
51125			else {
51126				this.get_container_ul().children('.jstree-initial-node').remove();
51127				this.redraw(true);
51128			}
51129			if(this._data.core.selected.length !== s) {
51130				this.trigger('changed', { 'action' : 'model', 'selected' : this._data.core.selected });
51131			}
51132			cb.call(this, true);
51133		},
51134		/**
51135		 * appends JSON content to the tree. Used internally.
51136		 * @private
51137		 * @name _append_json_data(obj, data)
51138		 * @param  {mixed} obj the node to append to
51139		 * @param  {String} data the JSON object to parse and append
51140		 * @param  {Boolean} force_processing internal param - do not set
51141		 * @trigger model.jstree, changed.jstree
51142		 */
51143		_append_json_data : function (dom, data, cb, force_processing) {
51144			if(this.element === null) { return; }
51145			dom = this.get_node(dom);
51146			dom.children = [];
51147			dom.children_d = [];
51148			// *%$@!!!
51149			if(data.d) {
51150				data = data.d;
51151				if(typeof data === "string") {
51152					data = JSON.parse(data);
51153				}
51154			}
51155			if(!$.isArray(data)) { data = [data]; }
51156			var w = null,
51157				args = {
51158					'df'	: this._model.default_state,
51159					'dat'	: data,
51160					'par'	: dom.id,
51161					'm'		: this._model.data,
51162					't_id'	: this._id,
51163					't_cnt'	: this._cnt,
51164					'sel'	: this._data.core.selected
51165				},
51166				func = function (data, undefined) {
51167					if(data.data) { data = data.data; }
51168					var dat = data.dat,
51169						par = data.par,
51170						chd = [],
51171						dpc = [],
51172						add = [],
51173						df = data.df,
51174						t_id = data.t_id,
51175						t_cnt = data.t_cnt,
51176						m = data.m,
51177						p = m[par],
51178						sel = data.sel,
51179						tmp, i, j, rslt,
51180						parse_flat = function (d, p, ps) {
51181							if(!ps) { ps = []; }
51182							else { ps = ps.concat(); }
51183							if(p) { ps.unshift(p); }
51184							var tid = d.id.toString(),
51185								i, j, c, e,
51186								tmp = {
51187									id			: tid,
51188									text		: d.text || '',
51189									icon		: d.icon !== undefined ? d.icon : true,
51190									parent		: p,
51191									parents		: ps,
51192									children	: d.children || [],
51193									children_d	: d.children_d || [],
51194									data		: d.data,
51195									state		: { },
51196									li_attr		: { id : false },
51197									a_attr		: { href : '#' },
51198									original	: false
51199								};
51200							for(i in df) {
51201								if(df.hasOwnProperty(i)) {
51202									tmp.state[i] = df[i];
51203								}
51204							}
51205							if(d && d.data && d.data.jstree && d.data.jstree.icon) {
51206								tmp.icon = d.data.jstree.icon;
51207							}
51208							if(tmp.icon === undefined || tmp.icon === null || tmp.icon === "") {
51209								tmp.icon = true;
51210							}
51211							if(d && d.data) {
51212								tmp.data = d.data;
51213								if(d.data.jstree) {
51214									for(i in d.data.jstree) {
51215										if(d.data.jstree.hasOwnProperty(i)) {
51216											tmp.state[i] = d.data.jstree[i];
51217										}
51218									}
51219								}
51220							}
51221							if(d && typeof d.state === 'object') {
51222								for (i in d.state) {
51223									if(d.state.hasOwnProperty(i)) {
51224										tmp.state[i] = d.state[i];
51225									}
51226								}
51227							}
51228							if(d && typeof d.li_attr === 'object') {
51229								for (i in d.li_attr) {
51230									if(d.li_attr.hasOwnProperty(i)) {
51231										tmp.li_attr[i] = d.li_attr[i];
51232									}
51233								}
51234							}
51235							if(!tmp.li_attr.id) {
51236								tmp.li_attr.id = tid;
51237							}
51238							if(d && typeof d.a_attr === 'object') {
51239								for (i in d.a_attr) {
51240									if(d.a_attr.hasOwnProperty(i)) {
51241										tmp.a_attr[i] = d.a_attr[i];
51242									}
51243								}
51244							}
51245							if(d && d.children && d.children === true) {
51246								tmp.state.loaded = false;
51247								tmp.children = [];
51248								tmp.children_d = [];
51249							}
51250							m[tmp.id] = tmp;
51251							for(i = 0, j = tmp.children.length; i < j; i++) {
51252								c = parse_flat(m[tmp.children[i]], tmp.id, ps);
51253								e = m[c];
51254								tmp.children_d.push(c);
51255								if(e.children_d.length) {
51256									tmp.children_d = tmp.children_d.concat(e.children_d);
51257								}
51258							}
51259							delete d.data;
51260							delete d.children;
51261							m[tmp.id].original = d;
51262							if(tmp.state.selected) {
51263								add.push(tmp.id);
51264							}
51265							return tmp.id;
51266						},
51267						parse_nest = function (d, p, ps) {
51268							if(!ps) { ps = []; }
51269							else { ps = ps.concat(); }
51270							if(p) { ps.unshift(p); }
51271							var tid = false, i, j, c, e, tmp;
51272							do {
51273								tid = 'j' + t_id + '_' + (++t_cnt);
51274							} while(m[tid]);
51275
51276							tmp = {
51277								id			: false,
51278								text		: typeof d === 'string' ? d : '',
51279								icon		: typeof d === 'object' && d.icon !== undefined ? d.icon : true,
51280								parent		: p,
51281								parents		: ps,
51282								children	: [],
51283								children_d	: [],
51284								data		: null,
51285								state		: { },
51286								li_attr		: { id : false },
51287								a_attr		: { href : '#' },
51288								original	: false
51289							};
51290							for(i in df) {
51291								if(df.hasOwnProperty(i)) {
51292									tmp.state[i] = df[i];
51293								}
51294							}
51295							if(d && d.id) { tmp.id = d.id.toString(); }
51296							if(d && d.text) { tmp.text = d.text; }
51297							if(d && d.data && d.data.jstree && d.data.jstree.icon) {
51298								tmp.icon = d.data.jstree.icon;
51299							}
51300							if(tmp.icon === undefined || tmp.icon === null || tmp.icon === "") {
51301								tmp.icon = true;
51302							}
51303							if(d && d.data) {
51304								tmp.data = d.data;
51305								if(d.data.jstree) {
51306									for(i in d.data.jstree) {
51307										if(d.data.jstree.hasOwnProperty(i)) {
51308											tmp.state[i] = d.data.jstree[i];
51309										}
51310									}
51311								}
51312							}
51313							if(d && typeof d.state === 'object') {
51314								for (i in d.state) {
51315									if(d.state.hasOwnProperty(i)) {
51316										tmp.state[i] = d.state[i];
51317									}
51318								}
51319							}
51320							if(d && typeof d.li_attr === 'object') {
51321								for (i in d.li_attr) {
51322									if(d.li_attr.hasOwnProperty(i)) {
51323										tmp.li_attr[i] = d.li_attr[i];
51324									}
51325								}
51326							}
51327							if(tmp.li_attr.id && !tmp.id) {
51328								tmp.id = tmp.li_attr.id.toString();
51329							}
51330							if(!tmp.id) {
51331								tmp.id = tid;
51332							}
51333							if(!tmp.li_attr.id) {
51334								tmp.li_attr.id = tmp.id;
51335							}
51336							if(d && typeof d.a_attr === 'object') {
51337								for (i in d.a_attr) {
51338									if(d.a_attr.hasOwnProperty(i)) {
51339										tmp.a_attr[i] = d.a_attr[i];
51340									}
51341								}
51342							}
51343							if(d && d.children && d.children.length) {
51344								for(i = 0, j = d.children.length; i < j; i++) {
51345									c = parse_nest(d.children[i], tmp.id, ps);
51346									e = m[c];
51347									tmp.children.push(c);
51348									if(e.children_d.length) {
51349										tmp.children_d = tmp.children_d.concat(e.children_d);
51350									}
51351								}
51352								tmp.children_d = tmp.children_d.concat(tmp.children);
51353							}
51354							if(d && d.children && d.children === true) {
51355								tmp.state.loaded = false;
51356								tmp.children = [];
51357								tmp.children_d = [];
51358							}
51359							delete d.data;
51360							delete d.children;
51361							tmp.original = d;
51362							m[tmp.id] = tmp;
51363							if(tmp.state.selected) {
51364								add.push(tmp.id);
51365							}
51366							return tmp.id;
51367						};
51368
51369					if(dat.length && dat[0].id !== undefined && dat[0].parent !== undefined) {
51370						// Flat JSON support (for easy import from DB):
51371						// 1) convert to object (foreach)
51372						for(i = 0, j = dat.length; i < j; i++) {
51373							if(!dat[i].children) {
51374								dat[i].children = [];
51375							}
51376							if(!dat[i].state) {
51377								dat[i].state = {};
51378							}
51379							m[dat[i].id.toString()] = dat[i];
51380						}
51381						// 2) populate children (foreach)
51382						for(i = 0, j = dat.length; i < j; i++) {
51383							if (!m[dat[i].parent.toString()]) {
51384								this._data.core.last_error = { 'error' : 'parse', 'plugin' : 'core', 'id' : 'core_07', 'reason' : 'Node with invalid parent', 'data' : JSON.stringify({ 'id' : dat[i].id.toString(), 'parent' : dat[i].parent.toString() }) };
51385								this.settings.core.error.call(this, this._data.core.last_error);
51386								continue;
51387							}
51388
51389							m[dat[i].parent.toString()].children.push(dat[i].id.toString());
51390							// populate parent.children_d
51391							p.children_d.push(dat[i].id.toString());
51392						}
51393						// 3) normalize && populate parents and children_d with recursion
51394						for(i = 0, j = p.children.length; i < j; i++) {
51395							tmp = parse_flat(m[p.children[i]], par, p.parents.concat());
51396							dpc.push(tmp);
51397							if(m[tmp].children_d.length) {
51398								dpc = dpc.concat(m[tmp].children_d);
51399							}
51400						}
51401						for(i = 0, j = p.parents.length; i < j; i++) {
51402							m[p.parents[i]].children_d = m[p.parents[i]].children_d.concat(dpc);
51403						}
51404						// ?) three_state selection - p.state.selected && t - (if three_state foreach(dat => ch) -> foreach(parents) if(parent.selected) child.selected = true;
51405						rslt = {
51406							'cnt' : t_cnt,
51407							'mod' : m,
51408							'sel' : sel,
51409							'par' : par,
51410							'dpc' : dpc,
51411							'add' : add
51412						};
51413					}
51414					else {
51415						for(i = 0, j = dat.length; i < j; i++) {
51416							tmp = parse_nest(dat[i], par, p.parents.concat());
51417							if(tmp) {
51418								chd.push(tmp);
51419								dpc.push(tmp);
51420								if(m[tmp].children_d.length) {
51421									dpc = dpc.concat(m[tmp].children_d);
51422								}
51423							}
51424						}
51425						p.children = chd;
51426						p.children_d = dpc;
51427						for(i = 0, j = p.parents.length; i < j; i++) {
51428							m[p.parents[i]].children_d = m[p.parents[i]].children_d.concat(dpc);
51429						}
51430						rslt = {
51431							'cnt' : t_cnt,
51432							'mod' : m,
51433							'sel' : sel,
51434							'par' : par,
51435							'dpc' : dpc,
51436							'add' : add
51437						};
51438					}
51439					if(typeof window === 'undefined' || typeof window.document === 'undefined') {
51440						postMessage(rslt);
51441					}
51442					else {
51443						return rslt;
51444					}
51445				},
51446				rslt = function (rslt, worker) {
51447					if(this.element === null) { return; }
51448					this._cnt = rslt.cnt;
51449					var i, m = this._model.data;
51450					for (i in m) {
51451						if (m.hasOwnProperty(i) && m[i].state && m[i].state.loading && rslt.mod[i]) {
51452							rslt.mod[i].state.loading = true;
51453						}
51454					}
51455					this._model.data = rslt.mod; // breaks the reference in load_node - careful
51456
51457					if(worker) {
51458						var j, a = rslt.add, r = rslt.sel, s = this._data.core.selected.slice();
51459						m = this._model.data;
51460						// if selection was changed while calculating in worker
51461						if(r.length !== s.length || $.vakata.array_unique(r.concat(s)).length !== r.length) {
51462							// deselect nodes that are no longer selected
51463							for(i = 0, j = r.length; i < j; i++) {
51464								if($.inArray(r[i], a) === -1 && $.inArray(r[i], s) === -1) {
51465									m[r[i]].state.selected = false;
51466								}
51467							}
51468							// select nodes that were selected in the mean time
51469							for(i = 0, j = s.length; i < j; i++) {
51470								if($.inArray(s[i], r) === -1) {
51471									m[s[i]].state.selected = true;
51472								}
51473							}
51474						}
51475					}
51476					if(rslt.add.length) {
51477						this._data.core.selected = this._data.core.selected.concat(rslt.add);
51478					}
51479
51480					this.trigger('model', { "nodes" : rslt.dpc, 'parent' : rslt.par });
51481
51482					if(rslt.par !== $.jstree.root) {
51483						this._node_changed(rslt.par);
51484						this.redraw();
51485					}
51486					else {
51487						// this.get_container_ul().children('.jstree-initial-node').remove();
51488						this.redraw(true);
51489					}
51490					if(rslt.add.length) {
51491						this.trigger('changed', { 'action' : 'model', 'selected' : this._data.core.selected });
51492					}
51493					cb.call(this, true);
51494				};
51495			if(this.settings.core.worker && window.Blob && window.URL && window.Worker) {
51496				try {
51497					if(this._wrk === null) {
51498						this._wrk = window.URL.createObjectURL(
51499							new window.Blob(
51500								['self.onmessage = ' + func.toString()],
51501								{type:"text/javascript"}
51502							)
51503						);
51504					}
51505					if(!this._data.core.working || force_processing) {
51506						this._data.core.working = true;
51507						w = new window.Worker(this._wrk);
51508						w.onmessage = $.proxy(function (e) {
51509							rslt.call(this, e.data, true);
51510							try { w.terminate(); w = null; } catch(ignore) { }
51511							if(this._data.core.worker_queue.length) {
51512								this._append_json_data.apply(this, this._data.core.worker_queue.shift());
51513							}
51514							else {
51515								this._data.core.working = false;
51516							}
51517						}, this);
51518						if(!args.par) {
51519							if(this._data.core.worker_queue.length) {
51520								this._append_json_data.apply(this, this._data.core.worker_queue.shift());
51521							}
51522							else {
51523								this._data.core.working = false;
51524							}
51525						}
51526						else {
51527							w.postMessage(args);
51528						}
51529					}
51530					else {
51531						this._data.core.worker_queue.push([dom, data, cb, true]);
51532					}
51533				}
51534				catch(e) {
51535					rslt.call(this, func(args), false);
51536					if(this._data.core.worker_queue.length) {
51537						this._append_json_data.apply(this, this._data.core.worker_queue.shift());
51538					}
51539					else {
51540						this._data.core.working = false;
51541					}
51542				}
51543			}
51544			else {
51545				rslt.call(this, func(args), false);
51546			}
51547		},
51548		/**
51549		 * parses a node from a jQuery object and appends them to the in memory tree model. Used internally.
51550		 * @private
51551		 * @name _parse_model_from_html(d [, p, ps])
51552		 * @param  {jQuery} d the jQuery object to parse
51553		 * @param  {String} p the parent ID
51554		 * @param  {Array} ps list of all parents
51555		 * @return {String} the ID of the object added to the model
51556		 */
51557		_parse_model_from_html : function (d, p, ps) {
51558			if(!ps) { ps = []; }
51559			else { ps = [].concat(ps); }
51560			if(p) { ps.unshift(p); }
51561			var c, e, m = this._model.data,
51562				data = {
51563					id			: false,
51564					text		: false,
51565					icon		: true,
51566					parent		: p,
51567					parents		: ps,
51568					children	: [],
51569					children_d	: [],
51570					data		: null,
51571					state		: { },
51572					li_attr		: { id : false },
51573					a_attr		: { href : '#' },
51574					original	: false
51575				}, i, tmp, tid;
51576			for(i in this._model.default_state) {
51577				if(this._model.default_state.hasOwnProperty(i)) {
51578					data.state[i] = this._model.default_state[i];
51579				}
51580			}
51581			tmp = $.vakata.attributes(d, true);
51582			$.each(tmp, function (i, v) {
51583				v = $.trim(v);
51584				if(!v.length) { return true; }
51585				data.li_attr[i] = v;
51586				if(i === 'id') {
51587					data.id = v.toString();
51588				}
51589			});
51590			tmp = d.children('a').first();
51591			if(tmp.length) {
51592				tmp = $.vakata.attributes(tmp, true);
51593				$.each(tmp, function (i, v) {
51594					v = $.trim(v);
51595					if(v.length) {
51596						data.a_attr[i] = v;
51597					}
51598				});
51599			}
51600			tmp = d.children("a").first().length ? d.children("a").first().clone() : d.clone();
51601			tmp.children("ins, i, ul").remove();
51602			tmp = tmp.html();
51603			tmp = $('<div />').html(tmp);
51604			data.text = this.settings.core.force_text ? tmp.text() : tmp.html();
51605			tmp = d.data();
51606			data.data = tmp ? $.extend(true, {}, tmp) : null;
51607			data.state.opened = d.hasClass('jstree-open');
51608			data.state.selected = d.children('a').hasClass('jstree-clicked');
51609			data.state.disabled = d.children('a').hasClass('jstree-disabled');
51610			if(data.data && data.data.jstree) {
51611				for(i in data.data.jstree) {
51612					if(data.data.jstree.hasOwnProperty(i)) {
51613						data.state[i] = data.data.jstree[i];
51614					}
51615				}
51616			}
51617			tmp = d.children("a").children(".jstree-themeicon");
51618			if(tmp.length) {
51619				data.icon = tmp.hasClass('jstree-themeicon-hidden') ? false : tmp.attr('rel');
51620			}
51621			if(data.state.icon !== undefined) {
51622				data.icon = data.state.icon;
51623			}
51624			if(data.icon === undefined || data.icon === null || data.icon === "") {
51625				data.icon = true;
51626			}
51627			tmp = d.children("ul").children("li");
51628			do {
51629				tid = 'j' + this._id + '_' + (++this._cnt);
51630			} while(m[tid]);
51631			data.id = data.li_attr.id ? data.li_attr.id.toString() : tid;
51632			if(tmp.length) {
51633				tmp.each($.proxy(function (i, v) {
51634					c = this._parse_model_from_html($(v), data.id, ps);
51635					e = this._model.data[c];
51636					data.children.push(c);
51637					if(e.children_d.length) {
51638						data.children_d = data.children_d.concat(e.children_d);
51639					}
51640				}, this));
51641				data.children_d = data.children_d.concat(data.children);
51642			}
51643			else {
51644				if(d.hasClass('jstree-closed')) {
51645					data.state.loaded = false;
51646				}
51647			}
51648			if(data.li_attr['class']) {
51649				data.li_attr['class'] = data.li_attr['class'].replace('jstree-closed','').replace('jstree-open','');
51650			}
51651			if(data.a_attr['class']) {
51652				data.a_attr['class'] = data.a_attr['class'].replace('jstree-clicked','').replace('jstree-disabled','');
51653			}
51654			m[data.id] = data;
51655			if(data.state.selected) {
51656				this._data.core.selected.push(data.id);
51657			}
51658			return data.id;
51659		},
51660		/**
51661		 * parses a node from a JSON object (used when dealing with flat data, which has no nesting of children, but has id and parent properties) and appends it to the in memory tree model. Used internally.
51662		 * @private
51663		 * @name _parse_model_from_flat_json(d [, p, ps])
51664		 * @param  {Object} d the JSON object to parse
51665		 * @param  {String} p the parent ID
51666		 * @param  {Array} ps list of all parents
51667		 * @return {String} the ID of the object added to the model
51668		 */
51669		_parse_model_from_flat_json : function (d, p, ps) {
51670			if(!ps) { ps = []; }
51671			else { ps = ps.concat(); }
51672			if(p) { ps.unshift(p); }
51673			var tid = d.id.toString(),
51674				m = this._model.data,
51675				df = this._model.default_state,
51676				i, j, c, e,
51677				tmp = {
51678					id			: tid,
51679					text		: d.text || '',
51680					icon		: d.icon !== undefined ? d.icon : true,
51681					parent		: p,
51682					parents		: ps,
51683					children	: d.children || [],
51684					children_d	: d.children_d || [],
51685					data		: d.data,
51686					state		: { },
51687					li_attr		: { id : false },
51688					a_attr		: { href : '#' },
51689					original	: false
51690				};
51691			for(i in df) {
51692				if(df.hasOwnProperty(i)) {
51693					tmp.state[i] = df[i];
51694				}
51695			}
51696			if(d && d.data && d.data.jstree && d.data.jstree.icon) {
51697				tmp.icon = d.data.jstree.icon;
51698			}
51699			if(tmp.icon === undefined || tmp.icon === null || tmp.icon === "") {
51700				tmp.icon = true;
51701			}
51702			if(d && d.data) {
51703				tmp.data = d.data;
51704				if(d.data.jstree) {
51705					for(i in d.data.jstree) {
51706						if(d.data.jstree.hasOwnProperty(i)) {
51707							tmp.state[i] = d.data.jstree[i];
51708						}
51709					}
51710				}
51711			}
51712			if(d && typeof d.state === 'object') {
51713				for (i in d.state) {
51714					if(d.state.hasOwnProperty(i)) {
51715						tmp.state[i] = d.state[i];
51716					}
51717				}
51718			}
51719			if(d && typeof d.li_attr === 'object') {
51720				for (i in d.li_attr) {
51721					if(d.li_attr.hasOwnProperty(i)) {
51722						tmp.li_attr[i] = d.li_attr[i];
51723					}
51724				}
51725			}
51726			if(!tmp.li_attr.id) {
51727				tmp.li_attr.id = tid;
51728			}
51729			if(d && typeof d.a_attr === 'object') {
51730				for (i in d.a_attr) {
51731					if(d.a_attr.hasOwnProperty(i)) {
51732						tmp.a_attr[i] = d.a_attr[i];
51733					}
51734				}
51735			}
51736			if(d && d.children && d.children === true) {
51737				tmp.state.loaded = false;
51738				tmp.children = [];
51739				tmp.children_d = [];
51740			}
51741			m[tmp.id] = tmp;
51742			for(i = 0, j = tmp.children.length; i < j; i++) {
51743				c = this._parse_model_from_flat_json(m[tmp.children[i]], tmp.id, ps);
51744				e = m[c];
51745				tmp.children_d.push(c);
51746				if(e.children_d.length) {
51747					tmp.children_d = tmp.children_d.concat(e.children_d);
51748				}
51749			}
51750			delete d.data;
51751			delete d.children;
51752			m[tmp.id].original = d;
51753			if(tmp.state.selected) {
51754				this._data.core.selected.push(tmp.id);
51755			}
51756			return tmp.id;
51757		},
51758		/**
51759		 * parses a node from a JSON object and appends it to the in memory tree model. Used internally.
51760		 * @private
51761		 * @name _parse_model_from_json(d [, p, ps])
51762		 * @param  {Object} d the JSON object to parse
51763		 * @param  {String} p the parent ID
51764		 * @param  {Array} ps list of all parents
51765		 * @return {String} the ID of the object added to the model
51766		 */
51767		_parse_model_from_json : function (d, p, ps) {
51768			if(!ps) { ps = []; }
51769			else { ps = ps.concat(); }
51770			if(p) { ps.unshift(p); }
51771			var tid = false, i, j, c, e, m = this._model.data, df = this._model.default_state, tmp;
51772			do {
51773				tid = 'j' + this._id + '_' + (++this._cnt);
51774			} while(m[tid]);
51775
51776			tmp = {
51777				id			: false,
51778				text		: typeof d === 'string' ? d : '',
51779				icon		: typeof d === 'object' && d.icon !== undefined ? d.icon : true,
51780				parent		: p,
51781				parents		: ps,
51782				children	: [],
51783				children_d	: [],
51784				data		: null,
51785				state		: { },
51786				li_attr		: { id : false },
51787				a_attr		: { href : '#' },
51788				original	: false
51789			};
51790			for(i in df) {
51791				if(df.hasOwnProperty(i)) {
51792					tmp.state[i] = df[i];
51793				}
51794			}
51795			if(d && d.id) { tmp.id = d.id.toString(); }
51796			if(d && d.text) { tmp.text = d.text; }
51797			if(d && d.data && d.data.jstree && d.data.jstree.icon) {
51798				tmp.icon = d.data.jstree.icon;
51799			}
51800			if(tmp.icon === undefined || tmp.icon === null || tmp.icon === "") {
51801				tmp.icon = true;
51802			}
51803			if(d && d.data) {
51804				tmp.data = d.data;
51805				if(d.data.jstree) {
51806					for(i in d.data.jstree) {
51807						if(d.data.jstree.hasOwnProperty(i)) {
51808							tmp.state[i] = d.data.jstree[i];
51809						}
51810					}
51811				}
51812			}
51813			if(d && typeof d.state === 'object') {
51814				for (i in d.state) {
51815					if(d.state.hasOwnProperty(i)) {
51816						tmp.state[i] = d.state[i];
51817					}
51818				}
51819			}
51820			if(d && typeof d.li_attr === 'object') {
51821				for (i in d.li_attr) {
51822					if(d.li_attr.hasOwnProperty(i)) {
51823						tmp.li_attr[i] = d.li_attr[i];
51824					}
51825				}
51826			}
51827			if(tmp.li_attr.id && !tmp.id) {
51828				tmp.id = tmp.li_attr.id.toString();
51829			}
51830			if(!tmp.id) {
51831				tmp.id = tid;
51832			}
51833			if(!tmp.li_attr.id) {
51834				tmp.li_attr.id = tmp.id;
51835			}
51836			if(d && typeof d.a_attr === 'object') {
51837				for (i in d.a_attr) {
51838					if(d.a_attr.hasOwnProperty(i)) {
51839						tmp.a_attr[i] = d.a_attr[i];
51840					}
51841				}
51842			}
51843			if(d && d.children && d.children.length) {
51844				for(i = 0, j = d.children.length; i < j; i++) {
51845					c = this._parse_model_from_json(d.children[i], tmp.id, ps);
51846					e = m[c];
51847					tmp.children.push(c);
51848					if(e.children_d.length) {
51849						tmp.children_d = tmp.children_d.concat(e.children_d);
51850					}
51851				}
51852				tmp.children_d = tmp.children_d.concat(tmp.children);
51853			}
51854			if(d && d.children && d.children === true) {
51855				tmp.state.loaded = false;
51856				tmp.children = [];
51857				tmp.children_d = [];
51858			}
51859			delete d.data;
51860			delete d.children;
51861			tmp.original = d;
51862			m[tmp.id] = tmp;
51863			if(tmp.state.selected) {
51864				this._data.core.selected.push(tmp.id);
51865			}
51866			return tmp.id;
51867		},
51868		/**
51869		 * redraws all nodes that need to be redrawn. Used internally.
51870		 * @private
51871		 * @name _redraw()
51872		 * @trigger redraw.jstree
51873		 */
51874		_redraw : function () {
51875			var nodes = this._model.force_full_redraw ? this._model.data[$.jstree.root].children.concat([]) : this._model.changed.concat([]),
51876				f = document.createElement('UL'), tmp, i, j, fe = this._data.core.focused;
51877			for(i = 0, j = nodes.length; i < j; i++) {
51878				tmp = this.redraw_node(nodes[i], true, this._model.force_full_redraw);
51879				if(tmp && this._model.force_full_redraw) {
51880					f.appendChild(tmp);
51881				}
51882			}
51883			if(this._model.force_full_redraw) {
51884				f.className = this.get_container_ul()[0].className;
51885				f.setAttribute('role','group');
51886				this.element.empty().append(f);
51887				//this.get_container_ul()[0].appendChild(f);
51888			}
51889			if(fe !== null && this.settings.core.restore_focus) {
51890				tmp = this.get_node(fe, true);
51891				if(tmp && tmp.length && tmp.children('.jstree-anchor')[0] !== document.activeElement) {
51892					tmp.children('.jstree-anchor').focus();
51893				}
51894				else {
51895					this._data.core.focused = null;
51896				}
51897			}
51898			this._model.force_full_redraw = false;
51899			this._model.changed = [];
51900			/**
51901			 * triggered after nodes are redrawn
51902			 * @event
51903			 * @name redraw.jstree
51904			 * @param {array} nodes the redrawn nodes
51905			 */
51906			this.trigger('redraw', { "nodes" : nodes });
51907		},
51908		/**
51909		 * redraws all nodes that need to be redrawn or optionally - the whole tree
51910		 * @name redraw([full])
51911		 * @param {Boolean} full if set to `true` all nodes are redrawn.
51912		 */
51913		redraw : function (full) {
51914			if(full) {
51915				this._model.force_full_redraw = true;
51916			}
51917			//if(this._model.redraw_timeout) {
51918			//	clearTimeout(this._model.redraw_timeout);
51919			//}
51920			//this._model.redraw_timeout = setTimeout($.proxy(this._redraw, this),0);
51921			this._redraw();
51922		},
51923		/**
51924		 * redraws a single node's children. Used internally.
51925		 * @private
51926		 * @name draw_children(node)
51927		 * @param {mixed} node the node whose children will be redrawn
51928		 */
51929		draw_children : function (node) {
51930			var obj = this.get_node(node),
51931				i = false,
51932				j = false,
51933				k = false,
51934				d = document;
51935			if(!obj) { return false; }
51936			if(obj.id === $.jstree.root) { return this.redraw(true); }
51937			node = this.get_node(node, true);
51938			if(!node || !node.length) { return false; } // TODO: quick toggle
51939
51940			node.children('.jstree-children').remove();
51941			node = node[0];
51942			if(obj.children.length && obj.state.loaded) {
51943				k = d.createElement('UL');
51944				k.setAttribute('role', 'group');
51945				k.className = 'jstree-children';
51946				for(i = 0, j = obj.children.length; i < j; i++) {
51947					k.appendChild(this.redraw_node(obj.children[i], true, true));
51948				}
51949				node.appendChild(k);
51950			}
51951		},
51952		/**
51953		 * redraws a single node. Used internally.
51954		 * @private
51955		 * @name redraw_node(node, deep, is_callback, force_render)
51956		 * @param {mixed} node the node to redraw
51957		 * @param {Boolean} deep should child nodes be redrawn too
51958		 * @param {Boolean} is_callback is this a recursion call
51959		 * @param {Boolean} force_render should children of closed parents be drawn anyway
51960		 */
51961		redraw_node : function (node, deep, is_callback, force_render) {
51962			var obj = this.get_node(node),
51963				par = false,
51964				ind = false,
51965				old = false,
51966				i = false,
51967				j = false,
51968				k = false,
51969				c = '',
51970				d = document,
51971				m = this._model.data,
51972				f = false,
51973				s = false,
51974				tmp = null,
51975				t = 0,
51976				l = 0,
51977				has_children = false,
51978				last_sibling = false;
51979			if(!obj) { return false; }
51980			if(obj.id === $.jstree.root) {  return this.redraw(true); }
51981			deep = deep || obj.children.length === 0;
51982			node = !document.querySelector ? document.getElementById(obj.id) : this.element[0].querySelector('#' + ("0123456789".indexOf(obj.id[0]) !== -1 ? '\\3' + obj.id[0] + ' ' + obj.id.substr(1).replace($.jstree.idregex,'\\$&') : obj.id.replace($.jstree.idregex,'\\$&')) ); //, this.element);
51983			if(!node) {
51984				deep = true;
51985				//node = d.createElement('LI');
51986				if(!is_callback) {
51987					par = obj.parent !== $.jstree.root ? $('#' + obj.parent.replace($.jstree.idregex,'\\$&'), this.element)[0] : null;
51988					if(par !== null && (!par || !m[obj.parent].state.opened)) {
51989						return false;
51990					}
51991					ind = $.inArray(obj.id, par === null ? m[$.jstree.root].children : m[obj.parent].children);
51992				}
51993			}
51994			else {
51995				node = $(node);
51996				if(!is_callback) {
51997					par = node.parent().parent()[0];
51998					if(par === this.element[0]) {
51999						par = null;
52000					}
52001					ind = node.index();
52002				}
52003				// m[obj.id].data = node.data(); // use only node's data, no need to touch jquery storage
52004				if(!deep && obj.children.length && !node.children('.jstree-children').length) {
52005					deep = true;
52006				}
52007				if(!deep) {
52008					old = node.children('.jstree-children')[0];
52009				}
52010				f = node.children('.jstree-anchor')[0] === document.activeElement;
52011				node.remove();
52012				//node = d.createElement('LI');
52013				//node = node[0];
52014			}
52015			node = this._data.core.node.cloneNode(true);
52016			// node is DOM, deep is boolean
52017
52018			c = 'jstree-node ';
52019			for(i in obj.li_attr) {
52020				if(obj.li_attr.hasOwnProperty(i)) {
52021					if(i === 'id') { continue; }
52022					if(i !== 'class') {
52023						node.setAttribute(i, obj.li_attr[i]);
52024					}
52025					else {
52026						c += obj.li_attr[i];
52027					}
52028				}
52029			}
52030			if(!obj.a_attr.id) {
52031				obj.a_attr.id = obj.id + '_anchor';
52032			}
52033			node.setAttribute('aria-selected', !!obj.state.selected);
52034			node.setAttribute('aria-level', obj.parents.length);
52035			node.setAttribute('aria-labelledby', obj.a_attr.id);
52036			if(obj.state.disabled) {
52037				node.setAttribute('aria-disabled', true);
52038			}
52039
52040			for(i = 0, j = obj.children.length; i < j; i++) {
52041				if(!m[obj.children[i]].state.hidden) {
52042					has_children = true;
52043					break;
52044				}
52045			}
52046			if(obj.parent !== null && m[obj.parent] && !obj.state.hidden) {
52047				i = $.inArray(obj.id, m[obj.parent].children);
52048				last_sibling = obj.id;
52049				if(i !== -1) {
52050					i++;
52051					for(j = m[obj.parent].children.length; i < j; i++) {
52052						if(!m[m[obj.parent].children[i]].state.hidden) {
52053							last_sibling = m[obj.parent].children[i];
52054						}
52055						if(last_sibling !== obj.id) {
52056							break;
52057						}
52058					}
52059				}
52060			}
52061
52062			if(obj.state.hidden) {
52063				c += ' jstree-hidden';
52064			}
52065			if (obj.state.loading) {
52066				c += ' jstree-loading';
52067			}
52068			if(obj.state.loaded && !has_children) {
52069				c += ' jstree-leaf';
52070			}
52071			else {
52072				c += obj.state.opened && obj.state.loaded ? ' jstree-open' : ' jstree-closed';
52073				node.setAttribute('aria-expanded', (obj.state.opened && obj.state.loaded) );
52074			}
52075			if(last_sibling === obj.id) {
52076				c += ' jstree-last';
52077			}
52078			node.id = obj.id;
52079			node.className = c;
52080			c = ( obj.state.selected ? ' jstree-clicked' : '') + ( obj.state.disabled ? ' jstree-disabled' : '');
52081			for(j in obj.a_attr) {
52082				if(obj.a_attr.hasOwnProperty(j)) {
52083					if(j === 'href' && obj.a_attr[j] === '#') { continue; }
52084					if(j !== 'class') {
52085						node.childNodes[1].setAttribute(j, obj.a_attr[j]);
52086					}
52087					else {
52088						c += ' ' + obj.a_attr[j];
52089					}
52090				}
52091			}
52092			if(c.length) {
52093				node.childNodes[1].className = 'jstree-anchor ' + c;
52094			}
52095			if((obj.icon && obj.icon !== true) || obj.icon === false) {
52096				if(obj.icon === false) {
52097					node.childNodes[1].childNodes[0].className += ' jstree-themeicon-hidden';
52098				}
52099				else if(obj.icon.indexOf('/') === -1 && obj.icon.indexOf('.') === -1) {
52100					node.childNodes[1].childNodes[0].className += ' ' + obj.icon + ' jstree-themeicon-custom';
52101				}
52102				else {
52103					node.childNodes[1].childNodes[0].style.backgroundImage = 'url("'+obj.icon+'")';
52104					node.childNodes[1].childNodes[0].style.backgroundPosition = 'center center';
52105					node.childNodes[1].childNodes[0].style.backgroundSize = 'auto';
52106					node.childNodes[1].childNodes[0].className += ' jstree-themeicon-custom';
52107				}
52108			}
52109
52110			if(this.settings.core.force_text) {
52111				node.childNodes[1].appendChild(d.createTextNode(obj.text));
52112			}
52113			else {
52114				node.childNodes[1].innerHTML += obj.text;
52115			}
52116
52117
52118			if(deep && obj.children.length && (obj.state.opened || force_render) && obj.state.loaded) {
52119				k = d.createElement('UL');
52120				k.setAttribute('role', 'group');
52121				k.className = 'jstree-children';
52122				for(i = 0, j = obj.children.length; i < j; i++) {
52123					k.appendChild(this.redraw_node(obj.children[i], deep, true));
52124				}
52125				node.appendChild(k);
52126			}
52127			if(old) {
52128				node.appendChild(old);
52129			}
52130			if(!is_callback) {
52131				// append back using par / ind
52132				if(!par) {
52133					par = this.element[0];
52134				}
52135				for(i = 0, j = par.childNodes.length; i < j; i++) {
52136					if(par.childNodes[i] && par.childNodes[i].className && par.childNodes[i].className.indexOf('jstree-children') !== -1) {
52137						tmp = par.childNodes[i];
52138						break;
52139					}
52140				}
52141				if(!tmp) {
52142					tmp = d.createElement('UL');
52143					tmp.setAttribute('role', 'group');
52144					tmp.className = 'jstree-children';
52145					par.appendChild(tmp);
52146				}
52147				par = tmp;
52148
52149				if(ind < par.childNodes.length) {
52150					par.insertBefore(node, par.childNodes[ind]);
52151				}
52152				else {
52153					par.appendChild(node);
52154				}
52155				if(f) {
52156					t = this.element[0].scrollTop;
52157					l = this.element[0].scrollLeft;
52158					node.childNodes[1].focus();
52159					this.element[0].scrollTop = t;
52160					this.element[0].scrollLeft = l;
52161				}
52162			}
52163			if(obj.state.opened && !obj.state.loaded) {
52164				obj.state.opened = false;
52165				setTimeout($.proxy(function () {
52166					this.open_node(obj.id, false, 0);
52167				}, this), 0);
52168			}
52169			return node;
52170		},
52171		/**
52172		 * opens a node, revealing its children. If the node is not loaded it will be loaded and opened once ready.
52173		 * @name open_node(obj [, callback, animation])
52174		 * @param {mixed} obj the node to open
52175		 * @param {Function} callback a function to execute once the node is opened
52176		 * @param {Number} animation the animation duration in milliseconds when opening the node (overrides the `core.animation` setting). Use `false` for no animation.
52177		 * @trigger open_node.jstree, after_open.jstree, before_open.jstree
52178		 */
52179		open_node : function (obj, callback, animation) {
52180			var t1, t2, d, t;
52181			if($.isArray(obj)) {
52182				obj = obj.slice();
52183				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
52184					this.open_node(obj[t1], callback, animation);
52185				}
52186				return true;
52187			}
52188			obj = this.get_node(obj);
52189			if(!obj || obj.id === $.jstree.root) {
52190				return false;
52191			}
52192			animation = animation === undefined ? this.settings.core.animation : animation;
52193			if(!this.is_closed(obj)) {
52194				if(callback) {
52195					callback.call(this, obj, false);
52196				}
52197				return false;
52198			}
52199			if(!this.is_loaded(obj)) {
52200				if(this.is_loading(obj)) {
52201					return setTimeout($.proxy(function () {
52202						this.open_node(obj, callback, animation);
52203					}, this), 500);
52204				}
52205				this.load_node(obj, function (o, ok) {
52206					return ok ? this.open_node(o, callback, animation) : (callback ? callback.call(this, o, false) : false);
52207				});
52208			}
52209			else {
52210				d = this.get_node(obj, true);
52211				t = this;
52212				if(d.length) {
52213					if(animation && d.children(".jstree-children").length) {
52214						d.children(".jstree-children").stop(true, true);
52215					}
52216					if(obj.children.length && !this._firstChild(d.children('.jstree-children')[0])) {
52217						this.draw_children(obj);
52218						//d = this.get_node(obj, true);
52219					}
52220					if(!animation) {
52221						this.trigger('before_open', { "node" : obj });
52222						d[0].className = d[0].className.replace('jstree-closed', 'jstree-open');
52223						d[0].setAttribute("aria-expanded", true);
52224					}
52225					else {
52226						this.trigger('before_open', { "node" : obj });
52227						d
52228							.children(".jstree-children").css("display","none").end()
52229							.removeClass("jstree-closed").addClass("jstree-open").attr("aria-expanded", true)
52230							.children(".jstree-children").stop(true, true)
52231								.slideDown(animation, function () {
52232									this.style.display = "";
52233									if (t.element) {
52234										t.trigger("after_open", { "node" : obj });
52235									}
52236								});
52237					}
52238				}
52239				obj.state.opened = true;
52240				if(callback) {
52241					callback.call(this, obj, true);
52242				}
52243				if(!d.length) {
52244					/**
52245					 * triggered when a node is about to be opened (if the node is supposed to be in the DOM, it will be, but it won't be visible yet)
52246					 * @event
52247					 * @name before_open.jstree
52248					 * @param {Object} node the opened node
52249					 */
52250					this.trigger('before_open', { "node" : obj });
52251				}
52252				/**
52253				 * triggered when a node is opened (if there is an animation it will not be completed yet)
52254				 * @event
52255				 * @name open_node.jstree
52256				 * @param {Object} node the opened node
52257				 */
52258				this.trigger('open_node', { "node" : obj });
52259				if(!animation || !d.length) {
52260					/**
52261					 * triggered when a node is opened and the animation is complete
52262					 * @event
52263					 * @name after_open.jstree
52264					 * @param {Object} node the opened node
52265					 */
52266					this.trigger("after_open", { "node" : obj });
52267				}
52268				return true;
52269			}
52270		},
52271		/**
52272		 * opens every parent of a node (node should be loaded)
52273		 * @name _open_to(obj)
52274		 * @param {mixed} obj the node to reveal
52275		 * @private
52276		 */
52277		_open_to : function (obj) {
52278			obj = this.get_node(obj);
52279			if(!obj || obj.id === $.jstree.root) {
52280				return false;
52281			}
52282			var i, j, p = obj.parents;
52283			for(i = 0, j = p.length; i < j; i+=1) {
52284				if(i !== $.jstree.root) {
52285					this.open_node(p[i], false, 0);
52286				}
52287			}
52288			return $('#' + obj.id.replace($.jstree.idregex,'\\$&'), this.element);
52289		},
52290		/**
52291		 * closes a node, hiding its children
52292		 * @name close_node(obj [, animation])
52293		 * @param {mixed} obj the node to close
52294		 * @param {Number} animation the animation duration in milliseconds when closing the node (overrides the `core.animation` setting). Use `false` for no animation.
52295		 * @trigger close_node.jstree, after_close.jstree
52296		 */
52297		close_node : function (obj, animation) {
52298			var t1, t2, t, d;
52299			if($.isArray(obj)) {
52300				obj = obj.slice();
52301				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
52302					this.close_node(obj[t1], animation);
52303				}
52304				return true;
52305			}
52306			obj = this.get_node(obj);
52307			if(!obj || obj.id === $.jstree.root) {
52308				return false;
52309			}
52310			if(this.is_closed(obj)) {
52311				return false;
52312			}
52313			animation = animation === undefined ? this.settings.core.animation : animation;
52314			t = this;
52315			d = this.get_node(obj, true);
52316
52317			obj.state.opened = false;
52318			/**
52319			 * triggered when a node is closed (if there is an animation it will not be complete yet)
52320			 * @event
52321			 * @name close_node.jstree
52322			 * @param {Object} node the closed node
52323			 */
52324			this.trigger('close_node',{ "node" : obj });
52325			if(!d.length) {
52326				/**
52327				 * triggered when a node is closed and the animation is complete
52328				 * @event
52329				 * @name after_close.jstree
52330				 * @param {Object} node the closed node
52331				 */
52332				this.trigger("after_close", { "node" : obj });
52333			}
52334			else {
52335				if(!animation) {
52336					d[0].className = d[0].className.replace('jstree-open', 'jstree-closed');
52337					d.attr("aria-expanded", false).children('.jstree-children').remove();
52338					this.trigger("after_close", { "node" : obj });
52339				}
52340				else {
52341					d
52342						.children(".jstree-children").attr("style","display:block !important").end()
52343						.removeClass("jstree-open").addClass("jstree-closed").attr("aria-expanded", false)
52344						.children(".jstree-children").stop(true, true).slideUp(animation, function () {
52345							this.style.display = "";
52346							d.children('.jstree-children').remove();
52347							if (t.element) {
52348								t.trigger("after_close", { "node" : obj });
52349							}
52350						});
52351				}
52352			}
52353		},
52354		/**
52355		 * toggles a node - closing it if it is open, opening it if it is closed
52356		 * @name toggle_node(obj)
52357		 * @param {mixed} obj the node to toggle
52358		 */
52359		toggle_node : function (obj) {
52360			var t1, t2;
52361			if($.isArray(obj)) {
52362				obj = obj.slice();
52363				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
52364					this.toggle_node(obj[t1]);
52365				}
52366				return true;
52367			}
52368			if(this.is_closed(obj)) {
52369				return this.open_node(obj);
52370			}
52371			if(this.is_open(obj)) {
52372				return this.close_node(obj);
52373			}
52374		},
52375		/**
52376		 * opens all nodes within a node (or the tree), revealing their children. If the node is not loaded it will be loaded and opened once ready.
52377		 * @name open_all([obj, animation, original_obj])
52378		 * @param {mixed} obj the node to open recursively, omit to open all nodes in the tree
52379		 * @param {Number} animation the animation duration in milliseconds when opening the nodes, the default is no animation
52380		 * @param {jQuery} reference to the node that started the process (internal use)
52381		 * @trigger open_all.jstree
52382		 */
52383		open_all : function (obj, animation, original_obj) {
52384			if(!obj) { obj = $.jstree.root; }
52385			obj = this.get_node(obj);
52386			if(!obj) { return false; }
52387			var dom = obj.id === $.jstree.root ? this.get_container_ul() : this.get_node(obj, true), i, j, _this;
52388			if(!dom.length) {
52389				for(i = 0, j = obj.children_d.length; i < j; i++) {
52390					if(this.is_closed(this._model.data[obj.children_d[i]])) {
52391						this._model.data[obj.children_d[i]].state.opened = true;
52392					}
52393				}
52394				return this.trigger('open_all', { "node" : obj });
52395			}
52396			original_obj = original_obj || dom;
52397			_this = this;
52398			dom = this.is_closed(obj) ? dom.find('.jstree-closed').addBack() : dom.find('.jstree-closed');
52399			dom.each(function () {
52400				_this.open_node(
52401					this,
52402					function(node, status) { if(status && this.is_parent(node)) { this.open_all(node, animation, original_obj); } },
52403					animation || 0
52404				);
52405			});
52406			if(original_obj.find('.jstree-closed').length === 0) {
52407				/**
52408				 * triggered when an `open_all` call completes
52409				 * @event
52410				 * @name open_all.jstree
52411				 * @param {Object} node the opened node
52412				 */
52413				this.trigger('open_all', { "node" : this.get_node(original_obj) });
52414			}
52415		},
52416		/**
52417		 * closes all nodes within a node (or the tree), revealing their children
52418		 * @name close_all([obj, animation])
52419		 * @param {mixed} obj the node to close recursively, omit to close all nodes in the tree
52420		 * @param {Number} animation the animation duration in milliseconds when closing the nodes, the default is no animation
52421		 * @trigger close_all.jstree
52422		 */
52423		close_all : function (obj, animation) {
52424			if(!obj) { obj = $.jstree.root; }
52425			obj = this.get_node(obj);
52426			if(!obj) { return false; }
52427			var dom = obj.id === $.jstree.root ? this.get_container_ul() : this.get_node(obj, true),
52428				_this = this, i, j;
52429			if(dom.length) {
52430				dom = this.is_open(obj) ? dom.find('.jstree-open').addBack() : dom.find('.jstree-open');
52431				$(dom.get().reverse()).each(function () { _this.close_node(this, animation || 0); });
52432			}
52433			for(i = 0, j = obj.children_d.length; i < j; i++) {
52434				this._model.data[obj.children_d[i]].state.opened = false;
52435			}
52436			/**
52437			 * triggered when an `close_all` call completes
52438			 * @event
52439			 * @name close_all.jstree
52440			 * @param {Object} node the closed node
52441			 */
52442			this.trigger('close_all', { "node" : obj });
52443		},
52444		/**
52445		 * checks if a node is disabled (not selectable)
52446		 * @name is_disabled(obj)
52447		 * @param  {mixed} obj
52448		 * @return {Boolean}
52449		 */
52450		is_disabled : function (obj) {
52451			obj = this.get_node(obj);
52452			return obj && obj.state && obj.state.disabled;
52453		},
52454		/**
52455		 * enables a node - so that it can be selected
52456		 * @name enable_node(obj)
52457		 * @param {mixed} obj the node to enable
52458		 * @trigger enable_node.jstree
52459		 */
52460		enable_node : function (obj) {
52461			var t1, t2;
52462			if($.isArray(obj)) {
52463				obj = obj.slice();
52464				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
52465					this.enable_node(obj[t1]);
52466				}
52467				return true;
52468			}
52469			obj = this.get_node(obj);
52470			if(!obj || obj.id === $.jstree.root) {
52471				return false;
52472			}
52473			obj.state.disabled = false;
52474			this.get_node(obj,true).children('.jstree-anchor').removeClass('jstree-disabled').attr('aria-disabled', false);
52475			/**
52476			 * triggered when an node is enabled
52477			 * @event
52478			 * @name enable_node.jstree
52479			 * @param {Object} node the enabled node
52480			 */
52481			this.trigger('enable_node', { 'node' : obj });
52482		},
52483		/**
52484		 * disables a node - so that it can not be selected
52485		 * @name disable_node(obj)
52486		 * @param {mixed} obj the node to disable
52487		 * @trigger disable_node.jstree
52488		 */
52489		disable_node : function (obj) {
52490			var t1, t2;
52491			if($.isArray(obj)) {
52492				obj = obj.slice();
52493				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
52494					this.disable_node(obj[t1]);
52495				}
52496				return true;
52497			}
52498			obj = this.get_node(obj);
52499			if(!obj || obj.id === $.jstree.root) {
52500				return false;
52501			}
52502			obj.state.disabled = true;
52503			this.get_node(obj,true).children('.jstree-anchor').addClass('jstree-disabled').attr('aria-disabled', true);
52504			/**
52505			 * triggered when an node is disabled
52506			 * @event
52507			 * @name disable_node.jstree
52508			 * @param {Object} node the disabled node
52509			 */
52510			this.trigger('disable_node', { 'node' : obj });
52511		},
52512		/**
52513		 * determines if a node is hidden
52514		 * @name is_hidden(obj)
52515		 * @param {mixed} obj the node
52516		 */
52517		is_hidden : function (obj) {
52518			obj = this.get_node(obj);
52519			return obj.state.hidden === true;
52520		},
52521		/**
52522		 * hides a node - it is still in the structure but will not be visible
52523		 * @name hide_node(obj)
52524		 * @param {mixed} obj the node to hide
52525		 * @param {Boolean} skip_redraw internal parameter controlling if redraw is called
52526		 * @trigger hide_node.jstree
52527		 */
52528		hide_node : function (obj, skip_redraw) {
52529			var t1, t2;
52530			if($.isArray(obj)) {
52531				obj = obj.slice();
52532				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
52533					this.hide_node(obj[t1], true);
52534				}
52535				if (!skip_redraw) {
52536					this.redraw();
52537				}
52538				return true;
52539			}
52540			obj = this.get_node(obj);
52541			if(!obj || obj.id === $.jstree.root) {
52542				return false;
52543			}
52544			if(!obj.state.hidden) {
52545				obj.state.hidden = true;
52546				this._node_changed(obj.parent);
52547				if(!skip_redraw) {
52548					this.redraw();
52549				}
52550				/**
52551				 * triggered when an node is hidden
52552				 * @event
52553				 * @name hide_node.jstree
52554				 * @param {Object} node the hidden node
52555				 */
52556				this.trigger('hide_node', { 'node' : obj });
52557			}
52558		},
52559		/**
52560		 * shows a node
52561		 * @name show_node(obj)
52562		 * @param {mixed} obj the node to show
52563		 * @param {Boolean} skip_redraw internal parameter controlling if redraw is called
52564		 * @trigger show_node.jstree
52565		 */
52566		show_node : function (obj, skip_redraw) {
52567			var t1, t2;
52568			if($.isArray(obj)) {
52569				obj = obj.slice();
52570				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
52571					this.show_node(obj[t1], true);
52572				}
52573				if (!skip_redraw) {
52574					this.redraw();
52575				}
52576				return true;
52577			}
52578			obj = this.get_node(obj);
52579			if(!obj || obj.id === $.jstree.root) {
52580				return false;
52581			}
52582			if(obj.state.hidden) {
52583				obj.state.hidden = false;
52584				this._node_changed(obj.parent);
52585				if(!skip_redraw) {
52586					this.redraw();
52587				}
52588				/**
52589				 * triggered when an node is shown
52590				 * @event
52591				 * @name show_node.jstree
52592				 * @param {Object} node the shown node
52593				 */
52594				this.trigger('show_node', { 'node' : obj });
52595			}
52596		},
52597		/**
52598		 * hides all nodes
52599		 * @name hide_all()
52600		 * @trigger hide_all.jstree
52601		 */
52602		hide_all : function (skip_redraw) {
52603			var i, m = this._model.data, ids = [];
52604			for(i in m) {
52605				if(m.hasOwnProperty(i) && i !== $.jstree.root && !m[i].state.hidden) {
52606					m[i].state.hidden = true;
52607					ids.push(i);
52608				}
52609			}
52610			this._model.force_full_redraw = true;
52611			if(!skip_redraw) {
52612				this.redraw();
52613			}
52614			/**
52615			 * triggered when all nodes are hidden
52616			 * @event
52617			 * @name hide_all.jstree
52618			 * @param {Array} nodes the IDs of all hidden nodes
52619			 */
52620			this.trigger('hide_all', { 'nodes' : ids });
52621			return ids;
52622		},
52623		/**
52624		 * shows all nodes
52625		 * @name show_all()
52626		 * @trigger show_all.jstree
52627		 */
52628		show_all : function (skip_redraw) {
52629			var i, m = this._model.data, ids = [];
52630			for(i in m) {
52631				if(m.hasOwnProperty(i) && i !== $.jstree.root && m[i].state.hidden) {
52632					m[i].state.hidden = false;
52633					ids.push(i);
52634				}
52635			}
52636			this._model.force_full_redraw = true;
52637			if(!skip_redraw) {
52638				this.redraw();
52639			}
52640			/**
52641			 * triggered when all nodes are shown
52642			 * @event
52643			 * @name show_all.jstree
52644			 * @param {Array} nodes the IDs of all shown nodes
52645			 */
52646			this.trigger('show_all', { 'nodes' : ids });
52647			return ids;
52648		},
52649		/**
52650		 * called when a node is selected by the user. Used internally.
52651		 * @private
52652		 * @name activate_node(obj, e)
52653		 * @param {mixed} obj the node
52654		 * @param {Object} e the related event
52655		 * @trigger activate_node.jstree, changed.jstree
52656		 */
52657		activate_node : function (obj, e) {
52658			if(this.is_disabled(obj)) {
52659				return false;
52660			}
52661			if(!e || typeof e !== 'object') {
52662				e = {};
52663			}
52664
52665			// ensure last_clicked is still in the DOM, make it fresh (maybe it was moved?) and make sure it is still selected, if not - make last_clicked the last selected node
52666			this._data.core.last_clicked = this._data.core.last_clicked && this._data.core.last_clicked.id !== undefined ? this.get_node(this._data.core.last_clicked.id) : null;
52667			if(this._data.core.last_clicked && !this._data.core.last_clicked.state.selected) { this._data.core.last_clicked = null; }
52668			if(!this._data.core.last_clicked && this._data.core.selected.length) { this._data.core.last_clicked = this.get_node(this._data.core.selected[this._data.core.selected.length - 1]); }
52669
52670			if(!this.settings.core.multiple || (!e.metaKey && !e.ctrlKey && !e.shiftKey) || (e.shiftKey && (!this._data.core.last_clicked || !this.get_parent(obj) || this.get_parent(obj) !== this._data.core.last_clicked.parent ) )) {
52671				if(!this.settings.core.multiple && (e.metaKey || e.ctrlKey || e.shiftKey) && this.is_selected(obj)) {
52672					this.deselect_node(obj, false, e);
52673				}
52674				else {
52675					this.deselect_all(true);
52676					this.select_node(obj, false, false, e);
52677					this._data.core.last_clicked = this.get_node(obj);
52678				}
52679			}
52680			else {
52681				if(e.shiftKey) {
52682					var o = this.get_node(obj).id,
52683						l = this._data.core.last_clicked.id,
52684						p = this.get_node(this._data.core.last_clicked.parent).children,
52685						c = false,
52686						i, j;
52687					for(i = 0, j = p.length; i < j; i += 1) {
52688						// separate IFs work whem o and l are the same
52689						if(p[i] === o) {
52690							c = !c;
52691						}
52692						if(p[i] === l) {
52693							c = !c;
52694						}
52695						if(!this.is_disabled(p[i]) && (c || p[i] === o || p[i] === l)) {
52696							if (!this.is_hidden(p[i])) {
52697								this.select_node(p[i], true, false, e);
52698							}
52699						}
52700						else {
52701							this.deselect_node(p[i], true, e);
52702						}
52703					}
52704					this.trigger('changed', { 'action' : 'select_node', 'node' : this.get_node(obj), 'selected' : this._data.core.selected, 'event' : e });
52705				}
52706				else {
52707					if(!this.is_selected(obj)) {
52708						this.select_node(obj, false, false, e);
52709					}
52710					else {
52711						this.deselect_node(obj, false, e);
52712					}
52713				}
52714			}
52715			/**
52716			 * triggered when an node is clicked or intercated with by the user
52717			 * @event
52718			 * @name activate_node.jstree
52719			 * @param {Object} node
52720			 * @param {Object} event the ooriginal event (if any) which triggered the call (may be an empty object)
52721			 */
52722			this.trigger('activate_node', { 'node' : this.get_node(obj), 'event' : e });
52723		},
52724		/**
52725		 * applies the hover state on a node, called when a node is hovered by the user. Used internally.
52726		 * @private
52727		 * @name hover_node(obj)
52728		 * @param {mixed} obj
52729		 * @trigger hover_node.jstree
52730		 */
52731		hover_node : function (obj) {
52732			obj = this.get_node(obj, true);
52733			if(!obj || !obj.length || obj.children('.jstree-hovered').length) {
52734				return false;
52735			}
52736			var o = this.element.find('.jstree-hovered'), t = this.element;
52737			if(o && o.length) { this.dehover_node(o); }
52738
52739			obj.children('.jstree-anchor').addClass('jstree-hovered');
52740			/**
52741			 * triggered when an node is hovered
52742			 * @event
52743			 * @name hover_node.jstree
52744			 * @param {Object} node
52745			 */
52746			this.trigger('hover_node', { 'node' : this.get_node(obj) });
52747			setTimeout(function () { t.attr('aria-activedescendant', obj[0].id); }, 0);
52748		},
52749		/**
52750		 * removes the hover state from a nodecalled when a node is no longer hovered by the user. Used internally.
52751		 * @private
52752		 * @name dehover_node(obj)
52753		 * @param {mixed} obj
52754		 * @trigger dehover_node.jstree
52755		 */
52756		dehover_node : function (obj) {
52757			obj = this.get_node(obj, true);
52758			if(!obj || !obj.length || !obj.children('.jstree-hovered').length) {
52759				return false;
52760			}
52761			obj.children('.jstree-anchor').removeClass('jstree-hovered');
52762			/**
52763			 * triggered when an node is no longer hovered
52764			 * @event
52765			 * @name dehover_node.jstree
52766			 * @param {Object} node
52767			 */
52768			this.trigger('dehover_node', { 'node' : this.get_node(obj) });
52769		},
52770		/**
52771		 * select a node
52772		 * @name select_node(obj [, supress_event, prevent_open])
52773		 * @param {mixed} obj an array can be used to select multiple nodes
52774		 * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered
52775		 * @param {Boolean} prevent_open if set to `true` parents of the selected node won't be opened
52776		 * @trigger select_node.jstree, changed.jstree
52777		 */
52778		select_node : function (obj, supress_event, prevent_open, e) {
52779			var dom, t1, t2, th;
52780			if($.isArray(obj)) {
52781				obj = obj.slice();
52782				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
52783					this.select_node(obj[t1], supress_event, prevent_open, e);
52784				}
52785				return true;
52786			}
52787			obj = this.get_node(obj);
52788			if(!obj || obj.id === $.jstree.root) {
52789				return false;
52790			}
52791			dom = this.get_node(obj, true);
52792			if(!obj.state.selected) {
52793				obj.state.selected = true;
52794				this._data.core.selected.push(obj.id);
52795				if(!prevent_open) {
52796					dom = this._open_to(obj);
52797				}
52798				if(dom && dom.length) {
52799					dom.attr('aria-selected', true).children('.jstree-anchor').addClass('jstree-clicked');
52800				}
52801				/**
52802				 * triggered when an node is selected
52803				 * @event
52804				 * @name select_node.jstree
52805				 * @param {Object} node
52806				 * @param {Array} selected the current selection
52807				 * @param {Object} event the event (if any) that triggered this select_node
52808				 */
52809				this.trigger('select_node', { 'node' : obj, 'selected' : this._data.core.selected, 'event' : e });
52810				if(!supress_event) {
52811					/**
52812					 * triggered when selection changes
52813					 * @event
52814					 * @name changed.jstree
52815					 * @param {Object} node
52816					 * @param {Object} action the action that caused the selection to change
52817					 * @param {Array} selected the current selection
52818					 * @param {Object} event the event (if any) that triggered this changed event
52819					 */
52820					this.trigger('changed', { 'action' : 'select_node', 'node' : obj, 'selected' : this._data.core.selected, 'event' : e });
52821				}
52822			}
52823		},
52824		/**
52825		 * deselect a node
52826		 * @name deselect_node(obj [, supress_event])
52827		 * @param {mixed} obj an array can be used to deselect multiple nodes
52828		 * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered
52829		 * @trigger deselect_node.jstree, changed.jstree
52830		 */
52831		deselect_node : function (obj, supress_event, e) {
52832			var t1, t2, dom;
52833			if($.isArray(obj)) {
52834				obj = obj.slice();
52835				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
52836					this.deselect_node(obj[t1], supress_event, e);
52837				}
52838				return true;
52839			}
52840			obj = this.get_node(obj);
52841			if(!obj || obj.id === $.jstree.root) {
52842				return false;
52843			}
52844			dom = this.get_node(obj, true);
52845			if(obj.state.selected) {
52846				obj.state.selected = false;
52847				this._data.core.selected = $.vakata.array_remove_item(this._data.core.selected, obj.id);
52848				if(dom.length) {
52849					dom.attr('aria-selected', false).children('.jstree-anchor').removeClass('jstree-clicked');
52850				}
52851				/**
52852				 * triggered when an node is deselected
52853				 * @event
52854				 * @name deselect_node.jstree
52855				 * @param {Object} node
52856				 * @param {Array} selected the current selection
52857				 * @param {Object} event the event (if any) that triggered this deselect_node
52858				 */
52859				this.trigger('deselect_node', { 'node' : obj, 'selected' : this._data.core.selected, 'event' : e });
52860				if(!supress_event) {
52861					this.trigger('changed', { 'action' : 'deselect_node', 'node' : obj, 'selected' : this._data.core.selected, 'event' : e });
52862				}
52863			}
52864		},
52865		/**
52866		 * select all nodes in the tree
52867		 * @name select_all([supress_event])
52868		 * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered
52869		 * @trigger select_all.jstree, changed.jstree
52870		 */
52871		select_all : function (supress_event) {
52872			var tmp = this._data.core.selected.concat([]), i, j;
52873			this._data.core.selected = this._model.data[$.jstree.root].children_d.concat();
52874			for(i = 0, j = this._data.core.selected.length; i < j; i++) {
52875				if(this._model.data[this._data.core.selected[i]]) {
52876					this._model.data[this._data.core.selected[i]].state.selected = true;
52877				}
52878			}
52879			this.redraw(true);
52880			/**
52881			 * triggered when all nodes are selected
52882			 * @event
52883			 * @name select_all.jstree
52884			 * @param {Array} selected the current selection
52885			 */
52886			this.trigger('select_all', { 'selected' : this._data.core.selected });
52887			if(!supress_event) {
52888				this.trigger('changed', { 'action' : 'select_all', 'selected' : this._data.core.selected, 'old_selection' : tmp });
52889			}
52890		},
52891		/**
52892		 * deselect all selected nodes
52893		 * @name deselect_all([supress_event])
52894		 * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered
52895		 * @trigger deselect_all.jstree, changed.jstree
52896		 */
52897		deselect_all : function (supress_event) {
52898			var tmp = this._data.core.selected.concat([]), i, j;
52899			for(i = 0, j = this._data.core.selected.length; i < j; i++) {
52900				if(this._model.data[this._data.core.selected[i]]) {
52901					this._model.data[this._data.core.selected[i]].state.selected = false;
52902				}
52903			}
52904			this._data.core.selected = [];
52905			this.element.find('.jstree-clicked').removeClass('jstree-clicked').parent().attr('aria-selected', false);
52906			/**
52907			 * triggered when all nodes are deselected
52908			 * @event
52909			 * @name deselect_all.jstree
52910			 * @param {Object} node the previous selection
52911			 * @param {Array} selected the current selection
52912			 */
52913			this.trigger('deselect_all', { 'selected' : this._data.core.selected, 'node' : tmp });
52914			if(!supress_event) {
52915				this.trigger('changed', { 'action' : 'deselect_all', 'selected' : this._data.core.selected, 'old_selection' : tmp });
52916			}
52917		},
52918		/**
52919		 * checks if a node is selected
52920		 * @name is_selected(obj)
52921		 * @param  {mixed}  obj
52922		 * @return {Boolean}
52923		 */
52924		is_selected : function (obj) {
52925			obj = this.get_node(obj);
52926			if(!obj || obj.id === $.jstree.root) {
52927				return false;
52928			}
52929			return obj.state.selected;
52930		},
52931		/**
52932		 * get an array of all selected nodes
52933		 * @name get_selected([full])
52934		 * @param  {mixed}  full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned
52935		 * @return {Array}
52936		 */
52937		get_selected : function (full) {
52938			return full ? $.map(this._data.core.selected, $.proxy(function (i) { return this.get_node(i); }, this)) : this._data.core.selected.slice();
52939		},
52940		/**
52941		 * get an array of all top level selected nodes (ignoring children of selected nodes)
52942		 * @name get_top_selected([full])
52943		 * @param  {mixed}  full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned
52944		 * @return {Array}
52945		 */
52946		get_top_selected : function (full) {
52947			var tmp = this.get_selected(true),
52948				obj = {}, i, j, k, l;
52949			for(i = 0, j = tmp.length; i < j; i++) {
52950				obj[tmp[i].id] = tmp[i];
52951			}
52952			for(i = 0, j = tmp.length; i < j; i++) {
52953				for(k = 0, l = tmp[i].children_d.length; k < l; k++) {
52954					if(obj[tmp[i].children_d[k]]) {
52955						delete obj[tmp[i].children_d[k]];
52956					}
52957				}
52958			}
52959			tmp = [];
52960			for(i in obj) {
52961				if(obj.hasOwnProperty(i)) {
52962					tmp.push(i);
52963				}
52964			}
52965			return full ? $.map(tmp, $.proxy(function (i) { return this.get_node(i); }, this)) : tmp;
52966		},
52967		/**
52968		 * get an array of all bottom level selected nodes (ignoring selected parents)
52969		 * @name get_bottom_selected([full])
52970		 * @param  {mixed}  full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned
52971		 * @return {Array}
52972		 */
52973		get_bottom_selected : function (full) {
52974			var tmp = this.get_selected(true),
52975				obj = [], i, j;
52976			for(i = 0, j = tmp.length; i < j; i++) {
52977				if(!tmp[i].children.length) {
52978					obj.push(tmp[i].id);
52979				}
52980			}
52981			return full ? $.map(obj, $.proxy(function (i) { return this.get_node(i); }, this)) : obj;
52982		},
52983		/**
52984		 * gets the current state of the tree so that it can be restored later with `set_state(state)`. Used internally.
52985		 * @name get_state()
52986		 * @private
52987		 * @return {Object}
52988		 */
52989		get_state : function () {
52990			var state	= {
52991				'core' : {
52992					'open' : [],
52993					'loaded' : [],
52994					'scroll' : {
52995						'left' : this.element.scrollLeft(),
52996						'top' : this.element.scrollTop()
52997					},
52998					/*!
52999					'themes' : {
53000						'name' : this.get_theme(),
53001						'icons' : this._data.core.themes.icons,
53002						'dots' : this._data.core.themes.dots
53003					},
53004					*/
53005					'selected' : []
53006				}
53007			}, i;
53008			for(i in this._model.data) {
53009				if(this._model.data.hasOwnProperty(i)) {
53010					if(i !== $.jstree.root) {
53011						if(this._model.data[i].state.loaded && this.settings.core.loaded_state) {
53012							state.core.loaded.push(i);
53013						}
53014						if(this._model.data[i].state.opened) {
53015							state.core.open.push(i);
53016						}
53017						if(this._model.data[i].state.selected) {
53018							state.core.selected.push(i);
53019						}
53020					}
53021				}
53022			}
53023			return state;
53024		},
53025		/**
53026		 * sets the state of the tree. Used internally.
53027		 * @name set_state(state [, callback])
53028		 * @private
53029		 * @param {Object} state the state to restore. Keep in mind this object is passed by reference and jstree will modify it.
53030		 * @param {Function} callback an optional function to execute once the state is restored.
53031		 * @trigger set_state.jstree
53032		 */
53033		set_state : function (state, callback) {
53034			if(state) {
53035				if(state.core && state.core.selected && state.core.initial_selection === undefined) {
53036					state.core.initial_selection = this._data.core.selected.concat([]).sort().join(',');
53037				}
53038				if(state.core) {
53039					var res, n, t, _this, i;
53040					if(state.core.loaded) {
53041						if(!this.settings.core.loaded_state || !$.isArray(state.core.loaded) || !state.core.loaded.length) {
53042							delete state.core.loaded;
53043							this.set_state(state, callback);
53044						}
53045						else {
53046							this._load_nodes(state.core.loaded, function (nodes) {
53047								delete state.core.loaded;
53048								this.set_state(state, callback);
53049							});
53050						}
53051						return false;
53052					}
53053					if(state.core.open) {
53054						if(!$.isArray(state.core.open) || !state.core.open.length) {
53055							delete state.core.open;
53056							this.set_state(state, callback);
53057						}
53058						else {
53059							this._load_nodes(state.core.open, function (nodes) {
53060								this.open_node(nodes, false, 0);
53061								delete state.core.open;
53062								this.set_state(state, callback);
53063							});
53064						}
53065						return false;
53066					}
53067					if(state.core.scroll) {
53068						if(state.core.scroll && state.core.scroll.left !== undefined) {
53069							this.element.scrollLeft(state.core.scroll.left);
53070						}
53071						if(state.core.scroll && state.core.scroll.top !== undefined) {
53072							this.element.scrollTop(state.core.scroll.top);
53073						}
53074						delete state.core.scroll;
53075						this.set_state(state, callback);
53076						return false;
53077					}
53078					if(state.core.selected) {
53079						_this = this;
53080						if (state.core.initial_selection === undefined ||
53081							state.core.initial_selection === this._data.core.selected.concat([]).sort().join(',')
53082						) {
53083							this.deselect_all();
53084							$.each(state.core.selected, function (i, v) {
53085								_this.select_node(v, false, true);
53086							});
53087						}
53088						delete state.core.initial_selection;
53089						delete state.core.selected;
53090						this.set_state(state, callback);
53091						return false;
53092					}
53093					for(i in state) {
53094						if(state.hasOwnProperty(i) && i !== "core" && $.inArray(i, this.settings.plugins) === -1) {
53095							delete state[i];
53096						}
53097					}
53098					if($.isEmptyObject(state.core)) {
53099						delete state.core;
53100						this.set_state(state, callback);
53101						return false;
53102					}
53103				}
53104				if($.isEmptyObject(state)) {
53105					state = null;
53106					if(callback) { callback.call(this); }
53107					/**
53108					 * triggered when a `set_state` call completes
53109					 * @event
53110					 * @name set_state.jstree
53111					 */
53112					this.trigger('set_state');
53113					return false;
53114				}
53115				return true;
53116			}
53117			return false;
53118		},
53119		/**
53120		 * refreshes the tree - all nodes are reloaded with calls to `load_node`.
53121		 * @name refresh()
53122		 * @param {Boolean} skip_loading an option to skip showing the loading indicator
53123		 * @param {Mixed} forget_state if set to `true` state will not be reapplied, if set to a function (receiving the current state as argument) the result of that function will be used as state
53124		 * @trigger refresh.jstree
53125		 */
53126		refresh : function (skip_loading, forget_state) {
53127			this._data.core.state = forget_state === true ? {} : this.get_state();
53128			if(forget_state && $.isFunction(forget_state)) { this._data.core.state = forget_state.call(this, this._data.core.state); }
53129			this._cnt = 0;
53130			this._model.data = {};
53131			this._model.data[$.jstree.root] = {
53132				id : $.jstree.root,
53133				parent : null,
53134				parents : [],
53135				children : [],
53136				children_d : [],
53137				state : { loaded : false }
53138			};
53139			this._data.core.selected = [];
53140			this._data.core.last_clicked = null;
53141			this._data.core.focused = null;
53142
53143			var c = this.get_container_ul()[0].className;
53144			if(!skip_loading) {
53145				this.element.html("<"+"ul class='"+c+"' role='group'><"+"li class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='treeitem' id='j"+this._id+"_loading'><i class='jstree-icon jstree-ocl'></i><"+"a class='jstree-anchor' href='#'><i class='jstree-icon jstree-themeicon-hidden'></i>" + this.get_string("Loading ...") + "</a></li></ul>");
53146				this.element.attr('aria-activedescendant','j'+this._id+'_loading');
53147			}
53148			this.load_node($.jstree.root, function (o, s) {
53149				if(s) {
53150					this.get_container_ul()[0].className = c;
53151					if(this._firstChild(this.get_container_ul()[0])) {
53152						this.element.attr('aria-activedescendant',this._firstChild(this.get_container_ul()[0]).id);
53153					}
53154					this.set_state($.extend(true, {}, this._data.core.state), function () {
53155						/**
53156						 * triggered when a `refresh` call completes
53157						 * @event
53158						 * @name refresh.jstree
53159						 */
53160						this.trigger('refresh');
53161					});
53162				}
53163				this._data.core.state = null;
53164			});
53165		},
53166		/**
53167		 * refreshes a node in the tree (reload its children) all opened nodes inside that node are reloaded with calls to `load_node`.
53168		 * @name refresh_node(obj)
53169		 * @param  {mixed} obj the node
53170		 * @trigger refresh_node.jstree
53171		 */
53172		refresh_node : function (obj) {
53173			obj = this.get_node(obj);
53174			if(!obj || obj.id === $.jstree.root) { return false; }
53175			var opened = [], to_load = [], s = this._data.core.selected.concat([]);
53176			to_load.push(obj.id);
53177			if(obj.state.opened === true) { opened.push(obj.id); }
53178			this.get_node(obj, true).find('.jstree-open').each(function() { to_load.push(this.id); opened.push(this.id); });
53179			this._load_nodes(to_load, $.proxy(function (nodes) {
53180				this.open_node(opened, false, 0);
53181				this.select_node(s);
53182				/**
53183				 * triggered when a node is refreshed
53184				 * @event
53185				 * @name refresh_node.jstree
53186				 * @param {Object} node - the refreshed node
53187				 * @param {Array} nodes - an array of the IDs of the nodes that were reloaded
53188				 */
53189				this.trigger('refresh_node', { 'node' : obj, 'nodes' : nodes });
53190			}, this), false, true);
53191		},
53192		/**
53193		 * set (change) the ID of a node
53194		 * @name set_id(obj, id)
53195		 * @param  {mixed} obj the node
53196		 * @param  {String} id the new ID
53197		 * @return {Boolean}
53198		 * @trigger set_id.jstree
53199		 */
53200		set_id : function (obj, id) {
53201			obj = this.get_node(obj);
53202			if(!obj || obj.id === $.jstree.root) { return false; }
53203			var i, j, m = this._model.data, old = obj.id;
53204			id = id.toString();
53205			// update parents (replace current ID with new one in children and children_d)
53206			m[obj.parent].children[$.inArray(obj.id, m[obj.parent].children)] = id;
53207			for(i = 0, j = obj.parents.length; i < j; i++) {
53208				m[obj.parents[i]].children_d[$.inArray(obj.id, m[obj.parents[i]].children_d)] = id;
53209			}
53210			// update children (replace current ID with new one in parent and parents)
53211			for(i = 0, j = obj.children.length; i < j; i++) {
53212				m[obj.children[i]].parent = id;
53213			}
53214			for(i = 0, j = obj.children_d.length; i < j; i++) {
53215				m[obj.children_d[i]].parents[$.inArray(obj.id, m[obj.children_d[i]].parents)] = id;
53216			}
53217			i = $.inArray(obj.id, this._data.core.selected);
53218			if(i !== -1) { this._data.core.selected[i] = id; }
53219			// update model and obj itself (obj.id, this._model.data[KEY])
53220			i = this.get_node(obj.id, true);
53221			if(i) {
53222				i.attr('id', id); //.children('.jstree-anchor').attr('id', id + '_anchor').end().attr('aria-labelledby', id + '_anchor');
53223				if(this.element.attr('aria-activedescendant') === obj.id) {
53224					this.element.attr('aria-activedescendant', id);
53225				}
53226			}
53227			delete m[obj.id];
53228			obj.id = id;
53229			obj.li_attr.id = id;
53230			m[id] = obj;
53231			/**
53232			 * triggered when a node id value is changed
53233			 * @event
53234			 * @name set_id.jstree
53235			 * @param {Object} node
53236			 * @param {String} old the old id
53237			 */
53238			this.trigger('set_id',{ "node" : obj, "new" : obj.id, "old" : old });
53239			return true;
53240		},
53241		/**
53242		 * get the text value of a node
53243		 * @name get_text(obj)
53244		 * @param  {mixed} obj the node
53245		 * @return {String}
53246		 */
53247		get_text : function (obj) {
53248			obj = this.get_node(obj);
53249			return (!obj || obj.id === $.jstree.root) ? false : obj.text;
53250		},
53251		/**
53252		 * set the text value of a node. Used internally, please use `rename_node(obj, val)`.
53253		 * @private
53254		 * @name set_text(obj, val)
53255		 * @param  {mixed} obj the node, you can pass an array to set the text on multiple nodes
53256		 * @param  {String} val the new text value
53257		 * @return {Boolean}
53258		 * @trigger set_text.jstree
53259		 */
53260		set_text : function (obj, val) {
53261			var t1, t2;
53262			if($.isArray(obj)) {
53263				obj = obj.slice();
53264				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
53265					this.set_text(obj[t1], val);
53266				}
53267				return true;
53268			}
53269			obj = this.get_node(obj);
53270			if(!obj || obj.id === $.jstree.root) { return false; }
53271			obj.text = val;
53272			if(this.get_node(obj, true).length) {
53273				this.redraw_node(obj.id);
53274			}
53275			/**
53276			 * triggered when a node text value is changed
53277			 * @event
53278			 * @name set_text.jstree
53279			 * @param {Object} obj
53280			 * @param {String} text the new value
53281			 */
53282			this.trigger('set_text',{ "obj" : obj, "text" : val });
53283			return true;
53284		},
53285		/**
53286		 * gets a JSON representation of a node (or the whole tree)
53287		 * @name get_json([obj, options])
53288		 * @param  {mixed} obj
53289		 * @param  {Object} options
53290		 * @param  {Boolean} options.no_state do not return state information
53291		 * @param  {Boolean} options.no_id do not return ID
53292		 * @param  {Boolean} options.no_children do not include children
53293		 * @param  {Boolean} options.no_data do not include node data
53294		 * @param  {Boolean} options.no_li_attr do not include LI attributes
53295		 * @param  {Boolean} options.no_a_attr do not include A attributes
53296		 * @param  {Boolean} options.flat return flat JSON instead of nested
53297		 * @return {Object}
53298		 */
53299		get_json : function (obj, options, flat) {
53300			obj = this.get_node(obj || $.jstree.root);
53301			if(!obj) { return false; }
53302			if(options && options.flat && !flat) { flat = []; }
53303			var tmp = {
53304				'id' : obj.id,
53305				'text' : obj.text,
53306				'icon' : this.get_icon(obj),
53307				'li_attr' : $.extend(true, {}, obj.li_attr),
53308				'a_attr' : $.extend(true, {}, obj.a_attr),
53309				'state' : {},
53310				'data' : options && options.no_data ? false : $.extend(true, $.isArray(obj.data)?[]:{}, obj.data)
53311				//( this.get_node(obj, true).length ? this.get_node(obj, true).data() : obj.data ),
53312			}, i, j;
53313			if(options && options.flat) {
53314				tmp.parent = obj.parent;
53315			}
53316			else {
53317				tmp.children = [];
53318			}
53319			if(!options || !options.no_state) {
53320				for(i in obj.state) {
53321					if(obj.state.hasOwnProperty(i)) {
53322						tmp.state[i] = obj.state[i];
53323					}
53324				}
53325			} else {
53326				delete tmp.state;
53327			}
53328			if(options && options.no_li_attr) {
53329				delete tmp.li_attr;
53330			}
53331			if(options && options.no_a_attr) {
53332				delete tmp.a_attr;
53333			}
53334			if(options && options.no_id) {
53335				delete tmp.id;
53336				if(tmp.li_attr && tmp.li_attr.id) {
53337					delete tmp.li_attr.id;
53338				}
53339				if(tmp.a_attr && tmp.a_attr.id) {
53340					delete tmp.a_attr.id;
53341				}
53342			}
53343			if(options && options.flat && obj.id !== $.jstree.root) {
53344				flat.push(tmp);
53345			}
53346			if(!options || !options.no_children) {
53347				for(i = 0, j = obj.children.length; i < j; i++) {
53348					if(options && options.flat) {
53349						this.get_json(obj.children[i], options, flat);
53350					}
53351					else {
53352						tmp.children.push(this.get_json(obj.children[i], options));
53353					}
53354				}
53355			}
53356			return options && options.flat ? flat : (obj.id === $.jstree.root ? tmp.children : tmp);
53357		},
53358		/**
53359		 * create a new node (do not confuse with load_node)
53360		 * @name create_node([par, node, pos, callback, is_loaded])
53361		 * @param  {mixed}   par       the parent node (to create a root node use either "#" (string) or `null`)
53362		 * @param  {mixed}   node      the data for the new node (a valid JSON object, or a simple string with the name)
53363		 * @param  {mixed}   pos       the index at which to insert the node, "first" and "last" are also supported, default is "last"
53364		 * @param  {Function} callback a function to be called once the node is created
53365		 * @param  {Boolean} is_loaded internal argument indicating if the parent node was succesfully loaded
53366		 * @return {String}            the ID of the newly create node
53367		 * @trigger model.jstree, create_node.jstree
53368		 */
53369		create_node : function (par, node, pos, callback, is_loaded) {
53370			if(par === null) { par = $.jstree.root; }
53371			par = this.get_node(par);
53372			if(!par) { return false; }
53373			pos = pos === undefined ? "last" : pos;
53374			if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) {
53375				return this.load_node(par, function () { this.create_node(par, node, pos, callback, true); });
53376			}
53377			if(!node) { node = { "text" : this.get_string('New node') }; }
53378			if(typeof node === "string") {
53379				node = { "text" : node };
53380			} else {
53381				node = $.extend(true, {}, node);
53382			}
53383			if(node.text === undefined) { node.text = this.get_string('New node'); }
53384			var tmp, dpc, i, j;
53385
53386			if(par.id === $.jstree.root) {
53387				if(pos === "before") { pos = "first"; }
53388				if(pos === "after") { pos = "last"; }
53389			}
53390			switch(pos) {
53391				case "before":
53392					tmp = this.get_node(par.parent);
53393					pos = $.inArray(par.id, tmp.children);
53394					par = tmp;
53395					break;
53396				case "after" :
53397					tmp = this.get_node(par.parent);
53398					pos = $.inArray(par.id, tmp.children) + 1;
53399					par = tmp;
53400					break;
53401				case "inside":
53402				case "first":
53403					pos = 0;
53404					break;
53405				case "last":
53406					pos = par.children.length;
53407					break;
53408				default:
53409					if(!pos) { pos = 0; }
53410					break;
53411			}
53412			if(pos > par.children.length) { pos = par.children.length; }
53413			if(!node.id) { node.id = true; }
53414			if(!this.check("create_node", node, par, pos)) {
53415				this.settings.core.error.call(this, this._data.core.last_error);
53416				return false;
53417			}
53418			if(node.id === true) { delete node.id; }
53419			node = this._parse_model_from_json(node, par.id, par.parents.concat());
53420			if(!node) { return false; }
53421			tmp = this.get_node(node);
53422			dpc = [];
53423			dpc.push(node);
53424			dpc = dpc.concat(tmp.children_d);
53425			this.trigger('model', { "nodes" : dpc, "parent" : par.id });
53426
53427			par.children_d = par.children_d.concat(dpc);
53428			for(i = 0, j = par.parents.length; i < j; i++) {
53429				this._model.data[par.parents[i]].children_d = this._model.data[par.parents[i]].children_d.concat(dpc);
53430			}
53431			node = tmp;
53432			tmp = [];
53433			for(i = 0, j = par.children.length; i < j; i++) {
53434				tmp[i >= pos ? i+1 : i] = par.children[i];
53435			}
53436			tmp[pos] = node.id;
53437			par.children = tmp;
53438
53439			this.redraw_node(par, true);
53440			/**
53441			 * triggered when a node is created
53442			 * @event
53443			 * @name create_node.jstree
53444			 * @param {Object} node
53445			 * @param {String} parent the parent's ID
53446			 * @param {Number} position the position of the new node among the parent's children
53447			 */
53448			this.trigger('create_node', { "node" : this.get_node(node), "parent" : par.id, "position" : pos });
53449			if(callback) { callback.call(this, this.get_node(node)); }
53450			return node.id;
53451		},
53452		/**
53453		 * set the text value of a node
53454		 * @name rename_node(obj, val)
53455		 * @param  {mixed} obj the node, you can pass an array to rename multiple nodes to the same name
53456		 * @param  {String} val the new text value
53457		 * @return {Boolean}
53458		 * @trigger rename_node.jstree
53459		 */
53460		rename_node : function (obj, val) {
53461			var t1, t2, old;
53462			if($.isArray(obj)) {
53463				obj = obj.slice();
53464				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
53465					this.rename_node(obj[t1], val);
53466				}
53467				return true;
53468			}
53469			obj = this.get_node(obj);
53470			if(!obj || obj.id === $.jstree.root) { return false; }
53471			old = obj.text;
53472			if(!this.check("rename_node", obj, this.get_parent(obj), val)) {
53473				this.settings.core.error.call(this, this._data.core.last_error);
53474				return false;
53475			}
53476			this.set_text(obj, val); // .apply(this, Array.prototype.slice.call(arguments))
53477			/**
53478			 * triggered when a node is renamed
53479			 * @event
53480			 * @name rename_node.jstree
53481			 * @param {Object} node
53482			 * @param {String} text the new value
53483			 * @param {String} old the old value
53484			 */
53485			this.trigger('rename_node', { "node" : obj, "text" : val, "old" : old });
53486			return true;
53487		},
53488		/**
53489		 * remove a node
53490		 * @name delete_node(obj)
53491		 * @param  {mixed} obj the node, you can pass an array to delete multiple nodes
53492		 * @return {Boolean}
53493		 * @trigger delete_node.jstree, changed.jstree
53494		 */
53495		delete_node : function (obj) {
53496			var t1, t2, par, pos, tmp, i, j, k, l, c, top, lft;
53497			if($.isArray(obj)) {
53498				obj = obj.slice();
53499				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
53500					this.delete_node(obj[t1]);
53501				}
53502				return true;
53503			}
53504			obj = this.get_node(obj);
53505			if(!obj || obj.id === $.jstree.root) { return false; }
53506			par = this.get_node(obj.parent);
53507			pos = $.inArray(obj.id, par.children);
53508			c = false;
53509			if(!this.check("delete_node", obj, par, pos)) {
53510				this.settings.core.error.call(this, this._data.core.last_error);
53511				return false;
53512			}
53513			if(pos !== -1) {
53514				par.children = $.vakata.array_remove(par.children, pos);
53515			}
53516			tmp = obj.children_d.concat([]);
53517			tmp.push(obj.id);
53518			for(i = 0, j = obj.parents.length; i < j; i++) {
53519				this._model.data[obj.parents[i]].children_d = $.vakata.array_filter(this._model.data[obj.parents[i]].children_d, function (v) {
53520					return $.inArray(v, tmp) === -1;
53521				});
53522			}
53523			for(k = 0, l = tmp.length; k < l; k++) {
53524				if(this._model.data[tmp[k]].state.selected) {
53525					c = true;
53526					break;
53527				}
53528			}
53529			if (c) {
53530				this._data.core.selected = $.vakata.array_filter(this._data.core.selected, function (v) {
53531					return $.inArray(v, tmp) === -1;
53532				});
53533			}
53534			/**
53535			 * triggered when a node is deleted
53536			 * @event
53537			 * @name delete_node.jstree
53538			 * @param {Object} node
53539			 * @param {String} parent the parent's ID
53540			 */
53541			this.trigger('delete_node', { "node" : obj, "parent" : par.id });
53542			if(c) {
53543				this.trigger('changed', { 'action' : 'delete_node', 'node' : obj, 'selected' : this._data.core.selected, 'parent' : par.id });
53544			}
53545			for(k = 0, l = tmp.length; k < l; k++) {
53546				delete this._model.data[tmp[k]];
53547			}
53548			if($.inArray(this._data.core.focused, tmp) !== -1) {
53549				this._data.core.focused = null;
53550				top = this.element[0].scrollTop;
53551				lft = this.element[0].scrollLeft;
53552				if(par.id === $.jstree.root) {
53553					if (this._model.data[$.jstree.root].children[0]) {
53554						this.get_node(this._model.data[$.jstree.root].children[0], true).children('.jstree-anchor').focus();
53555					}
53556				}
53557				else {
53558					this.get_node(par, true).children('.jstree-anchor').focus();
53559				}
53560				this.element[0].scrollTop  = top;
53561				this.element[0].scrollLeft = lft;
53562			}
53563			this.redraw_node(par, true);
53564			return true;
53565		},
53566		/**
53567		 * check if an operation is premitted on the tree. Used internally.
53568		 * @private
53569		 * @name check(chk, obj, par, pos)
53570		 * @param  {String} chk the operation to check, can be "create_node", "rename_node", "delete_node", "copy_node" or "move_node"
53571		 * @param  {mixed} obj the node
53572		 * @param  {mixed} par the parent
53573		 * @param  {mixed} pos the position to insert at, or if "rename_node" - the new name
53574		 * @param  {mixed} more some various additional information, for example if a "move_node" operations is triggered by DND this will be the hovered node
53575		 * @return {Boolean}
53576		 */
53577		check : function (chk, obj, par, pos, more) {
53578			obj = obj && obj.id ? obj : this.get_node(obj);
53579			par = par && par.id ? par : this.get_node(par);
53580			var tmp = chk.match(/^move_node|copy_node|create_node$/i) ? par : obj,
53581				chc = this.settings.core.check_callback;
53582			if(chk === "move_node" || chk === "copy_node") {
53583				if((!more || !more.is_multi) && (obj.id === par.id || (chk === "move_node" && $.inArray(obj.id, par.children) === pos) || $.inArray(par.id, obj.children_d) !== -1)) {
53584					this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_01', 'reason' : 'Moving parent inside child', 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
53585					return false;
53586				}
53587			}
53588			if(tmp && tmp.data) { tmp = tmp.data; }
53589			if(tmp && tmp.functions && (tmp.functions[chk] === false || tmp.functions[chk] === true)) {
53590				if(tmp.functions[chk] === false) {
53591					this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_02', 'reason' : 'Node data prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
53592				}
53593				return tmp.functions[chk];
53594			}
53595			if(chc === false || ($.isFunction(chc) && chc.call(this, chk, obj, par, pos, more) === false) || (chc && chc[chk] === false)) {
53596				this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_03', 'reason' : 'User config for core.check_callback prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
53597				return false;
53598			}
53599			return true;
53600		},
53601		/**
53602		 * get the last error
53603		 * @name last_error()
53604		 * @return {Object}
53605		 */
53606		last_error : function () {
53607			return this._data.core.last_error;
53608		},
53609		/**
53610		 * move a node to a new parent
53611		 * @name move_node(obj, par [, pos, callback, is_loaded])
53612		 * @param  {mixed} obj the node to move, pass an array to move multiple nodes
53613		 * @param  {mixed} par the new parent
53614		 * @param  {mixed} pos the position to insert at (besides integer values, "first" and "last" are supported, as well as "before" and "after"), defaults to integer `0`
53615		 * @param  {function} callback a function to call once the move is completed, receives 3 arguments - the node, the new parent and the position
53616		 * @param  {Boolean} is_loaded internal parameter indicating if the parent node has been loaded
53617		 * @param  {Boolean} skip_redraw internal parameter indicating if the tree should be redrawn
53618		 * @param  {Boolean} instance internal parameter indicating if the node comes from another instance
53619		 * @trigger move_node.jstree
53620		 */
53621		move_node : function (obj, par, pos, callback, is_loaded, skip_redraw, origin) {
53622			var t1, t2, old_par, old_pos, new_par, old_ins, is_multi, dpc, tmp, i, j, k, l, p;
53623
53624			par = this.get_node(par);
53625			pos = pos === undefined ? 0 : pos;
53626			if(!par) { return false; }
53627			if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) {
53628				return this.load_node(par, function () { this.move_node(obj, par, pos, callback, true, false, origin); });
53629			}
53630
53631			if($.isArray(obj)) {
53632				if(obj.length === 1) {
53633					obj = obj[0];
53634				}
53635				else {
53636					//obj = obj.slice();
53637					for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
53638						if((tmp = this.move_node(obj[t1], par, pos, callback, is_loaded, false, origin))) {
53639							par = tmp;
53640							pos = "after";
53641						}
53642					}
53643					this.redraw();
53644					return true;
53645				}
53646			}
53647			obj = obj && obj.id ? obj : this.get_node(obj);
53648
53649			if(!obj || obj.id === $.jstree.root) { return false; }
53650
53651			old_par = (obj.parent || $.jstree.root).toString();
53652			new_par = (!pos.toString().match(/^(before|after)$/) || par.id === $.jstree.root) ? par : this.get_node(par.parent);
53653			old_ins = origin ? origin : (this._model.data[obj.id] ? this : $.jstree.reference(obj.id));
53654			is_multi = !old_ins || !old_ins._id || (this._id !== old_ins._id);
53655			old_pos = old_ins && old_ins._id && old_par && old_ins._model.data[old_par] && old_ins._model.data[old_par].children ? $.inArray(obj.id, old_ins._model.data[old_par].children) : -1;
53656			if(old_ins && old_ins._id) {
53657				obj = old_ins._model.data[obj.id];
53658			}
53659
53660			if(is_multi) {
53661				if((tmp = this.copy_node(obj, par, pos, callback, is_loaded, false, origin))) {
53662					if(old_ins) { old_ins.delete_node(obj); }
53663					return tmp;
53664				}
53665				return false;
53666			}
53667			//var m = this._model.data;
53668			if(par.id === $.jstree.root) {
53669				if(pos === "before") { pos = "first"; }
53670				if(pos === "after") { pos = "last"; }
53671			}
53672			switch(pos) {
53673				case "before":
53674					pos = $.inArray(par.id, new_par.children);
53675					break;
53676				case "after" :
53677					pos = $.inArray(par.id, new_par.children) + 1;
53678					break;
53679				case "inside":
53680				case "first":
53681					pos = 0;
53682					break;
53683				case "last":
53684					pos = new_par.children.length;
53685					break;
53686				default:
53687					if(!pos) { pos = 0; }
53688					break;
53689			}
53690			if(pos > new_par.children.length) { pos = new_par.children.length; }
53691			if(!this.check("move_node", obj, new_par, pos, { 'core' : true, 'origin' : origin, 'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id) })) {
53692				this.settings.core.error.call(this, this._data.core.last_error);
53693				return false;
53694			}
53695			if(obj.parent === new_par.id) {
53696				dpc = new_par.children.concat();
53697				tmp = $.inArray(obj.id, dpc);
53698				if(tmp !== -1) {
53699					dpc = $.vakata.array_remove(dpc, tmp);
53700					if(pos > tmp) { pos--; }
53701				}
53702				tmp = [];
53703				for(i = 0, j = dpc.length; i < j; i++) {
53704					tmp[i >= pos ? i+1 : i] = dpc[i];
53705				}
53706				tmp[pos] = obj.id;
53707				new_par.children = tmp;
53708				this._node_changed(new_par.id);
53709				this.redraw(new_par.id === $.jstree.root);
53710			}
53711			else {
53712				// clean old parent and up
53713				tmp = obj.children_d.concat();
53714				tmp.push(obj.id);
53715				for(i = 0, j = obj.parents.length; i < j; i++) {
53716					dpc = [];
53717					p = old_ins._model.data[obj.parents[i]].children_d;
53718					for(k = 0, l = p.length; k < l; k++) {
53719						if($.inArray(p[k], tmp) === -1) {
53720							dpc.push(p[k]);
53721						}
53722					}
53723					old_ins._model.data[obj.parents[i]].children_d = dpc;
53724				}
53725				old_ins._model.data[old_par].children = $.vakata.array_remove_item(old_ins._model.data[old_par].children, obj.id);
53726
53727				// insert into new parent and up
53728				for(i = 0, j = new_par.parents.length; i < j; i++) {
53729					this._model.data[new_par.parents[i]].children_d = this._model.data[new_par.parents[i]].children_d.concat(tmp);
53730				}
53731				dpc = [];
53732				for(i = 0, j = new_par.children.length; i < j; i++) {
53733					dpc[i >= pos ? i+1 : i] = new_par.children[i];
53734				}
53735				dpc[pos] = obj.id;
53736				new_par.children = dpc;
53737				new_par.children_d.push(obj.id);
53738				new_par.children_d = new_par.children_d.concat(obj.children_d);
53739
53740				// update object
53741				obj.parent = new_par.id;
53742				tmp = new_par.parents.concat();
53743				tmp.unshift(new_par.id);
53744				p = obj.parents.length;
53745				obj.parents = tmp;
53746
53747				// update object children
53748				tmp = tmp.concat();
53749				for(i = 0, j = obj.children_d.length; i < j; i++) {
53750					this._model.data[obj.children_d[i]].parents = this._model.data[obj.children_d[i]].parents.slice(0,p*-1);
53751					Array.prototype.push.apply(this._model.data[obj.children_d[i]].parents, tmp);
53752				}
53753
53754				if(old_par === $.jstree.root || new_par.id === $.jstree.root) {
53755					this._model.force_full_redraw = true;
53756				}
53757				if(!this._model.force_full_redraw) {
53758					this._node_changed(old_par);
53759					this._node_changed(new_par.id);
53760				}
53761				if(!skip_redraw) {
53762					this.redraw();
53763				}
53764			}
53765			if(callback) { callback.call(this, obj, new_par, pos); }
53766			/**
53767			 * triggered when a node is moved
53768			 * @event
53769			 * @name move_node.jstree
53770			 * @param {Object} node
53771			 * @param {String} parent the parent's ID
53772			 * @param {Number} position the position of the node among the parent's children
53773			 * @param {String} old_parent the old parent of the node
53774			 * @param {Number} old_position the old position of the node
53775			 * @param {Boolean} is_multi do the node and new parent belong to different instances
53776			 * @param {jsTree} old_instance the instance the node came from
53777			 * @param {jsTree} new_instance the instance of the new parent
53778			 */
53779			this.trigger('move_node', { "node" : obj, "parent" : new_par.id, "position" : pos, "old_parent" : old_par, "old_position" : old_pos, 'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id), 'old_instance' : old_ins, 'new_instance' : this });
53780			return obj.id;
53781		},
53782		/**
53783		 * copy a node to a new parent
53784		 * @name copy_node(obj, par [, pos, callback, is_loaded])
53785		 * @param  {mixed} obj the node to copy, pass an array to copy multiple nodes
53786		 * @param  {mixed} par the new parent
53787		 * @param  {mixed} pos the position to insert at (besides integer values, "first" and "last" are supported, as well as "before" and "after"), defaults to integer `0`
53788		 * @param  {function} callback a function to call once the move is completed, receives 3 arguments - the node, the new parent and the position
53789		 * @param  {Boolean} is_loaded internal parameter indicating if the parent node has been loaded
53790		 * @param  {Boolean} skip_redraw internal parameter indicating if the tree should be redrawn
53791		 * @param  {Boolean} instance internal parameter indicating if the node comes from another instance
53792		 * @trigger model.jstree copy_node.jstree
53793		 */
53794		copy_node : function (obj, par, pos, callback, is_loaded, skip_redraw, origin) {
53795			var t1, t2, dpc, tmp, i, j, node, old_par, new_par, old_ins, is_multi;
53796
53797			par = this.get_node(par);
53798			pos = pos === undefined ? 0 : pos;
53799			if(!par) { return false; }
53800			if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) {
53801				return this.load_node(par, function () { this.copy_node(obj, par, pos, callback, true, false, origin); });
53802			}
53803
53804			if($.isArray(obj)) {
53805				if(obj.length === 1) {
53806					obj = obj[0];
53807				}
53808				else {
53809					//obj = obj.slice();
53810					for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
53811						if((tmp = this.copy_node(obj[t1], par, pos, callback, is_loaded, true, origin))) {
53812							par = tmp;
53813							pos = "after";
53814						}
53815					}
53816					this.redraw();
53817					return true;
53818				}
53819			}
53820			obj = obj && obj.id ? obj : this.get_node(obj);
53821			if(!obj || obj.id === $.jstree.root) { return false; }
53822
53823			old_par = (obj.parent || $.jstree.root).toString();
53824			new_par = (!pos.toString().match(/^(before|after)$/) || par.id === $.jstree.root) ? par : this.get_node(par.parent);
53825			old_ins = origin ? origin : (this._model.data[obj.id] ? this : $.jstree.reference(obj.id));
53826			is_multi = !old_ins || !old_ins._id || (this._id !== old_ins._id);
53827
53828			if(old_ins && old_ins._id) {
53829				obj = old_ins._model.data[obj.id];
53830			}
53831
53832			if(par.id === $.jstree.root) {
53833				if(pos === "before") { pos = "first"; }
53834				if(pos === "after") { pos = "last"; }
53835			}
53836			switch(pos) {
53837				case "before":
53838					pos = $.inArray(par.id, new_par.children);
53839					break;
53840				case "after" :
53841					pos = $.inArray(par.id, new_par.children) + 1;
53842					break;
53843				case "inside":
53844				case "first":
53845					pos = 0;
53846					break;
53847				case "last":
53848					pos = new_par.children.length;
53849					break;
53850				default:
53851					if(!pos) { pos = 0; }
53852					break;
53853			}
53854			if(pos > new_par.children.length) { pos = new_par.children.length; }
53855			if(!this.check("copy_node", obj, new_par, pos, { 'core' : true, 'origin' : origin, 'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id) })) {
53856				this.settings.core.error.call(this, this._data.core.last_error);
53857				return false;
53858			}
53859			node = old_ins ? old_ins.get_json(obj, { no_id : true, no_data : true, no_state : true }) : obj;
53860			if(!node) { return false; }
53861			if(node.id === true) { delete node.id; }
53862			node = this._parse_model_from_json(node, new_par.id, new_par.parents.concat());
53863			if(!node) { return false; }
53864			tmp = this.get_node(node);
53865			if(obj && obj.state && obj.state.loaded === false) { tmp.state.loaded = false; }
53866			dpc = [];
53867			dpc.push(node);
53868			dpc = dpc.concat(tmp.children_d);
53869			this.trigger('model', { "nodes" : dpc, "parent" : new_par.id });
53870
53871			// insert into new parent and up
53872			for(i = 0, j = new_par.parents.length; i < j; i++) {
53873				this._model.data[new_par.parents[i]].children_d = this._model.data[new_par.parents[i]].children_d.concat(dpc);
53874			}
53875			dpc = [];
53876			for(i = 0, j = new_par.children.length; i < j; i++) {
53877				dpc[i >= pos ? i+1 : i] = new_par.children[i];
53878			}
53879			dpc[pos] = tmp.id;
53880			new_par.children = dpc;
53881			new_par.children_d.push(tmp.id);
53882			new_par.children_d = new_par.children_d.concat(tmp.children_d);
53883
53884			if(new_par.id === $.jstree.root) {
53885				this._model.force_full_redraw = true;
53886			}
53887			if(!this._model.force_full_redraw) {
53888				this._node_changed(new_par.id);
53889			}
53890			if(!skip_redraw) {
53891				this.redraw(new_par.id === $.jstree.root);
53892			}
53893			if(callback) { callback.call(this, tmp, new_par, pos); }
53894			/**
53895			 * triggered when a node is copied
53896			 * @event
53897			 * @name copy_node.jstree
53898			 * @param {Object} node the copied node
53899			 * @param {Object} original the original node
53900			 * @param {String} parent the parent's ID
53901			 * @param {Number} position the position of the node among the parent's children
53902			 * @param {String} old_parent the old parent of the node
53903			 * @param {Number} old_position the position of the original node
53904			 * @param {Boolean} is_multi do the node and new parent belong to different instances
53905			 * @param {jsTree} old_instance the instance the node came from
53906			 * @param {jsTree} new_instance the instance of the new parent
53907			 */
53908			this.trigger('copy_node', { "node" : tmp, "original" : obj, "parent" : new_par.id, "position" : pos, "old_parent" : old_par, "old_position" : old_ins && old_ins._id && old_par && old_ins._model.data[old_par] && old_ins._model.data[old_par].children ? $.inArray(obj.id, old_ins._model.data[old_par].children) : -1,'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id), 'old_instance' : old_ins, 'new_instance' : this });
53909			return tmp.id;
53910		},
53911		/**
53912		 * cut a node (a later call to `paste(obj)` would move the node)
53913		 * @name cut(obj)
53914		 * @param  {mixed} obj multiple objects can be passed using an array
53915		 * @trigger cut.jstree
53916		 */
53917		cut : function (obj) {
53918			if(!obj) { obj = this._data.core.selected.concat(); }
53919			if(!$.isArray(obj)) { obj = [obj]; }
53920			if(!obj.length) { return false; }
53921			var tmp = [], o, t1, t2;
53922			for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
53923				o = this.get_node(obj[t1]);
53924				if(o && o.id && o.id !== $.jstree.root) { tmp.push(o); }
53925			}
53926			if(!tmp.length) { return false; }
53927			ccp_node = tmp;
53928			ccp_inst = this;
53929			ccp_mode = 'move_node';
53930			/**
53931			 * triggered when nodes are added to the buffer for moving
53932			 * @event
53933			 * @name cut.jstree
53934			 * @param {Array} node
53935			 */
53936			this.trigger('cut', { "node" : obj });
53937		},
53938		/**
53939		 * copy a node (a later call to `paste(obj)` would copy the node)
53940		 * @name copy(obj)
53941		 * @param  {mixed} obj multiple objects can be passed using an array
53942		 * @trigger copy.jstree
53943		 */
53944		copy : function (obj) {
53945			if(!obj) { obj = this._data.core.selected.concat(); }
53946			if(!$.isArray(obj)) { obj = [obj]; }
53947			if(!obj.length) { return false; }
53948			var tmp = [], o, t1, t2;
53949			for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
53950				o = this.get_node(obj[t1]);
53951				if(o && o.id
vendor: 2,801 bytes, lines 53951-54027
53951 && o.id !== $.jstree.root) { tmp.push(o); }
53952			}
53953			if(!tmp.length) { return false; }
53954			ccp_node = tmp;
53955			ccp_inst = this;
53956			ccp_mode = 'copy_node';
53957			/**
53958			 * triggered when nodes are added to the buffer for copying
53959			 * @event
53960			 * @name copy.jstree
53961			 * @param {Array} node
53962			 */
53963			this.trigger('copy', { "node" : obj });
53964		},
53965		/**
53966		 * get the current buffer (any nodes that are waiting for a paste operation)
53967		 * @name get_buffer()
53968		 * @return {Object} an object consisting of `mode` ("copy_node" or "move_node"), `node` (an array of objects) and `inst` (the instance)
53969		 */
53970		get_buffer : function () {
53971			return { 'mode' : ccp_mode, 'node' : ccp_node, 'inst' : ccp_inst };
53972		},
53973		/**
53974		 * check if there is something in the buffer to paste
53975		 * @name can_paste()
53976		 * @return {Boolean}
53977		 */
53978		can_paste : function () {
53979			return ccp_mode !== false && ccp_node !== false; // && ccp_inst._model.data[ccp_node];
53980		},
53981		/**
53982		 * copy or move the previously cut or copied nodes to a new parent
53983		 * @name paste(obj [, pos])
53984		 * @param  {mixed} obj the new parent
53985		 * @param  {mixed} pos the position to insert at (besides integer, "first" and "last" are supported), defaults to integer `0`
53986		 * @trigger paste.jstree
53987		 */
53988		paste : function (obj, pos) {
53989			obj = this.get_node(obj);
53990			if(!obj || !ccp_mode || !ccp_mode.match(/^(copy_node|move_node)$/) || !ccp_node) { return false; }
53991			if(this[ccp_mode](ccp_node, obj, pos, false, false, false, ccp_inst)) {
53992				/**
53993				 * triggered when paste is invoked
53994				 * @event
53995				 * @name paste.jstree
53996				 * @param {String} parent the ID of the receiving node
53997				 * @param {Array} node the nodes in the buffer
53998				 * @param {String} mode the performed operation - "copy_node" or "move_node"
53999				 */
54000				this.trigger('paste', { "parent" : obj.id, "node" : ccp_node, "mode" : ccp_mode });
54001			}
54002			ccp_node = false;
54003			ccp_mode = false;
54004			ccp_inst = false;
54005		},
54006		/**
54007		 * clear the buffer of previously copied or cut nodes
54008		 * @name clear_buffer()
54009		 * @trigger clear_buffer.jstree
54010		 */
54011		clear_buffer : function () {
54012			ccp_node = false;
54013			ccp_mode = false;
54014			ccp_inst = false;
54015			/**
54016			 * triggered when the copy / cut buffer is cleared
54017			 * @event
54018			 * @name clear_buffer.jstree
54019			 */
54020			this.trigger('clear_buffer');
54021		},
54022		/**
54023		 * put a node in edit mode (input field to rename the node)
54024		 * @name edit(obj [, default_text, callback])
54025		 * @param  {mixed} obj
54026		 * @param  {String} default_text the text to populate the input with (if omitted or set to a non-string value the node's text value is used)
54027		 * @param  {Function} callback a function to be called once the text box is blurred, it is called in the instance's scope and receives the node, a status parameter (true if the rename is successful, false otherwise)
vendor: 15,859 bytes, lines 54027-54525
54027 and a boolean indicating if the user cancelled the edit. You can access the node's title using .text
54028		 */
54029		edit : function (obj, default_text, callback) {
54030			var rtl, w, a, s, t, h1, h2, fn, tmp, cancel = false;
54031			obj = this.get_node(obj);
54032			if(!obj) { return false; }
54033			if(!this.check("edit", obj, this.get_parent(obj))) {
54034				this.settings.core.error.call(this, this._data.core.last_error);
54035				return false;
54036			}
54037			tmp = obj;
54038			default_text = typeof default_text === 'string' ? default_text : obj.text;
54039			this.set_text(obj, "");
54040			obj = this._open_to(obj);
54041			tmp.text = default_text;
54042
54043			rtl = this._data.core.rtl;
54044			w  = this.element.width();
54045			this._data.core.focused = tmp.id;
54046			a  = obj.children('.jstree-anchor').focus();
54047			s  = $('<span>');
54048			/*!
54049			oi = obj.children("i:visible"),
54050			ai = a.children("i:visible"),
54051			w1 = oi.width() * oi.length,
54052			w2 = ai.width() * ai.length,
54053			*/
54054			t  = default_text;
54055			h1 = $("<"+"div />", { css : { "position" : "absolute", "top" : "-200px", "left" : (rtl ? "0px" : "-1000px"), "visibility" : "hidden" } }).appendTo(document.body);
54056			h2 = $("<"+"input />", {
54057						"value" : t,
54058						"class" : "jstree-rename-input",
54059						// "size" : t.length,
54060						"css" : {
54061							"padding" : "0",
54062							"border" : "1px solid silver",
54063							"box-sizing" : "border-box",
54064							"display" : "inline-block",
54065							"height" : (this._data.core.li_height) + "px",
54066							"lineHeight" : (this._data.core.li_height) + "px",
54067							"width" : "150px" // will be set a bit further down
54068						},
54069						"blur" : $.proxy(function (e) {
54070							e.stopImmediatePropagation();
54071							e.preventDefault();
54072							var i = s.children(".jstree-rename-input"),
54073								v = i.val(),
54074								f = this.settings.core.force_text,
54075								nv;
54076							if(v === "") { v = t; }
54077							h1.remove();
54078							s.replaceWith(a);
54079							s.remove();
54080							t = f ? t : $('<div></div>').append($.parseHTML(t)).html();
54081							obj = this.get_node(obj);
54082							this.set_text(obj, t);
54083							nv = !!this.rename_node(obj, f ? $('<div></div>').text(v).text() : $('<div></div>').append($.parseHTML(v)).html());
54084							if(!nv) {
54085								this.set_text(obj, t); // move this up? and fix #483
54086							}
54087							this._data.core.focused = tmp.id;
54088							setTimeout($.proxy(function () {
54089								var node = this.get_node(tmp.id, true);
54090								if(node.length) {
54091									this._data.core.focused = tmp.id;
54092									node.children('.jstree-anchor').focus();
54093								}
54094							}, this), 0);
54095							if(callback) {
54096								callback.call(this, tmp, nv, cancel);
54097							}
54098							h2 = null;
54099						}, this),
54100						"keydown" : function (e) {
54101							var key = e.which;
54102							if(key === 27) {
54103								cancel = true;
54104								this.value = t;
54105							}
54106							if(key === 27 || key === 13 || key === 37 || key === 38 || key === 39 || key === 40 || key === 32) {
54107								e.stopImmediatePropagation();
54108							}
54109							if(key === 27 || key === 13) {
54110								e.preventDefault();
54111								this.blur();
54112							}
54113						},
54114						"click" : function (e) { e.stopImmediatePropagation(); },
54115						"mousedown" : function (e) { e.stopImmediatePropagation(); },
54116						"keyup" : function (e) {
54117							h2.width(Math.min(h1.text("pW" + this.value).width(),w));
54118						},
54119						"keypress" : function(e) {
54120							if(e.which === 13) { return false; }
54121						}
54122					});
54123				fn = {
54124						fontFamily		: a.css('fontFamily')		|| '',
54125						fontSize		: a.css('fontSize')			|| '',
54126						fontWeight		: a.css('fontWeight')		|| '',
54127						fontStyle		: a.css('fontStyle')		|| '',
54128						fontStretch		: a.css('fontStretch')		|| '',
54129						fontVariant		: a.css('fontVariant')		|| '',
54130						letterSpacing	: a.css('letterSpacing')	|| '',
54131						wordSpacing		: a.css('wordSpacing')		|| ''
54132				};
54133			s.attr('class', a.attr('class')).append(a.contents().clone()).append(h2);
54134			a.replaceWith(s);
54135			h1.css(fn);
54136			h2.css(fn).width(Math.min(h1.text("pW" + h2[0].value).width(),w))[0].select();
54137			$(document).one('mousedown.jstree touchstart.jstree dnd_start.vakata', function (e) {
54138				if (h2 && e.target !== h2) {
54139					$(h2).blur();
54140				}
54141			});
54142		},
54143
54144
54145		/**
54146		 * changes the theme
54147		 * @name set_theme(theme_name [, theme_url])
54148		 * @param {String} theme_name the name of the new theme to apply
54149		 * @param {mixed} theme_url  the location of the CSS file for this theme. Omit or set to `false` if you manually included the file. Set to `true` to autoload from the `core.themes.dir` directory.
54150		 * @trigger set_theme.jstree
54151		 */
54152		set_theme : function (theme_name, theme_url) {
54153			if(!theme_name) { return false; }
54154			if(theme_url === true) {
54155				var dir = this.settings.core.themes.dir;
54156				if(!dir) { dir = $.jstree.path + '/themes'; }
54157				theme_url = dir + '/' + theme_name + '/style.css';
54158			}
54159			if(theme_url && $.inArray(theme_url, themes_loaded) === -1) {
54160				$('head').append('<'+'link rel="stylesheet" href="' + theme_url + '" type="text/css" />');
54161				themes_loaded.push(theme_url);
54162			}
54163			if(this._data.core.themes.name) {
54164				this.element.removeClass('jstree-' + this._data.core.themes.name);
54165			}
54166			this._data.core.themes.name = theme_name;
54167			this.element.addClass('jstree-' + theme_name);
54168			this.element[this.settings.core.themes.responsive ? 'addClass' : 'removeClass' ]('jstree-' + theme_name + '-responsive');
54169			/**
54170			 * triggered when a theme is set
54171			 * @event
54172			 * @name set_theme.jstree
54173			 * @param {String} theme the new theme
54174			 */
54175			this.trigger('set_theme', { 'theme' : theme_name });
54176		},
54177		/**
54178		 * gets the name of the currently applied theme name
54179		 * @name get_theme()
54180		 * @return {String}
54181		 */
54182		get_theme : function () { return this._data.core.themes.name; },
54183		/**
54184		 * changes the theme variant (if the theme has variants)
54185		 * @name set_theme_variant(variant_name)
54186		 * @param {String|Boolean} variant_name the variant to apply (if `false` is used the current variant is removed)
54187		 */
54188		set_theme_variant : function (variant_name) {
54189			if(this._data.core.themes.variant) {
54190				this.element.removeClass('jstree-' + this._data.core.themes.name + '-' + this._data.core.themes.variant);
54191			}
54192			this._data.core.themes.variant = variant_name;
54193			if(variant_name) {
54194				this.element.addClass('jstree-' + this._data.core.themes.name + '-' + this._data.core.themes.variant);
54195			}
54196		},
54197		/**
54198		 * gets the name of the currently applied theme variant
54199		 * @name get_theme()
54200		 * @return {String}
54201		 */
54202		get_theme_variant : function () { return this._data.core.themes.variant; },
54203		/**
54204		 * shows a striped background on the container (if the theme supports it)
54205		 * @name show_stripes()
54206		 */
54207		show_stripes : function () {
54208			this._data.core.themes.stripes = true;
54209			this.get_container_ul().addClass("jstree-striped");
54210			/**
54211			 * triggered when stripes are shown
54212			 * @event
54213			 * @name show_stripes.jstree
54214			 */
54215			this.trigger('show_stripes');
54216		},
54217		/**
54218		 * hides the striped background on the container
54219		 * @name hide_stripes()
54220		 */
54221		hide_stripes : function () {
54222			this._data.core.themes.stripes = false;
54223			this.get_container_ul().removeClass("jstree-striped");
54224			/**
54225			 * triggered when stripes are hidden
54226			 * @event
54227			 * @name hide_stripes.jstree
54228			 */
54229			this.trigger('hide_stripes');
54230		},
54231		/**
54232		 * toggles the striped background on the container
54233		 * @name toggle_stripes()
54234		 */
54235		toggle_stripes : function () { if(this._data.core.themes.stripes) { this.hide_stripes(); } else { this.show_stripes(); } },
54236		/**
54237		 * shows the connecting dots (if the theme supports it)
54238		 * @name show_dots()
54239		 */
54240		show_dots : function () {
54241			this._data.core.themes.dots = true;
54242			this.get_container_ul().removeClass("jstree-no-dots");
54243			/**
54244			 * triggered when dots are shown
54245			 * @event
54246			 * @name show_dots.jstree
54247			 */
54248			this.trigger('show_dots');
54249		},
54250		/**
54251		 * hides the connecting dots
54252		 * @name hide_dots()
54253		 */
54254		hide_dots : function () {
54255			this._data.core.themes.dots = false;
54256			this.get_container_ul().addClass("jstree-no-dots");
54257			/**
54258			 * triggered when dots are hidden
54259			 * @event
54260			 * @name hide_dots.jstree
54261			 */
54262			this.trigger('hide_dots');
54263		},
54264		/**
54265		 * toggles the connecting dots
54266		 * @name toggle_dots()
54267		 */
54268		toggle_dots : function () { if(this._data.core.themes.dots) { this.hide_dots(); } else { this.show_dots(); } },
54269		/**
54270		 * show the node icons
54271		 * @name show_icons()
54272		 */
54273		show_icons : function () {
54274			this._data.core.themes.icons = true;
54275			this.get_container_ul().removeClass("jstree-no-icons");
54276			/**
54277			 * triggered when icons are shown
54278			 * @event
54279			 * @name show_icons.jstree
54280			 */
54281			this.trigger('show_icons');
54282		},
54283		/**
54284		 * hide the node icons
54285		 * @name hide_icons()
54286		 */
54287		hide_icons : function () {
54288			this._data.core.themes.icons = false;
54289			this.get_container_ul().addClass("jstree-no-icons");
54290			/**
54291			 * triggered when icons are hidden
54292			 * @event
54293			 * @name hide_icons.jstree
54294			 */
54295			this.trigger('hide_icons');
54296		},
54297		/**
54298		 * toggle the node icons
54299		 * @name toggle_icons()
54300		 */
54301		toggle_icons : function () { if(this._data.core.themes.icons) { this.hide_icons(); } else { this.show_icons(); } },
54302		/**
54303		 * show the node ellipsis
54304		 * @name show_icons()
54305		 */
54306		show_ellipsis : function () {
54307			this._data.core.themes.ellipsis = true;
54308			this.get_container_ul().addClass("jstree-ellipsis");
54309			/**
54310			 * triggered when ellisis is shown
54311			 * @event
54312			 * @name show_ellipsis.jstree
54313			 */
54314			this.trigger('show_ellipsis');
54315		},
54316		/**
54317		 * hide the node ellipsis
54318		 * @name hide_ellipsis()
54319		 */
54320		hide_ellipsis : function () {
54321			this._data.core.themes.ellipsis = false;
54322			this.get_container_ul().removeClass("jstree-ellipsis");
54323			/**
54324			 * triggered when ellisis is hidden
54325			 * @event
54326			 * @name hide_ellipsis.jstree
54327			 */
54328			this.trigger('hide_ellipsis');
54329		},
54330		/**
54331		 * toggle the node ellipsis
54332		 * @name toggle_icons()
54333		 */
54334		toggle_ellipsis : function () { if(this._data.core.themes.ellipsis) { this.hide_ellipsis(); } else { this.show_ellipsis(); } },
54335		/**
54336		 * set the node icon for a node
54337		 * @name set_icon(obj, icon)
54338		 * @param {mixed} obj
54339		 * @param {String} icon the new icon - can be a path to an icon or a className, if using an image that is in the current directory use a `./` prefix, otherwise it will be detected as a class
54340		 */
54341		set_icon : function (obj, icon) {
54342			var t1, t2, dom, old;
54343			if($.isArray(obj)) {
54344				obj = obj.slice();
54345				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
54346					this.set_icon(obj[t1], icon);
54347				}
54348				return true;
54349			}
54350			obj = this.get_node(obj);
54351			if(!obj || obj.id === $.jstree.root) { return false; }
54352			old = obj.icon;
54353			obj.icon = icon === true || icon === null || icon === undefined || icon === '' ? true : icon;
54354			dom = this.get_node(obj, true).children(".jstree-anchor").children(".jstree-themeicon");
54355			if(icon === false) {
54356				dom.removeClass('jstree-themeicon-custom ' + old).css("background","").removeAttr("rel");
54357				this.hide_icon(obj);
54358			}
54359			else if(icon === true || icon === null || icon === undefined || icon === '') {
54360				dom.removeClass('jstree-themeicon-custom ' + old).css("background","").removeAttr("rel");
54361				if(old === false) { this.show_icon(obj); }
54362			}
54363			else if(icon.indexOf("/") === -1 && icon.indexOf(".") === -1) {
54364				dom.removeClass(old).css("background","");
54365				dom.addClass(icon + ' jstree-themeicon-custom').attr("rel",icon);
54366				if(old === false) { this.show_icon(obj); }
54367			}
54368			else {
54369				dom.removeClass(old).css("background","");
54370				dom.addClass('jstree-themeicon-custom').css("background", "url('" + icon + "') center center no-repeat").attr("rel",icon);
54371				if(old === false) { this.show_icon(obj); }
54372			}
54373			return true;
54374		},
54375		/**
54376		 * get the node icon for a node
54377		 * @name get_icon(obj)
54378		 * @param {mixed} obj
54379		 * @return {String}
54380		 */
54381		get_icon : function (obj) {
54382			obj = this.get_node(obj);
54383			return (!obj || obj.id === $.jstree.root) ? false : obj.icon;
54384		},
54385		/**
54386		 * hide the icon on an individual node
54387		 * @name hide_icon(obj)
54388		 * @param {mixed} obj
54389		 */
54390		hide_icon : function (obj) {
54391			var t1, t2;
54392			if($.isArray(obj)) {
54393				obj = obj.slice();
54394				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
54395					this.hide_icon(obj[t1]);
54396				}
54397				return true;
54398			}
54399			obj = this.get_node(obj);
54400			if(!obj || obj === $.jstree.root) { return false; }
54401			obj.icon = false;
54402			this.get_node(obj, true).children(".jstree-anchor").children(".jstree-themeicon").addClass('jstree-themeicon-hidden');
54403			return true;
54404		},
54405		/**
54406		 * show the icon on an individual node
54407		 * @name show_icon(obj)
54408		 * @param {mixed} obj
54409		 */
54410		show_icon : function (obj) {
54411			var t1, t2, dom;
54412			if($.isArray(obj)) {
54413				obj = obj.slice();
54414				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
54415					this.show_icon(obj[t1]);
54416				}
54417				return true;
54418			}
54419			obj = this.get_node(obj);
54420			if(!obj || obj === $.jstree.root) { return false; }
54421			dom = this.get_node(obj, true);
54422			obj.icon = dom.length ? dom.children(".jstree-anchor").children(".jstree-themeicon").attr('rel') : true;
54423			if(!obj.icon) { obj.icon = true; }
54424			dom.children(".jstree-anchor").children(".jstree-themeicon").removeClass('jstree-themeicon-hidden');
54425			return true;
54426		}
54427	};
54428
54429	// helpers
54430	$.vakata = {};
54431	// collect attributes
54432	$.vakata.attributes = function(node, with_values) {
54433		node = $(node)[0];
54434		var attr = with_values ? {} : [];
54435		if(node && node.attributes) {
54436			$.each(node.attributes, function (i, v) {
54437				if($.inArray(v.name.toLowerCase(),['style','contenteditable','hasfocus','tabindex']) !== -1) { return; }
54438				if(v.value !== null && $.trim(v.value) !== '') {
54439					if(with_values) { attr[v.name] = v.value; }
54440					else { attr.push(v.name); }
54441				}
54442			});
54443		}
54444		return attr;
54445	};
54446	$.vakata.array_unique = function(array) {
54447		var a = [], i, j, l, o = {};
54448		for(i = 0, l = array.length; i < l; i++) {
54449			if(o[array[i]] === undefined) {
54450				a.push(array[i]);
54451				o[array[i]] = true;
54452			}
54453		}
54454		return a;
54455	};
54456	// remove item from array
54457	$.vakata.array_remove = function(array, from) {
54458		array.splice(from, 1);
54459		return array;
54460		//var rest = array.slice((to || from) + 1 || array.length);
54461		//array.length = from < 0 ? array.length + from : from;
54462		//array.push.apply(array, rest);
54463		//return array;
54464	};
54465	// remove item from array
54466	$.vakata.array_remove_item = function(array, item) {
54467		var tmp = $.inArray(item, array);
54468		return tmp !== -1 ? $.vakata.array_remove(array, tmp) : array;
54469	};
54470	$.vakata.array_filter = function(c,a,b,d,e) {
54471		if (c.filter) {
54472			return c.filter(a, b);
54473		}
54474		d=[];
54475		for (e in c) {
54476			if (~~e+''===e+'' && e>=0 && a.call(b,c[e],+e,c)) {
54477				d.push(c[e]);
54478			}
54479		}
54480		return d;
54481	};
54482
54483
54484/**
54485 * ### Changed plugin
54486 *
54487 * This plugin adds more information to the `changed.jstree` event. The new data is contained in the `changed` event data property, and contains a lists of `selected` and `deselected` nodes.
54488 */
54489
54490	$.jstree.plugins.changed = function (options, parent) {
54491		var last = [];
54492		this.trigger = function (ev, data) {
54493			var i, j;
54494			if(!data) {
54495				data = {};
54496			}
54497			if(ev.replace('.jstree','') === 'changed') {
54498				data.changed = { selected : [], deselected : [] };
54499				var tmp = {};
54500				for(i = 0, j = last.length; i < j; i++) {
54501					tmp[last[i]] = 1;
54502				}
54503				for(i = 0, j = data.selected.length; i < j; i++) {
54504					if(!tmp[data.selected[i]]) {
54505						data.changed.selected.push(data.selected[i]);
54506					}
54507					else {
54508						tmp[data.selected[i]] = 2;
54509					}
54510				}
54511				for(i = 0, j = last.length; i < j; i++) {
54512					if(tmp[last[i]] === 1) {
54513						data.changed.deselected.push(last[i]);
54514					}
54515				}
54516				last = data.selected.slice();
54517			}
54518			/**
54519			 * triggered when selection changes (the "changed" plugin enhances the original event with more data)
54520			 * @event
54521			 * @name changed.jstree
54522			 * @param {Object} node
54523			 * @param {Object} action the action that caused the selection to change
54524			 * @param {Array} selected the current selection
54525			 * @param {Object}
54525 changed an object containing two properties `selected` and `deselected` - both arrays of node IDs, which were selected or deselected since the last changed event
54526			 * @param {Object} event the event (if any) that triggered this changed event
54527			 * @plugin changed
54528			 */
54529			parent.trigger.call(this, ev, data);
54530		};
54531		this.refresh = function (skip_loading, forget_state) {
54532			last = [];
54533			return parent.refresh.apply(this, arguments);
54534		};
54535	};
54536
54537/**
54538 * ### Checkbox plugin
54539 *
54540 * This plugin renders checkbox icons in front of each node, making multiple selection much easier.
54541 * It also supports tri-state behavior, meaning that if a node has a few of its children checked it will be rendered as undetermined, and state will be propagated up.
54542 */
54543
54544	var _i = document.createElement('I');
54545	_i.className = 'jstree-icon jstree-checkbox';
54546	_i.setAttribute('role', 'presentation');
54547	/**
54548	 * stores all defaults for the checkbox plugin
54549	 * @name $.jstree.defaults.checkbox
54550	 * @plugin checkbox
54551	 */
54552	$.jstree.defaults.checkbox = {
54553		/**
54554		 * a boolean indicating if checkboxes should be visible (can be changed at a later time using `show_checkboxes()` and `hide_checkboxes`). Defaults to `true`.
54555		 * @name $.jstree.defaults.checkbox.visible
54556		 * @plugin checkbox
54557		 */
54558		visible				: true,
54559		/**
54560		 * a boolean indicating if checkboxes should cascade down and have an undetermined state. Defaults to `true`.
54561		 * @name $.jstree.defaults.checkbox.three_state
54562		 * @plugin checkbox
54563		 */
54564		three_state			: true,
54565		/**
54566		 * a boolean indicating if clicking anywhere on the node should act as clicking on the checkbox. Defaults to `true`.
54567		 * @name $.jstree.defaults.checkbox.whole_node
54568		 * @plugin checkbox
54569		 */
54570		whole_node			: true,
54571		/**
54572		 * a boolean indicating if the selected style of a node should be kept, or removed. Defaults to `true`.
54573		 * @name $.jstree.defaults.checkbox.keep_selected_style
54574		 * @plugin checkbox
54575		 */
54576		keep_selected_style	: true,
54577		/**
54578		 * This setting controls how cascading and undetermined nodes are applied.
54579		 * If 'up' is in the string - cascading up is enabled, if 'down' is in the string - cascading down is enabled, if 'undetermined' is in the string - undetermined nodes will be used.
54580		 * If `three_state` is set to `true` this setting is automatically set to 'up+down+undetermined'. Defaults to ''.
54581		 * @name $.jstree.defaults.checkbox.cascade
54582		 * @plugin checkbox
54583		 */
54584		cascade				: '',
54585		/**
54586		 * This setting controls if checkbox are bound to the general tree selection or to an internal array maintained by the checkbox plugin. Defaults to `true`, only set to `false` if you know exactly what you are doing.
54587		 * @name $.jstree.defaults.checkbox.tie_selection
54588		 * @plugin checkbox
54589		 */
54590		tie_selection		: true,
54591
54592		/**
54593		 * This setting controls if cascading down affects disabled checkboxes
54594		 * @name $.jstree.defaults.checkbox.cascade_to_disabled
54595		 * @plugin checkbox
54596		 */
54597		cascade_to_disabled : true,
54598
54599		/**
54600		 * This setting controls if cascading down affects hidden checkboxes
54601		 * @name $.jstree.defaults.checkbox.cascade_to_hidden
54602		 * @plugin checkbox
54603		 */
54604		cascade_to_hidden : true
54605	};
54606	$.jstree.plugins.checkbox = function (options, parent) {
54607		this.bind = function () {
54608			parent.bind.call(this);
54609			this._data.checkbox.uto = false;
54610			this._data.checkbox.selected = [];
54611			if(this.settings.checkbox.three_state) {
54612				this.settings.checkbox.cascade = 'up+down+undetermined';
54613			}
54614			this.element
54615				.on("init.jstree", $.proxy(function () {
54616						this._data.checkbox.visible = this.settings.checkbox.visible;
54617						if(!this.settings.checkbox.keep_selected_style) {
54618							this.element.addClass('jstree-checkbox-no-clicked');
54619						}
54620						if(this.settings.checkbox.tie_selection) {
54621							this.element.addClass('jstree-checkbox-selection');
54622						}
54623					}, this))
54624				.on("loading.jstree", $.proxy(function () {
54625						this[ this._data.checkbox.visible ? 'show_checkboxes' : 'hide_checkboxes' ]();
54626					}, this));
54627			if(this.settings.checkbox.cascade.indexOf('undetermined') !== -1) {
54628				this.element
54629					.on('changed.jstree uncheck_node.jstree check_node.jstree uncheck_all.
vendor: 89,340 bytes, lines 54629-56939
54629jstree check_all.jstree move_node.jstree copy_node.jstree redraw.jstree open_node.jstree', $.proxy(function () {
54630							// only if undetermined is in setting
54631							if(this._data.checkbox.uto) { clearTimeout(this._data.checkbox.uto); }
54632							this._data.checkbox.uto = setTimeout($.proxy(this._undetermined, this), 50);
54633						}, this));
54634			}
54635			if(!this.settings.checkbox.tie_selection) {
54636				this.element
54637					.on('model.jstree', $.proxy(function (e, data) {
54638						var m = this._model.data,
54639							p = m[data.parent],
54640							dpc = data.nodes,
54641							i, j;
54642						for(i = 0, j = dpc.length; i < j; i++) {
54643							m[dpc[i]].state.checked = m[dpc[i]].state.checked || (m[dpc[i]].original && m[dpc[i]].original.state && m[dpc[i]].original.state.checked);
54644							if(m[dpc[i]].state.checked) {
54645								this._data.checkbox.selected.push(dpc[i]);
54646							}
54647						}
54648					}, this));
54649			}
54650			if(this.settings.checkbox.cascade.indexOf('up') !== -1 || this.settings.checkbox.cascade.indexOf('down') !== -1) {
54651				this.element
54652					.on('model.jstree', $.proxy(function (e, data) {
54653							var m = this._model.data,
54654								p = m[data.parent],
54655								dpc = data.nodes,
54656								chd = [],
54657								c, i, j, k, l, tmp, s = this.settings.checkbox.cascade, t = this.settings.checkbox.tie_selection;
54658
54659							if(s.indexOf('down') !== -1) {
54660								// apply down
54661								if(p.state[ t ? 'selected' : 'checked' ]) {
54662									for(i = 0, j = dpc.length; i < j; i++) {
54663										m[dpc[i]].state[ t ? 'selected' : 'checked' ] = true;
54664									}
54665
54666									this._data[ t ? 'core' : 'checkbox' ].selected = this._data[ t ? 'core' : 'checkbox' ].selected.concat(dpc);
54667								}
54668								else {
54669									for(i = 0, j = dpc.length; i < j; i++) {
54670										if(m[dpc[i]].state[ t ? 'selected' : 'checked' ]) {
54671											for(k = 0, l = m[dpc[i]].children_d.length; k < l; k++) {
54672												m[m[dpc[i]].children_d[k]].state[ t ? 'selected' : 'checked' ] = true;
54673											}
54674											this._data[ t ? 'core' : 'checkbox' ].selected = this._data[ t ? 'core' : 'checkbox' ].selected.concat(m[dpc[i]].children_d);
54675										}
54676									}
54677								}
54678							}
54679
54680							if(s.indexOf('up') !== -1) {
54681								// apply up
54682								for(i = 0, j = p.children_d.length; i < j; i++) {
54683									if(!m[p.children_d[i]].children.length) {
54684										chd.push(m[p.children_d[i]].parent);
54685									}
54686								}
54687								chd = $.vakata.array_unique(chd);
54688								for(k = 0, l = chd.length; k < l; k++) {
54689									p = m[chd[k]];
54690									while(p && p.id !== $.jstree.root) {
54691										c = 0;
54692										for(i = 0, j = p.children.length; i < j; i++) {
54693											c += m[p.children[i]].state[ t ? 'selected' : 'checked' ];
54694										}
54695										if(c === j) {
54696											p.state[ t ? 'selected' : 'checked' ] = true;
54697											this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id);
54698											tmp = this.get_node(p, true);
54699											if(tmp && tmp.length) {
54700												tmp.attr('aria-selected', true).children('.jstree-anchor').addClass( t ? 'jstree-clicked' : 'jstree-checked');
54701											}
54702										}
54703										else {
54704											break;
54705										}
54706										p = this.get_node(p.parent);
54707									}
54708								}
54709							}
54710
54711							this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_unique(this._data[ t ? 'core' : 'checkbox' ].selected);
54712						}, this))
54713					.on(this.settings.checkbox.tie_selection ? 'select_node.jstree' : 'check_node.jstree', $.proxy(function (e, data) {
54714							var self = this,
54715								obj = data.node,
54716								m = this._model.data,
54717								par = this.get_node(obj.parent),
54718								i, j, c, tmp, s = this.settings.checkbox.cascade, t = this.settings.checkbox.tie_selection,
54719								sel = {}, cur = this._data[ t ? 'core' : 'checkbox' ].selected;
54720
54721							for (i = 0, j = cur.length; i < j; i++) {
54722								sel[cur[i]] = true;
54723							}
54724
54725							// apply down
54726							if(s.indexOf('down') !== -1) {
54727								//this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_unique(this._data[ t ? 'core' : 'checkbox' ].selected.concat(obj.children_d));
54728								var selectedIds = this._cascade_new_checked_state(obj.id, true);
54729								var temp = obj.children_d.concat(obj.id);
54730								for (i = 0, j = temp.length; i < j; i++) {
54731									if (selectedIds.indexOf(temp[i]) > -1) {
54732										sel[temp[i]] = true;
54733									}
54734									else {
54735										delete sel[temp[i]];
54736									}
54737								}
54738							}
54739
54740							// apply up
54741							if(s.indexOf('up') !== -1) {
54742								while(par && par.id !== $.jstree.root) {
54743									c = 0;
54744									for(i = 0, j = par.children.length; i < j; i++) {
54745										c += m[par.children[i]].state[ t ? 'selected' : 'checked' ];
54746									}
54747									if(c === j) {
54748										par.state[ t ? 'selected' : 'checked' ] = true;
54749										sel[par.id] = true;
54750										//this._data[ t ? 'core' : 'checkbox' ].selected.push(par.id);
54751										tmp = this.get_node(par, true);
54752										if(tmp && tmp.length) {
54753											tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked');
54754										}
54755									}
54756									else {
54757										break;
54758									}
54759									par = this.get_node(par.parent);
54760								}
54761							}
54762
54763							cur = [];
54764							for (i in sel) {
54765								if (sel.hasOwnProperty(i)) {
54766									cur.push(i);
54767								}
54768							}
54769							this._data[ t ? 'core' : 'checkbox' ].selected = cur;
54770						}, this))
54771					.on(this.settings.checkbox.tie_selection ? 'deselect_all.jstree' : 'uncheck_all.jstree', $.proxy(function (e, data) {
54772							var obj = this.get_node($.jstree.root),
54773								m = this._model.data,
54774								i, j, tmp;
54775							for(i = 0, j = obj.children_d.length; i < j; i++) {
54776								tmp = m[obj.children_d[i]];
54777								if(tmp && tmp.original && tmp.original.state && tmp.original.state.undetermined) {
54778									tmp.original.state.undetermined = false;
54779								}
54780							}
54781						}, this))
54782					.on(this.settings.checkbox.tie_selection ? 'deselect_node.jstree' : 'uncheck_node.jstree', $.proxy(function (e, data) {
54783							var self = this,
54784								obj = data.node,
54785								dom = this.get_node(obj, true),
54786								i, j, tmp, s = this.settings.checkbox.cascade, t = this.settings.checkbox.tie_selection,
54787								cur = this._data[ t ? 'core' : 'checkbox' ].selected, sel = {},
54788								stillSelectedIds = [],
54789								allIds = obj.children_d.concat(obj.id);
54790
54791							// apply down
54792							if(s.indexOf('down') !== -1) {
54793								var selectedIds = this._cascade_new_checked_state(obj.id, false);
54794
54795								cur = cur.filter(function(id) {
54796									return allIds.indexOf(id) === -1 || selectedIds.indexOf(id) > -1;
54797								});
54798							}
54799
54800							// only apply up if cascade up is enabled and if this node is not selected
54801							// (if all child nodes are disabled and cascade_to_disabled === false then this node will till be selected).
54802							if(s.indexOf('up') !== -1 && cur.indexOf(obj.id) === -1) {
54803								for(i = 0, j = obj.parents.length; i < j; i++) {
54804									tmp = this._model.data[obj.parents[i]];
54805									tmp.state[ t ? 'selected' : 'checked' ] = false;
54806									if(tmp && tmp.original && tmp.original.state && tmp.original.state.undetermined) {
54807										tmp.original.state.undetermined = false;
54808									}
54809									tmp = this.get_node(obj.parents[i], true);
54810									if(tmp && tmp.length) {
54811										tmp.attr('aria-selected', false).children('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked');
54812									}
54813								}
54814
54815								cur = cur.filter(function(id) {
54816									return obj.parents.indexOf(id) === -1;
54817								});
54818							}
54819
54820							this._data[ t ? 'core' : 'checkbox' ].selected = cur;
54821						}, this));
54822			}
54823			if(this.settings.checkbox.cascade.indexOf('up') !== -1) {
54824				this.element
54825					.on('delete_node.jstree', $.proxy(function (e, data) {
54826							// apply up (whole handler)
54827							var p = this.get_node(data.parent),
54828								m = this._model.data,
54829								i, j, c, tmp, t = this.settings.checkbox.tie_selection;
54830							while(p && p.id !== $.jstree.root && !p.state[ t ? 'selected' : 'checked' ]) {
54831								c = 0;
54832								for(i = 0, j = p.children.length; i < j; i++) {
54833									c += m[p.children[i]].state[ t ? 'selected' : 'checked' ];
54834								}
54835								if(j > 0 && c === j) {
54836									p.state[ t ? 'selected' : 'checked' ] = true;
54837									this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id);
54838									tmp = this.get_node(p, true);
54839									if(tmp && tmp.length) {
54840										tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked');
54841									}
54842								}
54843								else {
54844									break;
54845								}
54846								p = this.get_node(p.parent);
54847							}
54848						}, this))
54849					.on('move_node.jstree', $.proxy(function (e, data) {
54850							// apply up (whole handler)
54851							var is_multi = data.is_multi,
54852								old_par = data.old_parent,
54853								new_par = this.get_node(data.parent),
54854								m = this._model.data,
54855								p, c, i, j, tmp, t = this.settings.checkbox.tie_selection;
54856							if(!is_multi) {
54857								p = this.get_node(old_par);
54858								while(p && p.id !== $.jstree.root && !p.state[ t ? 'selected' : 'checked' ]) {
54859									c = 0;
54860									for(i = 0, j = p.children.length; i < j; i++) {
54861										c += m[p.children[i]].state[ t ? 'selected' : 'checked' ];
54862									}
54863									if(j > 0 && c === j) {
54864										p.state[ t ? 'selected' : 'checked' ] = true;
54865										this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id);
54866										tmp = this.get_node(p, true);
54867										if(tmp && tmp.length) {
54868											tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked');
54869										}
54870									}
54871									else {
54872										break;
54873									}
54874									p = this.get_node(p.parent);
54875								}
54876							}
54877							p = new_par;
54878							while(p && p.id !== $.jstree.root) {
54879								c = 0;
54880								for(i = 0, j = p.children.length; i < j; i++) {
54881									c += m[p.children[i]].state[ t ? 'selected' : 'checked' ];
54882								}
54883								if(c === j) {
54884									if(!p.state[ t ? 'selected' : 'checked' ]) {
54885										p.state[ t ? 'selected' : 'checked' ] = true;
54886										this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id);
54887										tmp = this.get_node(p, true);
54888										if(tmp && tmp.length) {
54889											tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked');
54890										}
54891									}
54892								}
54893								else {
54894									if(p.state[ t ? 'selected' : 'checked' ]) {
54895										p.state[ t ? 'selected' : 'checked' ] = false;
54896										this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_remove_item(this._data[ t ? 'core' : 'checkbox' ].selected, p.id);
54897										tmp = this.get_node(p, true);
54898										if(tmp && tmp.length) {
54899											tmp.attr('aria-selected', false).children('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked');
54900										}
54901									}
54902									else {
54903										break;
54904									}
54905								}
54906								p = this.get_node(p.parent);
54907							}
54908						}, this));
54909			}
54910		};
54911		/**
54912		 * get an array of all nodes whose state is "undetermined"
54913		 * @name get_undetermined([full])
54914		 * @param  {boolean} full: if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned
54915		 * @return {Array}
54916		 * @plugin checkbox
54917		 */
54918		this.get_undetermined = function (full) {
54919			if (this.settings.checkbox.cascade.indexOf('undetermined') === -1) {
54920				return [];
54921			}
54922			var i, j, k, l, o = {}, m = this._model.data, t = this.settings.checkbox.tie_selection, s = this._data[ t ? 'core' : 'checkbox' ].selected, p = [], tt = this, r = [];
54923			for(i = 0, j = s.length; i < j; i++) {
54924				if(m[s[i]] && m[s[i]].parents) {
54925					for(k = 0, l = m[s[i]].parents.length; k < l; k++) {
54926						if(o[m[s[i]].parents[k]] !== undefined) {
54927							break;
54928						}
54929						if(m[s[i]].parents[k] !== $.jstree.root) {
54930							o[m[s[i]].parents[k]] = true;
54931							p.push(m[s[i]].parents[k]);
54932						}
54933					}
54934				}
54935			}
54936			// attempt for server side undetermined state
54937			this.element.find('.jstree-closed').not(':has(.jstree-children)')
54938				.each(function () {
54939					var tmp = tt.get_node(this), tmp2;
54940					
54941					if(!tmp) { return; }
54942					
54943					if(!tmp.state.loaded) {
54944						if(tmp.original && tmp.original.state && tmp.original.state.undetermined && tmp.original.state.undetermined === true) {
54945							if(o[tmp.id] === undefined && tmp.id !== $.jstree.root) {
54946								o[tmp.id] = true;
54947								p.push(tmp.id);
54948							}
54949							for(k = 0, l = tmp.parents.length; k < l; k++) {
54950								if(o[tmp.parents[k]] === undefined && tmp.parents[k] !== $.jstree.root) {
54951									o[tmp.parents[k]] = true;
54952									p.push(tmp.parents[k]);
54953								}
54954							}
54955						}
54956					}
54957					else {
54958						for(i = 0, j = tmp.children_d.length; i < j; i++) {
54959							tmp2 = m[tmp.children_d[i]];
54960							if(!tmp2.state.loaded && tmp2.original && tmp2.original.state && tmp2.original.state.undetermined && tmp2.original.state.undetermined === true) {
54961								if(o[tmp2.id] === undefined && tmp2.id !== $.jstree.root) {
54962									o[tmp2.id] = true;
54963									p.push(tmp2.id);
54964								}
54965								for(k = 0, l = tmp2.parents.length; k < l; k++) {
54966									if(o[tmp2.parents[k]] === undefined && tmp2.parents[k] !== $.jstree.root) {
54967										o[tmp2.parents[k]] = true;
54968										p.push(tmp2.parents[k]);
54969									}
54970								}
54971							}
54972						}
54973					}
54974				});
54975			for (i = 0, j = p.length; i < j; i++) {
54976				if(!m[p[i]].state[ t ? 'selected' : 'checked' ]) {
54977					r.push(full ? m[p[i]] : p[i]);
54978				}
54979			}
54980			return r;
54981		};
54982		/**
54983		 * set the undetermined state where and if necessary. Used internally.
54984		 * @private
54985		 * @name _undetermined()
54986		 * @plugin checkbox
54987		 */
54988		this._undetermined = function () {
54989			if(this.element === null) { return; }
54990			var p = this.get_undetermined(false), i, j, s;
54991
54992			this.element.find('.jstree-undetermined').removeClass('jstree-undetermined');
54993			for (i = 0, j = p.length; i < j; i++) {
54994				s = this.get_node(p[i], true);
54995				if(s && s.length) {
54996					s.children('.jstree-anchor').children('.jstree-checkbox').addClass('jstree-undetermined');
54997				}
54998			}
54999		};
55000		this.redraw_node = function(obj, deep, is_callback, force_render) {
55001			obj = parent.redraw_node.apply(this, arguments);
55002			if(obj) {
55003				var i, j, tmp = null, icon = null;
55004				for(i = 0, j = obj.childNodes.length; i < j; i++) {
55005					if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) {
55006						tmp = obj.childNodes[i];
55007						break;
55008					}
55009				}
55010				if(tmp) {
55011					if(!this.settings.checkbox.tie_selection && this._model.data[obj.id].state.checked) { tmp.className += ' jstree-checked'; }
55012					icon = _i.cloneNode(false);
55013					if(this._model.data[obj.id].state.checkbox_disabled) { icon.className += ' jstree-checkbox-disabled'; }
55014					tmp.insertBefore(icon, tmp.childNodes[0]);
55015				}
55016			}
55017			if(!is_callback && this.settings.checkbox.cascade.indexOf('undetermined') !== -1) {
55018				if(this._data.checkbox.uto) { clearTimeout(this._data.checkbox.uto); }
55019				this._data.checkbox.uto = setTimeout($.proxy(this._undetermined, this), 50);
55020			}
55021			return obj;
55022		};
55023		/**
55024		 * show the node checkbox icons
55025		 * @name show_checkboxes()
55026		 * @plugin checkbox
55027		 */
55028		this.show_checkboxes = function () { this._data.core.themes.checkboxes = true; this.get_container_ul().removeClass("jstree-no-checkboxes"); };
55029		/**
55030		 * hide the node checkbox icons
55031		 * @name hide_checkboxes()
55032		 * @plugin checkbox
55033		 */
55034		this.hide_checkboxes = function () { this._data.core.themes.checkboxes = false; this.get_container_ul().addClass("jstree-no-checkboxes"); };
55035		/**
55036		 * toggle the node icons
55037		 * @name toggle_checkboxes()
55038		 * @plugin checkbox
55039		 */
55040		this.toggle_checkboxes = function () { if(this._data.core.themes.checkboxes) { this.hide_checkboxes(); } else { this.show_checkboxes(); } };
55041		/**
55042		 * checks if a node is in an undetermined state
55043		 * @name is_undetermined(obj)
55044		 * @param  {mixed} obj
55045		 * @return {Boolean}
55046		 */
55047		this.is_undetermined = function (obj) {
55048			obj = this.get_node(obj);
55049			var s = this.settings.checkbox.cascade, i, j, t = this.settings.checkbox.tie_selection, d = this._data[ t ? 'core' : 'checkbox' ].selected, m = this._model.data;
55050			if(!obj || obj.state[ t ? 'selected' : 'checked' ] === true || s.indexOf('undetermined') === -1 || (s.indexOf('down') === -1 && s.indexOf('up') === -1)) {
55051				return false;
55052			}
55053			if(!obj.state.loaded && obj.original.state.undetermined === true) {
55054				return true;
55055			}
55056			for(i = 0, j = obj.children_d.length; i < j; i++) {
55057				if($.inArray(obj.children_d[i], d) !== -1 || (!m[obj.children_d[i]].state.loaded && m[obj.children_d[i]].original.state.undetermined)) {
55058					return true;
55059				}
55060			}
55061			return false;
55062		};
55063		/**
55064		 * disable a node's checkbox
55065		 * @name disable_checkbox(obj)
55066		 * @param {mixed} obj an array can be used too
55067		 * @trigger disable_checkbox.jstree
55068		 * @plugin checkbox
55069		 */
55070		this.disable_checkbox = function (obj) {
55071			var t1, t2, dom;
55072			if($.isArray(obj)) {
55073				obj = obj.slice();
55074				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
55075					this.disable_checkbox(obj[t1]);
55076				}
55077				return true;
55078			}
55079			obj = this.get_node(obj);
55080			if(!obj || obj.id === $.jstree.root) {
55081				return false;
55082			}
55083			dom = this.get_node(obj, true);
55084			if(!obj.state.checkbox_disabled) {
55085				obj.state.checkbox_disabled = true;
55086				if(dom && dom.length) {
55087					dom.children('.jstree-anchor').children('.jstree-checkbox').addClass('jstree-checkbox-disabled');
55088				}
55089				/**
55090				 * triggered when an node's checkbox is disabled
55091				 * @event
55092				 * @name disable_checkbox.jstree
55093				 * @param {Object} node
55094				 * @plugin checkbox
55095				 */
55096				this.trigger('disable_checkbox', { 'node' : obj });
55097			}
55098		};
55099		/**
55100		 * enable a node's checkbox
55101		 * @name disable_checkbox(obj)
55102		 * @param {mixed} obj an array can be used too
55103		 * @trigger enable_checkbox.jstree
55104		 * @plugin checkbox
55105		 */
55106		this.enable_checkbox = function (obj) {
55107			var t1, t2, dom;
55108			if($.isArray(obj)) {
55109				obj = obj.slice();
55110				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
55111					this.enable_checkbox(obj[t1]);
55112				}
55113				return true;
55114			}
55115			obj = this.get_node(obj);
55116			if(!obj || obj.id === $.jstree.root) {
55117				return false;
55118			}
55119			dom = this.get_node(obj, true);
55120			if(obj.state.checkbox_disabled) {
55121				obj.state.checkbox_disabled = false;
55122				if(dom && dom.length) {
55123					dom.children('.jstree-anchor').children('.jstree-checkbox').removeClass('jstree-checkbox-disabled');
55124				}
55125				/**
55126				 * triggered when an node's checkbox is enabled
55127				 * @event
55128				 * @name enable_checkbox.jstree
55129				 * @param {Object} node
55130				 * @plugin checkbox
55131				 */
55132				this.trigger('enable_checkbox', { 'node' : obj });
55133			}
55134		};
55135
55136		this.activate_node = function (obj, e) {
55137			if($(e.target).hasClass('jstree-checkbox-disabled')) {
55138				return false;
55139			}
55140			if(this.settings.checkbox.tie_selection && (this.settings.checkbox.whole_node || $(e.target).hasClass('jstree-checkbox'))) {
55141				e.ctrlKey = true;
55142			}
55143			if(this.settings.checkbox.tie_selection || (!this.settings.checkbox.whole_node && !$(e.target).hasClass('jstree-checkbox'))) {
55144				return parent.activate_node.call(this, obj, e);
55145			}
55146			if(this.is_disabled(obj)) {
55147				return false;
55148			}
55149			if(this.is_checked(obj)) {
55150				this.uncheck_node(obj, e);
55151			}
55152			else {
55153				this.check_node(obj, e);
55154			}
55155			this.trigger('activate_node', { 'node' : this.get_node(obj) });
55156		};
55157
55158		/**
55159		 * Cascades checked state to a node and all its descendants. This function does NOT affect hidden and disabled nodes (or their descendants).
55160		 * However if these unaffected nodes are already selected their ids will be included in the returned array.
55161		 * @private
55162		 * @param {string} id the node ID
55163		 * @param {bool} checkedState should the nodes be checked or not
55164		 * @returns {Array} Array of all node id's (in this tree branch) that are checked.
55165		 */
55166		this._cascade_new_checked_state = function (id, checkedState) {
55167			var self = this;
55168			var t = this.settings.checkbox.tie_selection;
55169			var node = this._model.data[id];
55170			var selectedNodeIds = [];
55171			var selectedChildrenIds = [], i, j, selectedChildIds;
55172
55173			if (
55174				(this.settings.checkbox.cascade_to_disabled || !node.state.disabled) &&
55175				(this.settings.checkbox.cascade_to_hidden || !node.state.hidden)
55176			) {
55177				//First try and check/uncheck the children
55178				if (node.children) {
55179					for (i = 0, j = node.children.length; i < j; i++) {
55180						var childId = node.children[i];
55181						selectedChildIds = self._cascade_new_checked_state(childId, checkedState);
55182						selectedNodeIds = selectedNodeIds.concat(selectedChildIds);
55183						if (selectedChildIds.indexOf(childId) > -1) {
55184							selectedChildrenIds.push(childId);
55185						}
55186					}
55187				}
55188
55189				var dom = self.get_node(node, true);
55190
55191				//A node's state is undetermined if some but not all of it's children are checked/selected .
55192				var undetermined = selectedChildrenIds.length > 0 && selectedChildrenIds.length < node.children.length;
55193
55194				if(node.original && node.original.state && node.original.state.undetermined) {
55195					node.original.state.undetermined = undetermined;
55196				}
55197
55198				//If a node is undetermined then remove selected class
55199				if (undetermined) {
55200					node.state[ t ? 'selected' : 'checked' ] = false;
55201					dom.attr('aria-selected', false).children('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked');
55202				}
55203				//Otherwise, if the checkedState === true (i.e. the node is being checked now) and all of the node's children are checked (if it has any children),
55204				//check the node and style it correctly.
55205				else if (checkedState && selectedChildrenIds.length === node.children.length) {
55206					node.state[ t ? 'selected' : 'checked' ] = checkedState;
55207					selectedNodeIds.push(node.id);
55208
55209					dom.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked');
55210				}
55211				else {
55212					node.state[ t ? 'selected' : 'checked' ] = false;
55213					dom.attr('aria-selected', false).children('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked');
55214				}
55215			}
55216			else {
55217				selectedChildIds = this.get_checked_descendants(id);
55218
55219				if (node.state[ t ? 'selected' : 'checked' ]) {
55220					selectedChildIds.push(node.id);
55221				}
55222
55223				selectedNodeIds = selectedNodeIds.concat(selectedChildIds);
55224			}
55225
55226			return selectedNodeIds;
55227		};
55228
55229		/**
55230		 * Gets ids of nodes selected in branch (of tree) specified by id (does not include the node specified by id)
55231		 * @name get_checked_descendants(obj)
55232		 * @param {string} id the node ID
55233		 * @return {Array} array of IDs
55234		 * @plugin checkbox
55235		 */
55236		this.get_checked_descendants = function (id) {
55237			var self = this;
55238			var t = self.settings.checkbox.tie_selection;
55239			var node = self._model.data[id];
55240
55241			return node.children_d.filter(function(_id) {
55242				return self._model.data[_id].state[ t ? 'selected' : 'checked' ];
55243			});
55244		};
55245
55246		/**
55247		 * check a node (only if tie_selection in checkbox settings is false, otherwise select_node will be called internally)
55248		 * @name check_node(obj)
55249		 * @param {mixed} obj an array can be used to check multiple nodes
55250		 * @trigger check_node.jstree
55251		 * @plugin checkbox
55252		 */
55253		this.check_node = function (obj, e) {
55254			if(this.settings.checkbox.tie_selection) { return this.select_node(obj, false, true, e); }
55255			var dom, t1, t2, th;
55256			if($.isArray(obj)) {
55257				obj = obj.slice();
55258				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
55259					this.check_node(obj[t1], e);
55260				}
55261				return true;
55262			}
55263			obj = this.get_node(obj);
55264			if(!obj || obj.id === $.jstree.root) {
55265				return false;
55266			}
55267			dom = this.get_node(obj, true);
55268			if(!obj.state.checked) {
55269				obj.state.checked = true;
55270				this._data.checkbox.selected.push(obj.id);
55271				if(dom && dom.length) {
55272					dom.children('.jstree-anchor').addClass('jstree-checked');
55273				}
55274				/**
55275				 * triggered when an node is checked (only if tie_selection in checkbox settings is false)
55276				 * @event
55277				 * @name check_node.jstree
55278				 * @param {Object} node
55279				 * @param {Array} selected the current selection
55280				 * @param {Object} event the event (if any) that triggered this check_node
55281				 * @plugin checkbox
55282				 */
55283				this.trigger('check_node', { 'node' : obj, 'selected' : this._data.checkbox.selected, 'event' : e });
55284			}
55285		};
55286		/**
55287		 * uncheck a node (only if tie_selection in checkbox settings is false, otherwise deselect_node will be called internally)
55288		 * @name uncheck_node(obj)
55289		 * @param {mixed} obj an array can be used to uncheck multiple nodes
55290		 * @trigger uncheck_node.jstree
55291		 * @plugin checkbox
55292		 */
55293		this.uncheck_node = function (obj, e) {
55294			if(this.settings.checkbox.tie_selection) { return this.deselect_node(obj, false, e); }
55295			var t1, t2, dom;
55296			if($.isArray(obj)) {
55297				obj = obj.slice();
55298				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
55299					this.uncheck_node(obj[t1], e);
55300				}
55301				return true;
55302			}
55303			obj = this.get_node(obj);
55304			if(!obj || obj.id === $.jstree.root) {
55305				return false;
55306			}
55307			dom = this.get_node(obj, true);
55308			if(obj.state.checked) {
55309				obj.state.checked = false;
55310				this._data.checkbox.selected = $.vakata.array_remove_item(this._data.checkbox.selected, obj.id);
55311				if(dom.length) {
55312					dom.children('.jstree-anchor').removeClass('jstree-checked');
55313				}
55314				/**
55315				 * triggered when an node is unchecked (only if tie_selection in checkbox settings is false)
55316				 * @event
55317				 * @name uncheck_node.jstree
55318				 * @param {Object} node
55319				 * @param {Array} selected the current selection
55320				 * @param {Object} event the event (if any) that triggered this uncheck_node
55321				 * @plugin checkbox
55322				 */
55323				this.trigger('uncheck_node', { 'node' : obj, 'selected' : this._data.checkbox.selected, 'event' : e });
55324			}
55325		};
55326		
55327		/**
55328		 * checks all nodes in the tree (only if tie_selection in checkbox settings is false, otherwise select_all will be called internally)
55329		 * @name check_all()
55330		 * @trigger check_all.jstree, changed.jstree
55331		 * @plugin checkbox
55332		 */
55333		this.check_all = function () {
55334			if(this.settings.checkbox.tie_selection) { return this.select_all(); }
55335			var tmp = this._data.checkbox.selected.concat([]), i, j;
55336			this._data.checkbox.selected = this._model.data[$.jstree.root].children_d.concat();
55337			for(i = 0, j = this._data.checkbox.selected.length; i < j; i++) {
55338				if(this._model.data[this._data.checkbox.selected[i]]) {
55339					this._model.data[this._data.checkbox.selected[i]].state.checked = true;
55340				}
55341			}
55342			this.redraw(true);
55343			/**
55344			 * triggered when all nodes are checked (only if tie_selection in checkbox settings is false)
55345			 * @event
55346			 * @name check_all.jstree
55347			 * @param {Array} selected the current selection
55348			 * @plugin checkbox
55349			 */
55350			this.trigger('check_all', { 'selected' : this._data.checkbox.selected });
55351		};
55352		/**
55353		 * uncheck all checked nodes (only if tie_selection in checkbox settings is false, otherwise deselect_all will be called internally)
55354		 * @name uncheck_all()
55355		 * @trigger uncheck_all.jstree
55356		 * @plugin checkbox
55357		 */
55358		this.uncheck_all = function () {
55359			if(this.settings.checkbox.tie_selection) { return this.deselect_all(); }
55360			var tmp = this._data.checkbox.selected.concat([]), i, j;
55361			for(i = 0, j = this._data.checkbox.selected.length; i < j; i++) {
55362				if(this._model.data[this._data.checkbox.selected[i]]) {
55363					this._model.data[this._data.checkbox.selected[i]].state.checked = false;
55364				}
55365			}
55366			this._data.checkbox.selected = [];
55367			this.element.find('.jstree-checked').removeClass('jstree-checked');
55368			/**
55369			 * triggered when all nodes are unchecked (only if tie_selection in checkbox settings is false)
55370			 * @event
55371			 * @name uncheck_all.jstree
55372			 * @param {Object} node the previous selection
55373			 * @param {Array} selected the current selection
55374			 * @plugin checkbox
55375			 */
55376			this.trigger('uncheck_all', { 'selected' : this._data.checkbox.selected, 'node' : tmp });
55377		};
55378		/**
55379		 * checks if a node is checked (if tie_selection is on in the settings this function will return the same as is_selected)
55380		 * @name is_checked(obj)
55381		 * @param  {mixed}  obj
55382		 * @return {Boolean}
55383		 * @plugin checkbox
55384		 */
55385		this.is_checked = function (obj) {
55386			if(this.settings.checkbox.tie_selection) { return this.is_selected(obj); }
55387			obj = this.get_node(obj);
55388			if(!obj || obj.id === $.jstree.root) { return false; }
55389			return obj.state.checked;
55390		};
55391		/**
55392		 * get an array of all checked nodes (if tie_selection is on in the settings this function will return the same as get_selected)
55393		 * @name get_checked([full])
55394		 * @param  {mixed}  full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned
55395		 * @return {Array}
55396		 * @plugin checkbox
55397		 */
55398		this.get_checked = function (full) {
55399			if(this.settings.checkbox.tie_selection) { return this.get_selected(full); }
55400			return full ? $.map(this._data.checkbox.selected, $.proxy(function (i) { return this.get_node(i); }, this)) : this._data.checkbox.selected;
55401		};
55402		/**
55403		 * get an array of all top level checked nodes (ignoring children of checked nodes) (if tie_selection is on in the settings this function will return the same as get_top_selected)
55404		 * @name get_top_checked([full])
55405		 * @param  {mixed}  full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned
55406		 * @return {Array}
55407		 * @plugin checkbox
55408		 */
55409		this.get_top_checked = function (full) {
55410			if(this.settings.checkbox.tie_selection) { return this.get_top_selected(full); }
55411			var tmp = this.get_checked(true),
55412				obj = {}, i, j, k, l;
55413			for(i = 0, j = tmp.length; i < j; i++) {
55414				obj[tmp[i].id] = tmp[i];
55415			}
55416			for(i = 0, j = tmp.length; i < j; i++) {
55417				for(k = 0, l = tmp[i].children_d.length; k < l; k++) {
55418					if(obj[tmp[i].children_d[k]]) {
55419						delete obj[tmp[i].children_d[k]];
55420					}
55421				}
55422			}
55423			tmp = [];
55424			for(i in obj) {
55425				if(obj.hasOwnProperty(i)) {
55426					tmp.push(i);
55427				}
55428			}
55429			return full ? $.map(tmp, $.proxy(function (i) { return this.get_node(i); }, this)) : tmp;
55430		};
55431		/**
55432		 * get an array of all bottom level checked nodes (ignoring selected parents) (if tie_selection is on in the settings this function will return the same as get_bottom_selected)
55433		 * @name get_bottom_checked([full])
55434		 * @param  {mixed}  full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned
55435		 * @return {Array}
55436		 * @plugin checkbox
55437		 */
55438		this.get_bottom_checked = function (full) {
55439			if(this.settings.checkbox.tie_selection) { return this.get_bottom_selected(full); }
55440			var tmp = this.get_checked(true),
55441				obj = [], i, j;
55442			for(i = 0, j = tmp.length; i < j; i++) {
55443				if(!tmp[i].children.length) {
55444					obj.push(tmp[i].id);
55445				}
55446			}
55447			return full ? $.map(obj, $.proxy(function (i) { return this.get_node(i); }, this)) : obj;
55448		};
55449		this.load_node = function (obj, callback) {
55450			var k, l, i, j, c, tmp;
55451			if(!$.isArray(obj) && !this.settings.checkbox.tie_selection) {
55452				tmp = this.get_node(obj);
55453				if(tmp && tmp.state.loaded) {
55454					for(k = 0, l = tmp.children_d.length; k < l; k++) {
55455						if(this._model.data[tmp.children_d[k]].state.checked) {
55456							c = true;
55457							this._data.checkbox.selected = $.vakata.array_remove_item(this._data.checkbox.selected, tmp.children_d[k]);
55458						}
55459					}
55460				}
55461			}
55462			return parent.load_node.apply(this, arguments);
55463		};
55464		this.get_state = function () {
55465			var state = parent.get_state.apply(this, arguments);
55466			if(this.settings.checkbox.tie_selection) { return state; }
55467			state.checkbox = this._data.checkbox.selected.slice();
55468			return state;
55469		};
55470		this.set_state = function (state, callback) {
55471			var res = parent.set_state.apply(this, arguments);
55472			if(res && state.checkbox) {
55473				if(!this.settings.checkbox.tie_selection) {
55474					this.uncheck_all();
55475					var _this = this;
55476					$.each(state.checkbox, function (i, v) {
55477						_this.check_node(v);
55478					});
55479				}
55480				delete state.checkbox;
55481				this.set_state(state, callback);
55482				return false;
55483			}
55484			return res;
55485		};
55486		this.refresh = function (skip_loading, forget_state) {
55487			if(this.settings.checkbox.tie_selection) {
55488				this._data.checkbox.selected = [];
55489			}
55490			return parent.refresh.apply(this, arguments);
55491		};
55492	};
55493
55494	// include the checkbox plugin by default
55495	// $.jstree.defaults.plugins.push("checkbox");
55496
55497
55498/**
55499 * ### Conditionalselect plugin
55500 *
55501 * This plugin allows defining a callback to allow or deny node selection by user input (activate node method).
55502 */
55503
55504	/**
55505	 * a callback (function) which is invoked in the instance's scope and receives two arguments - the node and the event that triggered the `activate_node` call. Returning false prevents working with the node, returning true allows invoking activate_node. Defaults to returning `true`.
55506	 * @name $.jstree.defaults.checkbox.visible
55507	 * @plugin checkbox
55508	 */
55509	$.jstree.defaults.conditionalselect = function () { return true; };
55510	$.jstree.plugins.conditionalselect = function (options, parent) {
55511		// own function
55512		this.activate_node = function (obj, e) {
55513			if(this.settings.conditionalselect.call(this, this.get_node(obj), e)) {
55514				return parent.activate_node.call(this, obj, e);
55515			}
55516		};
55517	};
55518
55519
55520/**
55521 * ### Contextmenu plugin
55522 *
55523 * Shows a context menu when a node is right-clicked.
55524 */
55525
55526	/**
55527	 * stores all defaults for the contextmenu plugin
55528	 * @name $.jstree.defaults.contextmenu
55529	 * @plugin contextmenu
55530	 */
55531	$.jstree.defaults.contextmenu = {
55532		/**
55533		 * a boolean indicating if the node should be selected when the context menu is invoked on it. Defaults to `true`.
55534		 * @name $.jstree.defaults.contextmenu.select_node
55535		 * @plugin contextmenu
55536		 */
55537		select_node : true,
55538		/**
55539		 * a boolean indicating if the menu should be shown aligned with the node. Defaults to `true`, otherwise the mouse coordinates are used.
55540		 * @name $.jstree.defaults.contextmenu.show_at_node
55541		 * @plugin contextmenu
55542		 */
55543		show_at_node : true,
55544		/**
55545		 * an object of actions, or a function that accepts a node and a callback function and calls the callback function with an object of actions available for that node (you can also return the items too).
55546		 *
55547		 * Each action consists of a key (a unique name) and a value which is an object with the following properties (only label and action are required). Once a menu item is activated the `action` function will be invoked with an object containing the following keys: item - the contextmenu item definition as seen below, reference - the DOM node that was used (the tree node), element - the contextmenu DOM element, position - an object with x/y properties indicating the position of the menu.
55548		 *
55549		 * * `separator_before` - a boolean indicating if there should be a separator before this item
55550		 * * `separator_after` - a boolean indicating if there should be a separator after this item
55551		 * * `_disabled` - a boolean indicating if this action should be disabled
55552		 * * `label` - a string - the name of the action (could be a function returning a string)
55553		 * * `title` - a string - an optional tooltip for the item
55554		 * * `action` - a function to be executed if this item is chosen, the function will receive 
55555		 * * `icon` - a string, can be a path to an icon or a className, if using an image that is in the current directory use a `./` prefix, otherwise it will be detected as a class
55556		 * * `shortcut` - keyCode which will trigger the action if the menu is open (for example `113` for rename, which equals F2)
55557		 * * `shortcut_label` - shortcut label (like for example `F2` for rename)
55558		 * * `submenu` - an object with the same structure as $.jstree.defaults.contextmenu.items which can be used to create a submenu - each key will be rendered as a separate option in a submenu that will appear once the current item is hovered
55559		 *
55560		 * @name $.jstree.defaults.contextmenu.items
55561		 * @plugin contextmenu
55562		 */
55563		items : function (o, cb) { // Could be an object directly
55564			return {
55565				"create" : {
55566					"separator_before"	: false,
55567					"separator_after"	: true,
55568					"_disabled"			: false, //(this.check("create_node", data.reference, {}, "last")),
55569					"label"				: "Create",
55570					"action"			: function (data) {
55571						var inst = $.jstree.reference(data.reference),
55572							obj = inst.get_node(data.reference);
55573						inst.create_node(obj, {}, "last", function (new_node) {
55574							try {
55575								inst.edit(new_node);
55576							} catch (ex) {
55577								setTimeout(function () { inst.edit(new_node); },0);
55578							}
55579						});
55580					}
55581				},
55582				"rename" : {
55583					"separator_before"	: false,
55584					"separator_after"	: false,
55585					"_disabled"			: false, //(this.check("rename_node", data.reference, this.get_parent(data.reference), "")),
55586					"label"				: "Rename",
55587					/*!
55588					"shortcut"			: 113,
55589					"shortcut_label"	: 'F2',
55590					"icon"				: "glyphicon glyphicon-leaf",
55591					*/
55592					"action"			: function (data) {
55593						var inst = $.jstree.reference(data.reference),
55594							obj = inst.get_node(data.reference);
55595						inst.edit(obj);
55596					}
55597				},
55598				"remove" : {
55599					"separator_before"	: false,
55600					"icon"				: false,
55601					"separator_after"	: false,
55602					"_disabled"			: false, //(this.check("delete_node", data.reference, this.get_parent(data.reference), "")),
55603					"label"				: "Delete",
55604					"action"			: function (data) {
55605						var inst = $.jstree.reference(data.reference),
55606							obj = inst.get_node(data.reference);
55607						if(inst.is_selected(obj)) {
55608							inst.delete_node(inst.get_selected());
55609						}
55610						else {
55611							inst.delete_node(obj);
55612						}
55613					}
55614				},
55615				"ccp" : {
55616					"separator_before"	: true,
55617					"icon"				: false,
55618					"separator_after"	: false,
55619					"label"				: "Edit",
55620					"action"			: false,
55621					"submenu" : {
55622						"cut" : {
55623							"separator_before"	: false,
55624							"separator_after"	: false,
55625							"label"				: "Cut",
55626							"action"			: function (data) {
55627								var inst = $.jstree.reference(data.reference),
55628									obj = inst.get_node(data.reference);
55629								if(inst.is_selected(obj)) {
55630									inst.cut(inst.get_top_selected());
55631								}
55632								else {
55633									inst.cut(obj);
55634								}
55635							}
55636						},
55637						"copy" : {
55638							"separator_before"	: false,
55639							"icon"				: false,
55640							"separator_after"	: false,
55641							"label"				: "Copy",
55642							"action"			: function (data) {
55643								var inst = $.jstree.reference(data.reference),
55644									obj = inst.get_node(data.reference);
55645								if(inst.is_selected(obj)) {
55646									inst.copy(inst.get_top_selected());
55647								}
55648								else {
55649									inst.copy(obj);
55650								}
55651							}
55652						},
55653						"paste" : {
55654							"separator_before"	: false,
55655							"icon"				: false,
55656							"_disabled"			: function (data) {
55657								return !$.jstree.reference(data.reference).can_paste();
55658							},
55659							"separator_after"	: false,
55660							"label"				: "Paste",
55661							"action"			: function (data) {
55662								var inst = $.jstree.reference(data.reference),
55663									obj = inst.get_node(data.reference);
55664								inst.paste(obj);
55665							}
55666						}
55667					}
55668				}
55669			};
55670		}
55671	};
55672
55673	$.jstree.plugins.contextmenu = function (options, parent) {
55674		this.bind = function () {
55675			parent.bind.call(this);
55676
55677			var last_ts = 0, cto = null, ex, ey;
55678			this.element
55679				.on("init.jstree loading.jstree ready.jstree", $.proxy(function () {
55680						this.get_container_ul().addClass('jstree-contextmenu');
55681					}, this))
55682				.on("contextmenu.jstree", ".jstree-anchor", $.proxy(function (e, data) {
55683						if (e.target.tagName.toLowerCase() === 'input') {
55684							return;
55685						}
55686						e.preventDefault();
55687						last_ts = e.ctrlKey ? +new Date() : 0;
55688						if(data || cto) {
55689							last_ts = (+new Date()) + 10000;
55690						}
55691						if(cto) {
55692							clearTimeout(cto);
55693						}
55694						if(!this.is_loading(e.currentTarget)) {
55695							this.show_contextmenu(e.currentTarget, e.pageX, e.pageY, e);
55696						}
55697					}, this))
55698				.on("click.jstree", ".jstree-anchor", $.proxy(function (e) {
55699						if(this._data.contextmenu.visible && (!last_ts || (+new Date()) - last_ts > 250)) { // work around safari & macOS ctrl+click
55700							$.vakata.context.hide();
55701						}
55702						last_ts = 0;
55703					}, this))
55704				.on("touchstart.jstree", ".jstree-anchor", function (e) {
55705						if(!e.originalEvent || !e.originalEvent.changedTouches || !e.originalEvent.changedTouches[0]) {
55706							return;
55707						}
55708						ex = e.originalEvent.changedTouches[0].clientX;
55709						ey = e.originalEvent.changedTouches[0].clientY;
55710						cto = setTimeout(function () {
55711							$(e.currentTarget).trigger('contextmenu', true);
55712						}, 750);
55713					})
55714				.on('touchmove.vakata.jstree', function (e) {
55715						if(cto && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0] && (Math.abs(ex - e.originalEvent.changedTouches[0].clientX) > 10 || Math.abs(ey - e.originalEvent.changedTouches[0].clientY) > 10)) {
55716							clearTimeout(cto);
55717							$.vakata.context.hide();
55718						}
55719					})
55720				.on('touchend.vakata.jstree', function (e) {
55721						if(cto) {
55722							clearTimeout(cto);
55723						}
55724					});
55725
55726			/*!
55727			if(!('oncontextmenu' in document.body) && ('ontouchstart' in document.body)) {
55728				var el = null, tm = null;
55729				this.element
55730					.on("touchstart", ".jstree-anchor", function (e) {
55731						el = e.currentTarget;
55732						tm = +new Date();
55733						$(document).one("touchend", function (e) {
55734							e.target = document.elementFromPoint(e.originalEvent.targetTouches[0].pageX - window.pageXOffset, e.originalEvent.targetTouches[0].pageY - window.pageYOffset);
55735							e.currentTarget = e.target;
55736							tm = ((+(new Date())) - tm);
55737							if(e.target === el && tm > 600 && tm < 1000) {
55738								e.preventDefault();
55739								$(el).trigger('contextmenu', e);
55740							}
55741							el = null;
55742							tm = null;
55743						});
55744					});
55745			}
55746			*/
55747			$(document).on("context_hide.vakata.jstree", $.proxy(function (e, data) {
55748				this._data.contextmenu.visible = false;
55749				$(data.reference).removeClass('jstree-context');
55750			}, this));
55751		};
55752		this.teardown = function () {
55753			if(this._data.contextmenu.visible) {
55754				$.vakata.context.hide();
55755			}
55756			parent.teardown.call(this);
55757		};
55758
55759		/**
55760		 * prepare and show the context menu for a node
55761		 * @name show_contextmenu(obj [, x, y])
55762		 * @param {mixed} obj the node
55763		 * @param {Number} x the x-coordinate relative to the document to show the menu at
55764		 * @param {Number} y the y-coordinate relative to the document to show the menu at
55765		 * @param {Object} e the event if available that triggered the contextmenu
55766		 * @plugin contextmenu
55767		 * @trigger show_contextmenu.jstree
55768		 */
55769		this.show_contextmenu = function (obj, x, y, e) {
55770			obj = this.get_node(obj);
55771			if(!obj || obj.id === $.jstree.root) { return false; }
55772			var s = this.settings.contextmenu,
55773				d = this.get_node(obj, true),
55774				a = d.children(".jstree-anchor"),
55775				o = false,
55776				i = false;
55777			if(s.show_at_node || x === undefined || y === undefined) {
55778				o = a.offset();
55779				x = o.left;
55780				y = o.top + this._data.core.li_height;
55781			}
55782			if(this.settings.contextmenu.select_node && !this.is_selected(obj)) {
55783				this.activate_node(obj, e);
55784			}
55785
55786			i = s.items;
55787			if($.isFunction(i)) {
55788				i = i.call(this, obj, $.proxy(function (i) {
55789					this._show_contextmenu(obj, x, y, i);
55790				}, this));
55791			}
55792			if($.isPlainObject(i)) {
55793				this._show_contextmenu(obj, x, y, i);
55794			}
55795		};
55796		/**
55797		 * show the prepared context menu for a node
55798		 * @name _show_contextmenu(obj, x, y, i)
55799		 * @param {mixed} obj the node
55800		 * @param {Number} x the x-coordinate relative to the document to show the menu at
55801		 * @param {Number} y the y-coordinate relative to the document to show the menu at
55802		 * @param {Number} i the object of items to show
55803		 * @plugin contextmenu
55804		 * @trigger show_contextmenu.jstree
55805		 * @private
55806		 */
55807		this._show_contextmenu = function (obj, x, y, i) {
55808			var d = this.get_node(obj, true),
55809				a = d.children(".jstree-anchor");
55810			$(document).one("context_show.vakata.jstree", $.proxy(function (e, data) {
55811				var cls = 'jstree-contextmenu jstree-' + this.get_theme() + '-contextmenu';
55812				$(data.element).addClass(cls);
55813				a.addClass('jstree-context');
55814			}, this));
55815			this._data.contextmenu.visible = true;
55816			$.vakata.context.show(a, { 'x' : x, 'y' : y }, i);
55817			/**
55818			 * triggered when the contextmenu is shown for a node
55819			 * @event
55820			 * @name show_contextmenu.jstree
55821			 * @param {Object} node the node
55822			 * @param {Number} x the x-coordinate of the menu relative to the document
55823			 * @param {Number} y the y-coordinate of the menu relative to the document
55824			 * @plugin contextmenu
55825			 */
55826			this.trigger('show_contextmenu', { "node" : obj, "x" : x, "y" : y });
55827		};
55828	};
55829
55830	// contextmenu helper
55831	(function ($) {
55832		var right_to_left = false,
55833			vakata_context = {
55834				element		: false,
55835				reference	: false,
55836				position_x	: 0,
55837				position_y	: 0,
55838				items		: [],
55839				html		: "",
55840				is_visible	: false
55841			};
55842
55843		$.vakata.context = {
55844			settings : {
55845				hide_onmouseleave	: 0,
55846				icons				: true
55847			},
55848			_trigger : function (event_name) {
55849				$(document).triggerHandler("context_" + event_name + ".vakata", {
55850					"reference"	: vakata_context.reference,
55851					"element"	: vakata_context.element,
55852					"position"	: {
55853						"x" : vakata_context.position_x,
55854						"y" : vakata_context.position_y
55855					}
55856				});
55857			},
55858			_execute : function (i) {
55859				i = vakata_context.items[i];
55860				return i && (!i._disabled || ($.isFunction(i._disabled) && !i._disabled({ "item" : i, "reference" : vakata_context.reference, "element" : vakata_context.element }))) && i.action ? i.action.call(null, {
55861							"item"		: i,
55862							"reference"	: vakata_context.reference,
55863							"element"	: vakata_context.element,
55864							"position"	: {
55865								"x" : vakata_context.position_x,
55866								"y" : vakata_context.position_y
55867							}
55868						}) : false;
55869			},
55870			_parse : function (o, is_callback) {
55871				if(!o) { return false; }
55872				if(!is_callback) {
55873					vakata_context.html		= "";
55874					vakata_context.items	= [];
55875				}
55876				var str = "",
55877					sep = false,
55878					tmp;
55879
55880				if(is_callback) { str += "<"+"ul>"; }
55881				$.each(o, function (i, val) {
55882					if(!val) { return true; }
55883					vakata_context.items.push(val);
55884					if(!sep && val.separator_before) {
55885						str += "<"+"li class='vakata-context-separator'><"+"a href='#' " + ($.vakata.context.settings.icons ? '' : 'style="margin-left:0px;"') + ">&#160;<"+"/a><"+"/li>";
55886					}
55887					sep = false;
55888					str += "<"+"li class='" + (val._class || "") + (val._disabled === true || ($.isFunction(val._disabled) && val._disabled({ "item" : val, "reference" : vakata_context.reference, "element" : vakata_context.element })) ? " vakata-contextmenu-disabled " : "") + "' "+(val.shortcut?" data-shortcut='"+val.shortcut+"' ":'')+">";
55889					str += "<"+"a href='#' rel='" + (vakata_context.items.length - 1) + "' " + (val.title ? "title='" + val.title + "'" : "") + ">";
55890					if($.vakata.context.settings.icons) {
55891						str += "<"+"i ";
55892						if(val.icon) {
55893							if(val.icon.indexOf("/") !== -1 || val.icon.indexOf(".") !== -1) { str += " style='background:url(\"" + val.icon + "\") center center no-repeat' "; }
55894							else { str += " class='" + val.icon + "' "; }
55895						}
55896						str += "><"+"/i><"+"span class='vakata-contextmenu-sep'>&#160;<"+"/span>";
55897					}
55898					str += ($.isFunction(val.label) ? val.label({ "item" : i, "reference" : vakata_context.reference, "element" : vakata_context.element }) : val.label) + (val.shortcut?' <span class="vakata-contextmenu-shortcut vakata-contextmenu-shortcut-'+val.shortcut+'">'+ (val.shortcut_label || '') +'</span>':'') + "<"+"/a>";
55899					if(val.submenu) {
55900						tmp = $.vakata.context._parse(val.submenu, true);
55901						if(tmp) { str += tmp; }
55902					}
55903					str += "<"+"/li>";
55904					if(val.separator_after) {
55905						str += "<"+"li class='vakata-context-separator'><"+"a href='#' " + ($.vakata.context.settings.icons ? '' : 'style="margin-left:0px;"') + ">&#160;<"+"/a><"+"/li>";
55906						sep = true;
55907					}
55908				});
55909				str  = str.replace(/<li class\='vakata-context-separator'\><\/li\>$/,"");
55910				if(is_callback) { str += "</ul>"; }
55911				/**
55912				 * triggered on the document when the contextmenu is parsed (HTML is built)
55913				 * @event
55914				 * @plugin contextmenu
55915				 * @name context_parse.vakata
55916				 * @param {jQuery} reference the element that was right clicked
55917				 * @param {jQuery} element the DOM element of the menu itself
55918				 * @param {Object} position the x & y coordinates of the menu
55919				 */
55920				if(!is_callback) { vakata_context.html = str; $.vakata.context._trigger("parse"); }
55921				return str.length > 10 ? str : false;
55922			},
55923			_show_submenu : function (o) {
55924				o = $(o);
55925				if(!o.length || !o.children("ul").length) { return; }
55926				var e = o.children("ul"),
55927					xl = o.offset().left,
55928					x = xl + o.outerWidth(),
55929					y = o.offset().top,
55930					w = e.width(),
55931					h = e.height(),
55932					dw = $(window).width() + $(window).scrollLeft(),
55933					dh = $(window).height() + $(window).scrollTop();
55934				// може да се спести е една проверка - дали няма някой от класовете вече нагоре
55935				if(right_to_left) {
55936					o[x - (w + 10 + o.outerWidth()) < 0 ? "addClass" : "removeClass"]("vakata-context-left");
55937				}
55938				else {
55939					o[x + w > dw  && xl > dw - x ? "addClass" : "removeClass"]("vakata-context-right");
55940				}
55941				if(y + h + 10 > dh) {
55942					e.css("bottom","-1px");
55943				}
55944
55945				//if does not fit - stick it to the side
55946				if (o.hasClass('vakata-context-right')) {
55947					if (xl < w) {
55948						e.css("margin-right", xl - w);
55949					}
55950				} else {
55951					if (dw - x < w) {
55952						e.css("margin-left", dw - x - w);
55953					}
55954				}
55955
55956				e.show();
55957			},
55958			show : function (reference, position, data) {
55959				var o, e, x, y, w, h, dw, dh, cond = true;
55960				if(vakata_context.element && vakata_context.element.length) {
55961					vakata_context.element.width('');
55962				}
55963				switch(cond) {
55964					case (!position && !reference):
55965						return false;
55966					case (!!position && !!reference):
55967						vakata_context.reference	= reference;
55968						vakata_context.position_x	= position.x;
55969						vakata_context.position_y	= position.y;
55970						break;
55971					case (!position && !!reference):
55972						vakata_context.reference	= reference;
55973						o = reference.offset();
55974						vakata_context.position_x	= o.left + reference.outerHeight();
55975						vakata_context.position_y	= o.top;
55976						break;
55977					case (!!position && !reference):
55978						vakata_context.position_x	= position.x;
55979						vakata_context.position_y	= position.y;
55980						break;
55981				}
55982				if(!!reference && !data && $(reference).data('vakata_contextmenu')) {
55983					data = $(reference).data('vakata_contextmenu');
55984				}
55985				if($.vakata.context._parse(data)) {
55986					vakata_context.element.html(vakata_context.html);
55987				}
55988				if(vakata_context.items.length) {
55989					vakata_context.element.appendTo(document.body);
55990					e = vakata_context.element;
55991					x = vakata_context.position_x;
55992					y = vakata_context.position_y;
55993					w = e.width();
55994					h = e.height();
55995					dw = $(window).width() + $(window).scrollLeft();
55996					dh = $(window).height() + $(window).scrollTop();
55997					if(right_to_left) {
55998						x -= (e.outerWidth() - $(reference).outerWidth());
55999						if(x < $(window).scrollLeft() + 20) {
56000							x = $(window).scrollLeft() + 20;
56001						}
56002					}
56003					if(x + w + 20 > dw) {
56004						x = dw - (w + 20);
56005					}
56006					if(y + h + 20 > dh) {
56007						y = dh - (h + 20);
56008					}
56009
56010					vakata_context.element
56011						.css({ "left" : x, "top" : y })
56012						.show()
56013						.find('a').first().focus().parent().addClass("vakata-context-hover");
56014					vakata_context.is_visible = true;
56015					/**
56016					 * triggered on the document when the contextmenu is shown
56017					 * @event
56018					 * @plugin contextmenu
56019					 * @name context_show.vakata
56020					 * @param {jQuery} reference the element that was right clicked
56021					 * @param {jQuery} element the DOM element of the menu itself
56022					 * @param {Object} position the x & y coordinates of the menu
56023					 */
56024					$.vakata.context._trigger("show");
56025				}
56026			},
56027			hide : function () {
56028				if(vakata_context.is_visible) {
56029					vakata_context.element.hide().find("ul").hide().end().find(':focus').blur().end().detach();
56030					vakata_context.is_visible = false;
56031					/**
56032					 * triggered on the document when the contextmenu is hidden
56033					 * @event
56034					 * @plugin contextmenu
56035					 * @name context_hide.vakata
56036					 * @param {jQuery} reference the element that was right clicked
56037					 * @param {jQuery} element the DOM element of the menu itself
56038					 * @param {Object} position the x & y coordinates of the menu
56039					 */
56040					$.vakata.context._trigger("hide");
56041				}
56042			}
56043		};
56044		$(function () {
56045			right_to_left = $(document.body).css("direction") === "rtl";
56046			var to = false;
56047
56048			vakata_context.element = $("<ul class='vakata-context'></ul>");
56049			vakata_context.element
56050				.on("mouseenter", "li", function (e) {
56051					e.stopImmediatePropagation();
56052
56053					if($.contains(this, e.relatedTarget)) {
56054						// премахнато заради delegate mouseleave по-долу
56055						// $(this).find(".vakata-context-hover").removeClass("vakata-context-hover");
56056						return;
56057					}
56058
56059					if(to) { clearTimeout(to); }
56060					vakata_context.element.find(".vakata-context-hover").removeClass("vakata-context-hover").end();
56061
56062					$(this)
56063						.siblings().find("ul").hide().end().end()
56064						.parentsUntil(".vakata-context", "li").addBack().addClass("vakata-context-hover");
56065					$.vakata.context._show_submenu(this);
56066				})
56067				// тестово - дали не натоварва?
56068				.on("mouseleave", "li", function (e) {
56069					if($.contains(this, e.relatedTarget)) { return; }
56070					$(this).find(".vakata-context-hover").addBack().removeClass("vakata-context-hover");
56071				})
56072				.on("mouseleave", function (e) {
56073					$(this).find(".vakata-context-hover").removeClass("vakata-context-hover");
56074					if($.vakata.context.settings.hide_onmouseleave) {
56075						to = setTimeout(
56076							(function (t) {
56077								return function () { $.vakata.context.hide(); };
56078							}(this)), $.vakata.context.settings.hide_onmouseleave);
56079					}
56080				})
56081				.on("click", "a", function (e) {
56082					e.preventDefault();
56083				//})
56084				//.on("mouseup", "a", function (e) {
56085					if(!$(this).blur().parent().hasClass("vakata-context-disabled") && $.vakata.context._execute($(this).attr("rel")) !== false) {
56086						$.vakata.context.hide();
56087					}
56088				})
56089				.on('keydown', 'a', function (e) {
56090						var o = null;
56091						switch(e.which) {
56092							case 13:
56093							case 32:
56094								e.type = "click";
56095								e.preventDefault();
56096								$(e.currentTarget).trigger(e);
56097								break;
56098							case 37:
56099								if(vakata_context.is_visible) {
56100									vakata_context.element.find(".vakata-context-hover").last().closest("li").first().find("ul").hide().find(".vakata-context-hover").removeClass("vakata-context-hover").end().end().children('a').focus();
56101									e.stopImmediatePropagation();
56102									e.preventDefault();
56103								}
56104								break;
56105							case 38:
56106								if(vakata_context.is_visible) {
56107									o = vakata_context.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").prevAll("li:not(.vakata-context-separator)").first();
56108									if(!o.length) { o = vakata_context.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").last(); }
56109									o.addClass("vakata-context-hover").children('a').focus();
56110									e.stopImmediatePropagation();
56111									e.preventDefault();
56112								}
56113								break;
56114							case 39:
56115								if(vakata_context.is_visible) {
56116									vakata_context.element.find(".vakata-context-hover").last().children("ul").show().children("li:not(.vakata-context-separator)").removeClass("vakata-context-hover").first().addClass("vakata-context-hover").children('a').focus();
56117									e.stopImmediatePropagation();
56118									e.preventDefault();
56119								}
56120								break;
56121							case 40:
56122								if(vakata_context.is_visible) {
56123									o = vakata_context.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").nextAll("li:not(.vakata-context-separator)").first();
56124									if(!o.length) { o = vakata_context.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").first(); }
56125									o.addClass("vakata-context-hover").children('a').focus();
56126									e.stopImmediatePropagation();
56127									e.preventDefault();
56128								}
56129								break;
56130							case 27:
56131								$.vakata.context.hide();
56132								e.preventDefault();
56133								break;
56134							default:
56135								//console.log(e.which);
56136								break;
56137						}
56138					})
56139				.on('keydown', function (e) {
56140					e.preventDefault();
56141					var a = vakata_context.element.find('.vakata-contextmenu-shortcut-' + e.which).parent();
56142					if(a.parent().not('.vakata-context-disabled')) {
56143						a.click();
56144					}
56145				});
56146
56147			$(document)
56148				.on("mousedown.vakata.jstree", function (e) {
56149					if(vakata_context.is_visible && vakata_context.element[0] !== e.target  && !$.contains(vakata_context.element[0], e.target)) {
56150						$.vakata.context.hide();
56151					}
56152				})
56153				.on("context_show.vakata.jstree", function (e, data) {
56154					vakata_context.element.find("li:has(ul)").children("a").addClass("vakata-context-parent");
56155					if(right_to_left) {
56156						vakata_context.element.addClass("vakata-context-rtl").css("direction", "rtl");
56157					}
56158					// also apply a RTL class?
56159					vakata_context.element.find("ul").hide().end();
56160				});
56161		});
56162	}($));
56163	// $.jstree.defaults.plugins.push("contextmenu");
56164
56165
56166/**
56167 * ### Drag'n'drop plugin
56168 *
56169 * Enables dragging and dropping of nodes in the tree, resulting in a move or copy operations.
56170 */
56171
56172	/**
56173	 * stores all defaults for the drag'n'drop plugin
56174	 * @name $.jstree.defaults.dnd
56175	 * @plugin dnd
56176	 */
56177	$.jstree.defaults.dnd = {
56178		/**
56179		 * a boolean indicating if a copy should be possible while dragging (by pressint the meta key or Ctrl). Defaults to `true`.
56180		 * @name $.jstree.defaults.dnd.copy
56181		 * @plugin dnd
56182		 */
56183		copy : true,
56184		/**
56185		 * a number indicating how long a node should remain hovered while dragging to be opened. Defaults to `500`.
56186		 * @name $.jstree.defaults.dnd.open_timeout
56187		 * @plugin dnd
56188		 */
56189		open_timeout : 500,
56190		/**
56191		 * a function invoked each time a node is about to be dragged, invoked in the tree's scope and receives the nodes about to be dragged as an argument (array) and the event that started the drag - return `false` to prevent dragging
56192		 * @name $.jstree.defaults.dnd.is_draggable
56193		 * @plugin dnd
56194		 */
56195		is_draggable : true,
56196		/**
56197		 * a boolean indicating if checks should constantly be made while the user is dragging the node (as opposed to checking only on drop), default is `true`
56198		 * @name $.jstree.defaults.dnd.check_while_dragging
56199		 * @plugin dnd
56200		 */
56201		check_while_dragging : true,
56202		/**
56203		 * a boolean indicating if nodes from this tree should only be copied with dnd (as opposed to moved), default is `false`
56204		 * @name $.jstree.defaults.dnd.always_copy
56205		 * @plugin dnd
56206		 */
56207		always_copy : false,
56208		/**
56209		 * when dropping a node "inside", this setting indicates the position the node should go to - it can be an integer or a string: "first" (same as 0) or "last", default is `0`
56210		 * @name $.jstree.defaults.dnd.inside_pos
56211		 * @plugin dnd
56212		 */
56213		inside_pos : 0,
56214		/**
56215		 * when starting the drag on a node that is selected this setting controls if all selected nodes are dragged or only the single node, default is `true`, which means all selected nodes are dragged when the drag is started on a selected node
56216		 * @name $.jstree.defaults.dnd.drag_selection
56217		 * @plugin dnd
56218		 */
56219		drag_selection : true,
56220		/**
56221		 * controls whether dnd works on touch devices. If left as boolean true dnd will work the same as in desktop browsers, which in some cases may impair scrolling. If set to boolean false dnd will not work on touch devices. There is a special third option - string "selected" which means only selected nodes can be dragged on touch devices.
56222		 * @name $.jstree.defaults.dnd.touch
56223		 * @plugin dnd
56224		 */
56225		touch : true,
56226		/**
56227		 * controls whether items can be dropped anywhere on the node, not just on the anchor, by default only the node anchor is a valid drop target. Works best with the wholerow plugin. If enabled on mobile depending on the interface it might be hard for the user to cancel the drop, since the whole tree container will be a valid drop target.
56228		 * @name $.jstree.defaults.dnd.large_drop_target
56229		 * @plugin dnd
56230		 */
56231		large_drop_target : false,
56232		/**
56233		 * controls whether a drag can be initiated from any part of the node and not just the text/icon part, works best with the wholerow plugin. Keep in mind it can cause problems with tree scrolling on mobile depending on the interface - in that case set the touch option to "selected".
56234		 * @name $.jstree.defaults.dnd.large_drag_target
56235		 * @plugin dnd
56236		 */
56237		large_drag_target : false,
56238		/**
56239		 * controls whether use HTML5 dnd api instead of classical. That will allow better integration of dnd events with other HTML5 controls.
56240		 * @reference http://caniuse.com/#feat=dragndrop
56241		 * @name $.jstree.defaults.dnd.use_html5
56242		 * @plugin dnd
56243		 */
56244		use_html5: false
56245	};
56246	var drg, elm;
56247	// TODO: now check works by checking for each node individually, how about max_children, unique, etc?
56248	$.jstree.plugins.dnd = function (options, parent) {
56249		this.init = function (el, options) {
56250			parent.init.call(this, el, options);
56251			this.settings.dnd.use_html5 = this.settings.dnd.use_html5 && ('draggable' in document.createElement('span'));
56252		};
56253		this.bind = function () {
56254			parent.bind.call(this);
56255
56256			this.element
56257				.on(this.settings.dnd.use_html5 ? 'dragstart.jstree' : 'mousedown.jstree touchstart.jstree', this.settings.dnd.large_drag_target ? '.jstree-node' : '.jstree-anchor', $.proxy(function (e) {
56258						if(this.settings.dnd.large_drag_target && $(e.target).closest('.jstree-node')[0] !== e.currentTarget) {
56259							return true;
56260						}
56261						if(e.type === "touchstart" && (!this.settings.dnd.touch || (this.settings.dnd.touch === 'selected' && !$(e.currentTarget).closest('.jstree-node').children('.jstree-anchor').hasClass('jstree-clicked')))) {
56262							return true;
56263						}
56264						var obj = this.get_node(e.target),
56265							mlt = this.is_selected(obj) && this.settings.dnd.drag_selection ? this.get_top_selected().length : 1,
56266							txt = (mlt > 1 ? mlt + ' ' + this.get_string('nodes') : this.get_text(e.currentTarget));
56267						if(this.settings.core.force_text) {
56268							txt = $.vakata.html.escape(txt);
56269						}
56270						if(obj && obj.id && obj.id !== $.jstree.root && (e.which === 1 || e.type === "touchstart" || e.type === "dragstart") &&
56271							(this.settings.dnd.is_draggable === true || ($.isFunction(this.settings.dnd.is_draggable) && this.settings.dnd.is_draggable.call(this, (mlt > 1 ? this.get_top_selected(true) : [obj]), e)))
56272						) {
56273							drg = { 'jstree' : true, 'origin' : this, 'obj' : this.get_node(obj,true), 'nodes' : mlt > 1 ? this.get_top_selected() : [obj.id] };
56274							elm = e.currentTarget;
56275							if (this.settings.dnd.use_html5) {
56276								$.vakata.dnd._trigger('start', e, { 'helper': $(), 'element': elm, 'data': drg });
56277							} else {
56278								this.element.trigger('mousedown.jstree');
56279								return $.vakata.dnd.start(e, drg, '<div id="jstree-dnd" class="jstree-' + this.get_theme() + ' jstree-' + this.get_theme() + '-' + this.get_theme_variant() + ' ' + ( this.settings.core.themes.responsive ? ' jstree-dnd-responsive' : '' ) + '"><i class="jstree-icon jstree-er"></i>' + txt + '<ins class="jstree-copy" style="display:none;">+</ins></div>');
56280							}
56281						}
56282					}, this));
56283			if (this.settings.dnd.use_html5) {
56284				this.element
56285					.on('dragover.jstree', function (e) {
56286							e.preventDefault();
56287							$.vakata.dnd._trigger('move', e, { 'helper': $(), 'element': elm, 'data': drg });
56288							return false;
56289						})
56290					//.on('dragenter.jstree', this.settings.dnd.large_drop_target ? '.jstree-node' : '.jstree-anchor', $.proxy(function (e) {
56291					//		e.preventDefault();
56292					//		$.vakata.dnd._trigger('move', e, { 'helper': $(), 'element': elm, 'data': drg });
56293					//		return false;
56294					//	}, this))
56295					.on('drop.jstree', $.proxy(function (e) {
56296							e.preventDefault();
56297							$.vakata.dnd._trigger('stop', e, { 'helper': $(), 'element': elm, 'data': drg });
56298							return false;
56299						}, this));
56300			}
56301		};
56302		this.redraw_node = function(obj, deep, callback, force_render) {
56303			obj = parent.redraw_node.apply(this, arguments);
56304			if (obj && this.settings.dnd.use_html5) {
56305				if (this.settings.dnd.large_drag_target) {
56306					obj.setAttribute('draggable', true);
56307				} else {
56308					var i, j, tmp = null;
56309					for(i = 0, j = obj.childNodes.length; i < j; i++) {
56310						if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) {
56311							tmp = obj.childNodes[i];
56312							break;
56313						}
56314					}
56315					if(tmp) {
56316						tmp.setAttribute('draggable', true);
56317					}
56318				}
56319			}
56320			return obj;
56321		};
56322	};
56323
56324	$(function() {
56325		// bind only once for all instances
56326		var lastmv = false,
56327			laster = false,
56328			lastev = false,
56329			opento = false,
56330			marker = $('<div id="jstree-marker">&#160;</div>').hide(); //.appendTo('body');
56331
56332		$(document)
56333			.on('dragover.vakata.jstree', function (e) {
56334				if (elm) {
56335					$.vakata.dnd._trigger('move', e, { 'helper': $(), 'element': elm, 'data': drg });
56336				}
56337			})
56338			.on('drop.vakata.jstree', function (e) {
56339				if (elm) {
56340					$.vakata.dnd._trigger('stop', e, { 'helper': $(), 'element': elm, 'data': drg });
56341					elm = null;
56342					drg = null;
56343				}
56344			})
56345			.on('dnd_start.vakata.jstree', function (e, data) {
56346				lastmv = false;
56347				lastev = false;
56348				if(!data || !data.data || !data.data.jstree) { return; }
56349				marker.appendTo(document.body); //.show();
56350			})
56351			.on('dnd_move.vakata.jstree', function (e, data) {
56352				var isDifferentNode = data.event.target !== lastev.target;
56353				if(opento) {
56354					if (!data.event || data.event.type !== 'dragover' || isDifferentNode) {
56355						clearTimeout(opento);
56356					}
56357				}
56358				if(!data || !data.data || !data.data.jstree) { return; }
56359
56360				// if we are hovering the marker image do nothing (can happen on "inside" drags)
56361				if(data.event.target.id && data.event.target.id === 'jstree-marker') {
56362					return;
56363				}
56364				lastev = data.event;
56365
56366				var ins = $.jstree.reference(data.event.target),
56367					ref = false,
56368					off = false,
56369					rel = false,
56370					tmp, l, t, h, p, i, o, ok, t1, t2, op, ps, pr, ip, tm, is_copy, pn;
56371				// if we are over an instance
56372				if(ins && ins._data && ins._data.dnd) {
56373					marker.attr('class', 'jstree-' + ins.get_theme() + ( ins.settings.core.themes.responsive ? ' jstree-dnd-responsive' : '' ));
56374					is_copy = data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey)));
56375					data.helper
56376						.children().attr('class', 'jstree-' + ins.get_theme() + ' jstree-' + ins.get_theme() + '-' + ins.get_theme_variant() + ' ' + ( ins.settings.core.themes.responsive ? ' jstree-dnd-responsive' : '' ))
56377						.find('.jstree-copy').first()[ is_copy ? 'show' : 'hide' ]();
56378
56379					// if are hovering the container itself add a new root node
56380					//console.log(data.event);
56381					if( (data.event.target === ins.element[0] || data.event.target === ins.get_container_ul()[0]) && ins.get_container_ul().children().length === 0) {
56382						ok = true;
56383						for(t1 = 0, t2 = data.data.nodes.length; t1 < t2; t1++) {
56384							ok = ok && ins.check( (data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey)) ) ? "copy_node" : "move_node"), (data.data.origin && data.data.origin !== ins ? data.data.origin.get_node(data.data.nodes[t1]) : data.data.nodes[t1]), $.jstree.root, 'last', { 'dnd' : true, 'ref' : ins.get_node($.jstree.root), 'pos' : 'i', 'origin' : data.data.origin, 'is_multi' : (data.data.origin && data.data.origin !== ins), 'is_foreign' : (!data.data.origin) });
56385							if(!ok) { break; }
56386						}
56387						if(ok) {
56388							lastmv = { 'ins' : ins, 'par' : $.jstree.root, 'pos' : 'last' };
56389							marker.hide();
56390							data.helper.find('.jstree-icon').first().removeClass('jstree-er').addClass('jstree-ok');
56391							if (data.event.originalEvent && data.event.originalEvent.dataTransfer) {
56392								data.event.originalEvent.dataTransfer.dropEffect = is_copy ? 'copy' : 'move';
56393							}
56394							return;
56395						}
56396					}
56397					else {
56398						// if we are hovering a tree node
56399						ref = ins.settings.dnd.large_drop_target ? $(data.event.target).closest('.jstree-node').children('.jstree-anchor') : $(data.event.target).closest('.jstree-anchor');
56400						if(ref && ref.length && ref.parent().is('.jstree-closed, .jstree-open, .jstree-leaf')) {
56401							off = ref.offset();
56402							rel = (data.event.pageY !== undefined ? data.event.pageY : data.event.originalEvent.pageY) - off.top;
56403							h = ref.outerHeight();
56404							if(rel < h / 3) {
56405								o = ['b', 'i', 'a'];
56406							}
56407							else if(rel > h - h / 3) {
56408								o = ['a', 'i', 'b'];
56409							}
56410							else {
56411								o = rel > h / 2 ? ['i', 'a', 'b'] : ['i', 'b', 'a'];
56412							}
56413							$.each(o, function (j, v) {
56414								switch(v) {
56415									case 'b':
56416										l = off.left - 6;
56417										t = off.top;
56418										p = ins.get_parent(ref);
56419										i = ref.parent().index();
56420										break;
56421									case 'i':
56422										ip = ins.settings.dnd.inside_pos;
56423										tm = ins.get_node(ref.parent());
56424										l = off.left - 2;
56425										t = off.top + h / 2 + 1;
56426										p = tm.id;
56427										i = ip === 'first' ? 0 : (ip === 'last' ? tm.children.length : Math.min(ip, tm.children.length));
56428										break;
56429									case 'a':
56430										l = off.left - 6;
56431										t = off.top + h;
56432										p = ins.get_parent(ref);
56433										i = ref.parent().index() + 1;
56434										break;
56435								}
56436								ok = true;
56437								for(t1 = 0, t2 = data.data.nodes.length; t1 < t2; t1++) {
56438									op = data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey))) ? "copy_node" : "move_node";
56439									ps = i;
56440									if(op === "move_node" && v === 'a' && (data.data.origin && data.data.origin === ins) && p === ins.get_parent(data.data.nodes[t1])) {
56441										pr = ins.get_node(p);
56442										if(ps > $.inArray(data.data.nodes[t1], pr.children)) {
56443											ps -= 1;
56444										}
56445									}
56446									ok = ok && ( (ins && ins.settings && ins.settings.dnd && ins.settings.dnd.check_while_dragging === false) || ins.check(op, (data.data.origin && data.data.origin !== ins ? data.data.origin.get_node(data.data.nodes[t1]) : data.data.nodes[t1]), p, ps, { 'dnd' : true, 'ref' : ins.get_node(ref.parent()), 'pos' : v, 'origin' : data.data.origin, 'is_multi' : (data.data.origin && data.data.origin !== ins), 'is_foreign' : (!data.data.origin) }) );
56447									if(!ok) {
56448										if(ins && ins.last_error) { laster = ins.last_error(); }
56449										break;
56450									}
56451								}
56452								if(v === 'i' && ref.parent().is('.jstree-closed') && ins.settings.dnd.open_timeout) {
56453									if (!data.event || data.event.type !== 'dragover' || isDifferentNode) {
56454										if (opento) { clearTimeout(opento); }
56455										opento = setTimeout((function (x, z) { return function () { x.open_node(z); }; }(ins, ref)), ins.settings.dnd.open_timeout);
56456									}
56457								}
56458								if(ok) {
56459									pn = ins.get_node(p, true);
56460									if (!pn.hasClass('.jstree-dnd-parent')) {
56461										$('.jstree-dnd-parent').removeClass('jstree-dnd-parent');
56462										pn.addClass('jstree-dnd-parent');
56463									}
56464									lastmv = { 'ins' : ins, 'par' : p, 'pos' : v === 'i' && ip === 'last' && i === 0 && !ins.is_loaded(tm) ? 'last' : i };
56465									marker.css({ 'left' : l + 'px', 'top' : t + 'px' }).show();
56466									data.helper.find('.jstree-icon').first().removeClass('jstree-er').addClass('jstree-ok');
56467									if (data.event.originalEvent && data.event.originalEvent.dataTransfer) {
56468										data.event.originalEvent.dataTransfer.dropEffect = is_copy ? 'copy' : 'move';
56469									}
56470									laster = {};
56471									o = true;
56472									return false;
56473								}
56474							});
56475							if(o === true) { return; }
56476						}
56477					}
56478				}
56479				$('.jstree-dnd-parent').removeClass('jstree-dnd-parent');
56480				lastmv = false;
56481				data.helper.find('.jstree-icon').removeClass('jstree-ok').addClass('jstree-er');
56482				if (data.event.originalEvent && data.event.originalEvent.dataTransfer) {
56483					//data.event.originalEvent.dataTransfer.dropEffect = 'none';
56484				}
56485				marker.hide();
56486			})
56487			.on('dnd_scroll.vakata.jstree', function (e, data) {
56488				if(!data || !data.data || !data.data.jstree) { return; }
56489				marker.hide();
56490				lastmv = false;
56491				lastev = false;
56492				data.helper.find('.jstree-icon').first().removeClass('jstree-ok').addClass('jstree-er');
56493			})
56494			.on('dnd_stop.vakata.jstree', function (e, data) {
56495				$('.jstree-dnd-parent').removeClass('jstree-dnd-parent');
56496				if(opento) { clearTimeout(opento); }
56497				if(!data || !data.data || !data.data.jstree) { return; }
56498				marker.hide().detach();
56499				var i, j, nodes = [];
56500				if(lastmv) {
56501					for(i = 0, j = data.data.nodes.length; i < j; i++) {
56502						nodes[i] = data.data.origin ? data.data.origin.get_node(data.data.nodes[i]) : data.data.nodes[i];
56503					}
56504					lastmv.ins[ data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey))) ? 'copy_node' : 'move_node' ](nodes, lastmv.par, lastmv.pos, false, false, false, data.data.origin);
56505				}
56506				else {
56507					i = $(data.event.target).closest('.jstree');
56508					if(i.length && laster && laster.error && laster.error === 'check') {
56509						i = i.jstree(true);
56510						if(i) {
56511							i.settings.core.error.call(this, laster);
56512						}
56513					}
56514				}
56515				lastev = false;
56516				lastmv = false;
56517			})
56518			.on('keyup.jstree keydown.jstree', function (e, data) {
56519				data = $.vakata.dnd._get();
56520				if(data && data.data && data.data.jstree) {
56521					if (e.type === "keyup" && e.which === 27) {
56522						if (opento) { clearTimeout(opento); }
56523						lastmv = false;
56524						laster = false;
56525						lastev = false;
56526						opento = false;
56527						marker.hide().detach();
56528						$.vakata.dnd._clean();
56529					} else {
56530						data.helper.find('.jstree-copy').first()[ data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (e.metaKey || e.ctrlKey))) ? 'show' : 'hide' ]();
56531						if(lastev) {
56532							lastev.metaKey = e.metaKey;
56533							lastev.ctrlKey = e.ctrlKey;
56534							$.vakata.dnd._trigger('move', lastev);
56535						}
56536					}
56537				}
56538			});
56539	});
56540
56541	// helpers
56542	(function ($) {
56543		$.vakata.html = {
56544			div : $('<div />'),
56545			escape : function (str) {
56546				return $.vakata.html.div.text(str).html();
56547			},
56548			strip : function (str) {
56549				return $.vakata.html.div.empty().append($.parseHTML(str)).text();
56550			}
56551		};
56552		// private variable
56553		var vakata_dnd = {
56554			element	: false,
56555			target	: false,
56556			is_down	: false,
56557			is_drag	: false,
56558			helper	: false,
56559			helper_w: 0,
56560			data	: false,
56561			init_x	: 0,
56562			init_y	: 0,
56563			scroll_l: 0,
56564			scroll_t: 0,
56565			scroll_e: false,
56566			scroll_i: false,
56567			is_touch: false
56568		};
56569		$.vakata.dnd = {
56570			settings : {
56571				scroll_speed		: 10,
56572				scroll_proximity	: 20,
56573				helper_left			: 5,
56574				helper_top			: 10,
56575				threshold			: 5,
56576				threshold_touch		: 10
56577			},
56578			_trigger : function (event_name, e, data) {
56579				if (data === undefined) {
56580					data = $.vakata.dnd._get();
56581				}
56582				data.event = e;
56583				$(document).triggerHandler("dnd_" + event_name + ".vakata", data);
56584			},
56585			_get : function () {
56586				return {
56587					"data"		: vakata_dnd.data,
56588					"element"	: vakata_dnd.element,
56589					"helper"	: vakata_dnd.helper
56590				};
56591			},
56592			_clean : function () {
56593				if(vakata_dnd.helper) { vakata_dnd.helper.remove(); }
56594				if(vakata_dnd.scroll_i) { clearInterval(vakata_dnd.scroll_i); vakata_dnd.scroll_i = false; }
56595				vakata_dnd = {
56596					element	: false,
56597					target	: false,
56598					is_down	: false,
56599					is_drag	: false,
56600					helper	: false,
56601					helper_w: 0,
56602					data	: false,
56603					init_x	: 0,
56604					init_y	: 0,
56605					scroll_l: 0,
56606					scroll_t: 0,
56607					scroll_e: false,
56608					scroll_i: false,
56609					is_touch: false
56610				};
56611				$(document).off("mousemove.vakata.jstree touchmove.vakata.jstree", $.vakata.dnd.drag);
56612				$(document).off("mouseup.vakata.jstree touchend.vakata.jstree", $.vakata.dnd.stop);
56613			},
56614			_scroll : function (init_only) {
56615				if(!vakata_dnd.scroll_e || (!vakata_dnd.scroll_l && !vakata_dnd.scroll_t)) {
56616					if(vakata_dnd.scroll_i) { clearInterval(vakata_dnd.scroll_i); vakata_dnd.scroll_i = false; }
56617					return false;
56618				}
56619				if(!vakata_dnd.scroll_i) {
56620					vakata_dnd.scroll_i = setInterval($.vakata.dnd._scroll, 100);
56621					return false;
56622				}
56623				if(init_only === true) { return false; }
56624
56625				var i = vakata_dnd.scroll_e.scrollTop(),
56626					j = vakata_dnd.scroll_e.scrollLeft();
56627				vakata_dnd.scroll_e.scrollTop(i + vakata_dnd.scroll_t * $.vakata.dnd.settings.scroll_speed);
56628				vakata_dnd.scroll_e.scrollLeft(j + vakata_dnd.scroll_l * $.vakata.dnd.settings.scroll_speed);
56629				if(i !== vakata_dnd.scroll_e.scrollTop() || j !== vakata_dnd.scroll_e.scrollLeft()) {
56630					/**
56631					 * triggered on the document when a drag causes an element to scroll
56632					 * @event
56633					 * @plugin dnd
56634					 * @name dnd_scroll.vakata
56635					 * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start
56636					 * @param {DOM} element the DOM element being dragged
56637					 * @param {jQuery} helper the helper shown next to the mouse
56638					 * @param {jQuery} event the element that is scrolling
56639					 */
56640					$.vakata.dnd._trigger("scroll", vakata_dnd.scroll_e);
56641				}
56642			},
56643			start : function (e, data, html) {
56644				if(e.type === "touchstart" && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0]) {
56645					e.pageX = e.originalEvent.changedTouches[0].pageX;
56646					e.pageY = e.originalEvent.changedTouches[0].pageY;
56647					e.target = document.elementFromPoint(e.originalEvent.changedTouches[0].pageX - window.pageXOffset, e.originalEvent.changedTouches[0].pageY - window.pageYOffset);
56648				}
56649				if(vakata_dnd.is_drag) { $.vakata.dnd.stop({}); }
56650				try {
56651					e.currentTarget.unselectable = "on";
56652					e.currentTarget.onselectstart = function() { return false; };
56653					if(e.currentTarget.style) {
56654						e.currentTarget.style.touchAction = "none";
56655						e.currentTarget.style.msTouchAction = "none";
56656						e.currentTarget.style.MozUserSelect = "none";
56657					}
56658				} catch(ignore) { }
56659				vakata_dnd.init_x	= e.pageX;
56660				vakata_dnd.init_y	= e.pageY;
56661				vakata_dnd.data		= data;
56662				vakata_dnd.is_down	= true;
56663				vakata_dnd.element	= e.currentTarget;
56664				vakata_dnd.target	= e.target;
56665				vakata_dnd.is_touch	= e.type === "touchstart";
56666				if(html !== false) {
56667					vakata_dnd.helper = $("<div id='vakata-dnd'></div>").html(html).css({
56668						"display"		: "block",
56669						"margin"		: "0",
56670						"padding"		: "0",
56671						"position"		: "absolute",
56672						"top"			: "-2000px",
56673						"lineHeight"	: "16px",
56674						"zIndex"		: "10000"
56675					});
56676				}
56677				$(document).on("mousemove.vakata.jstree touchmove.vakata.jstree", $.vakata.dnd.drag);
56678				$(document).on("mouseup.vakata.jstree touchend.vakata.jstree", $.vakata.dnd.stop);
56679				return false;
56680			},
56681			drag : function (e) {
56682				if(e.type === "touchmove" && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0]) {
56683					e.pageX = e.originalEvent.changedTouches[0].pageX;
56684					e.pageY = e.originalEvent.changedTouches[0].pageY;
56685					e.target = document.elementFromPoint(e.originalEvent.changedTouches[0].pageX - window.pageXOffset, e.originalEvent.changedTouches[0].pageY - window.pageYOffset);
56686				}
56687				if(!vakata_dnd.is_down) { return; }
56688				if(!vakata_dnd.is_drag) {
56689					if(
56690						Math.abs(e.pageX - vakata_dnd.init_x) > (vakata_dnd.is_touch ? $.vakata.dnd.settings.threshold_touch : $.vakata.dnd.settings.threshold) ||
56691						Math.abs(e.pageY - vakata_dnd.init_y) > (vakata_dnd.is_touch ? $.vakata.dnd.settings.threshold_touch : $.vakata.dnd.settings.threshold)
56692					) {
56693						if(vakata_dnd.helper) {
56694							vakata_dnd.helper.appendTo(document.body);
56695							vakata_dnd.helper_w = vakata_dnd.helper.outerWidth();
56696						}
56697						vakata_dnd.is_drag = true;
56698						$(vakata_dnd.target).one('click.vakata', false);
56699						/**
56700						 * triggered on the document when a drag starts
56701						 * @event
56702						 * @plugin dnd
56703						 * @name dnd_start.vakata
56704						 * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start
56705						 * @param {DOM} element the DOM element being dragged
56706						 * @param {jQuery} helper the helper shown next to the mouse
56707						 * @param {Object} event the event that caused the start (probably mousemove)
56708						 */
56709						$.vakata.dnd._trigger("start", e);
56710					}
56711					else { return; }
56712				}
56713
56714				var d  = false, w  = false,
56715					dh = false, wh = false,
56716					dw = false, ww = false,
56717					dt = false, dl = false,
56718					ht = false, hl = false;
56719
56720				vakata_dnd.scroll_t = 0;
56721				vakata_dnd.scroll_l = 0;
56722				vakata_dnd.scroll_e = false;
56723				$($(e.target).parentsUntil("body").addBack().get().reverse())
56724					.filter(function () {
56725						return	(/^auto|scroll$/).test($(this).css("overflow")) &&
56726								(this.scrollHeight > this.offsetHeight || this.scrollWidth > this.offsetWidth);
56727					})
56728					.each(function () {
56729						var t = $(this), o = t.offset();
56730						if(this.scrollHeight > this.offsetHeight) {
56731							if(o.top + t.height() - e.pageY < $.vakata.dnd.settings.scroll_proximity)	{ vakata_dnd.scroll_t = 1; }
56732							if(e.pageY - o.top < $.vakata.dnd.settings.scroll_proximity)				{ vakata_dnd.scroll_t = -1; }
56733						}
56734						if(this.scrollWidth > this.offsetWidth) {
56735							if(o.left + t.width() - e.pageX < $.vakata.dnd.settings.scroll_proximity)	{ vakata_dnd.scroll_l = 1; }
56736							if(e.pageX - o.left < $.vakata.dnd.settings.scroll_proximity)				{ vakata_dnd.scroll_l = -1; }
56737						}
56738						if(vakata_dnd.scroll_t || vakata_dnd.scroll_l) {
56739							vakata_dnd.scroll_e = $(this);
56740							return false;
56741						}
56742					});
56743
56744				if(!vakata_dnd.scroll_e) {
56745					d  = $(document); w = $(window);
56746					dh = d.height(); wh = w.height();
56747					dw = d.width(); ww = w.width();
56748					dt = d.scrollTop(); dl = d.scrollLeft();
56749					if(dh > wh && e.pageY - dt < $.vakata.dnd.settings.scroll_proximity)		{ vakata_dnd.scroll_t = -1;  }
56750					if(dh > wh && wh - (e.pageY - dt) < $.vakata.dnd.settings.scroll_proximity)	{ vakata_dnd.scroll_t = 1; }
56751					if(dw > ww && e.pageX - dl < $.vakata.dnd.settings.scroll_proximity)		{ vakata_dnd.scroll_l = -1; }
56752					if(dw > ww && ww - (e.pageX - dl) < $.vakata.dnd.settings.scroll_proximity)	{ vakata_dnd.scroll_l = 1; }
56753					if(vakata_dnd.scroll_t || vakata_dnd.scroll_l) {
56754						vakata_dnd.scroll_e = d;
56755					}
56756				}
56757				if(vakata_dnd.scroll_e) { $.vakata.dnd._scroll(true); }
56758
56759				if(vakata_dnd.helper) {
56760					ht = parseInt(e.pageY + $.vakata.dnd.settings.helper_top, 10);
56761					hl = parseInt(e.pageX + $.vakata.dnd.settings.helper_left, 10);
56762					if(dh && ht + 25 > dh) { ht = dh - 50; }
56763					if(dw && hl + vakata_dnd.helper_w > dw) { hl = dw - (vakata_dnd.helper_w + 2); }
56764					vakata_dnd.helper.css({
56765						left	: hl + "px",
56766						top		: ht + "px"
56767					});
56768				}
56769				/**
56770				 * triggered on the document when a drag is in progress
56771				 * @event
56772				 * @plugin dnd
56773				 * @name dnd_move.vakata
56774				 * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start
56775				 * @param {DOM} element the DOM element being dragged
56776				 * @param {jQuery} helper the helper shown next to the mouse
56777				 * @param {Object} event the event that caused this to trigger (most likely mousemove)
56778				 */
56779				$.vakata.dnd._trigger("move", e);
56780				return false;
56781			},
56782			stop : function (e) {
56783				if(e.type === "touchend" && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0]) {
56784					e.pageX = e.originalEvent.changedTouches[0].pageX;
56785					e.pageY = e.originalEvent.changedTouches[0].pageY;
56786					e.target = document.elementFromPoint(e.originalEvent.changedTouches[0].pageX - window.pageXOffset, e.originalEvent.changedTouches[0].pageY - window.pageYOffset);
56787				}
56788				if(vakata_dnd.is_drag) {
56789					/**
56790					 * triggered on the document when a drag stops (the dragged element is dropped)
56791					 * @event
56792					 * @plugin dnd
56793					 * @name dnd_stop.vakata
56794					 * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start
56795					 * @param {DOM} element the DOM element being dragged
56796					 * @param {jQuery} helper the helper shown next to the mouse
56797					 * @param {Object} event the event that caused the stop
56798					 */
56799					if (e.target !== vakata_dnd.target) {
56800						$(vakata_dnd.target).off('click.vakata');
56801					}
56802					$.vakata.dnd._trigger("stop", e);
56803				}
56804				else {
56805					if(e.type === "touchend" && e.target === vakata_dnd.target) {
56806						var to = setTimeout(function () { $(e.target).click(); }, 100);
56807						$(e.target).one('click', function() { if(to) { clearTimeout(to); } });
56808					}
56809				}
56810				$.vakata.dnd._clean();
56811				return false;
56812			}
56813		};
56814	}($));
56815
56816	// include the dnd plugin by default
56817	// $.jstree.defaults.plugins.push("dnd");
56818
56819
56820/**
56821 * ### Massload plugin
56822 *
56823 * Adds massload functionality to jsTree, so that multiple nodes can be loaded in a single request (only useful with lazy loading).
56824 */
56825
56826	/**
56827	 * massload configuration
56828	 *
56829	 * It is possible to set this to a standard jQuery-like AJAX config.
56830	 * In addition to the standard jQuery ajax options here you can supply functions for `data` and `url`, the functions will be run in the current instance's scope and a param will be passed indicating which node IDs need to be loaded, the return value of those functions will be used.
56831	 *
56832	 * You can also set this to a function, that function will receive the node IDs being loaded as argument and a second param which is a function (callback) which should be called with the result.
56833	 *
56834	 * Both the AJAX and the function approach rely on the same return value - an object where the keys are the node IDs, and the value is the children of that node as an array.
56835	 *
56836	 *	{
56837	 *		"id1" : [{ "text" : "Child of ID1", "id" : "c1" }, { "text" : "Another child of ID1", "id" : "c2" }],
56838	 *		"id2" : [{ "text" : "Child of ID2", "id" : "c3" }]
56839	 *	}
56840	 * 
56841	 * @name $.jstree.defaults.massload
56842	 * @plugin massload
56843	 */
56844	$.jstree.defaults.massload = null;
56845	$.jstree.plugins.massload = function (options, parent) {
56846		this.init = function (el, options) {
56847			this._data.massload = {};
56848			parent.init.call(this, el, options);
56849		};
56850		this._load_nodes = function (nodes, callback, is_callback, force_reload) {
56851			var s = this.settings.massload,
56852				nodesString = JSON.stringify(nodes),
56853				toLoad = [],
56854				m = this._model.data,
56855				i, j, dom;
56856			if (!is_callback) {
56857				for(i = 0, j = nodes.length; i < j; i++) {
56858					if(!m[nodes[i]] || ( (!m[nodes[i]].state.loaded && !m[nodes[i]].state.failed) || force_reload) ) {
56859						toLoad.push(nodes[i]);
56860						dom = this.get_node(nodes[i], true);
56861						if (dom && dom.length) {
56862							dom.addClass("jstree-loading").attr('aria-busy',true);
56863						}
56864					}
56865				}
56866				this._data.massload = {};
56867				if (toLoad.length) {
56868					if($.isFunction(s)) {
56869						return s.call(this, toLoad, $.proxy(function (data) {
56870							var i, j;
56871							if(data) {
56872								for(i in data) {
56873									if(data.hasOwnProperty(i)) {
56874										this._data.massload[i] = data[i];
56875									}
56876								}
56877							}
56878							for(i = 0, j = nodes.length; i < j; i++) {
56879								dom = this.get_node(nodes[i], true);
56880								if (dom && dom.length) {
56881									dom.removeClass("jstree-loading").attr('aria-busy',false);
56882								}
56883							}
56884							parent._load_nodes.call(this, nodes, callback, is_callback, force_reload);
56885						}, this));
56886					}
56887					if(typeof s === 'object' && s && s.url) {
56888						s = $.extend(true, {}, s);
56889						if($.isFunction(s.url)) {
56890							s.url = s.url.call(this, toLoad);
56891						}
56892						if($.isFunction(s.data)) {
56893							s.data = s.data.call(this, toLoad);
56894						}
56895						return $.ajax(s)
56896							.done($.proxy(function (data,t,x) {
56897									var i, j;
56898									if(data) {
56899										for(i in data) {
56900											if(data.hasOwnProperty(i)) {
56901												this._data.massload[i] = data[i];
56902											}
56903										}
56904									}
56905									for(i = 0, j = nodes.length; i < j; i++) {
56906										dom = this.get_node(nodes[i], true);
56907										if (dom && dom.length) {
56908											dom.removeClass("jstree-loading").attr('aria-busy',false);
56909										}
56910									}
56911									parent._load_nodes.call(this, nodes, callback, is_callback, force_reload);
56912								}, this))
56913							.fail($.proxy(function (f) {
56914									parent._load_nodes.call(this, nodes, callback, is_callback, force_reload);
56915								}, this));
56916					}
56917				}
56918			}
56919			return parent._load_nodes.call(this, nodes, callback, is_callback, force_reload);
56920		};
56921		this._load_node = function (obj, callback) {
56922			var data = this._data.massload[obj.id],
56923				rslt = null, dom;
56924			if(data) {
56925				rslt = this[typeof data === 'string' ? '_append_html_data' : '_append_json_data'](
56926					obj,
56927					typeof data === 'string' ? $($.parseHTML(data)).filter(function () { return this.nodeType !== 3; }) : data,
56928					function (status) { callback.call(this, status); }
56929				);
56930				dom = this.get_node(obj.id, true);
56931				if (dom && dom.length) {
56932					dom.removeClass("jstree-loading").attr('aria-busy',false);
56933				}
56934				delete this._data.massload[obj.id];
56935				return rslt;
56936			}
56937			return parent._load_node.call(this, obj, callback);
56938		};
56939	};
vendor: 3,399 bytes, lines 56939-57022
56939
56940
56941/**
56942 * ### Search plugin
56943 *
56944 * Adds search functionality to jsTree.
56945 */
56946
56947	/**
56948	 * stores all defaults for the search plugin
56949	 * @name $.jstree.defaults.search
56950	 * @plugin search
56951	 */
56952	$.jstree.defaults.search = {
56953		/**
56954		 * a jQuery-like AJAX config, which jstree uses if a server should be queried for results.
56955		 *
56956		 * A `str` (which is the search string) parameter will be added with the request, an optional `inside` parameter will be added if the search is limited to a node id. The expected result is a JSON array with nodes that need to be opened so that matching nodes will be revealed.
56957		 * Leave this setting as `false` to not query the server. You can also set this to a function, which will be invoked in the instance's scope and receive 3 parameters - the search string, the callback to call with the array of nodes to load, and the optional node ID to limit the search to
56958		 * @name $.jstree.defaults.search.ajax
56959		 * @plugin search
56960		 */
56961		ajax : false,
56962		/**
56963		 * Indicates if the search should be fuzzy or not (should `chnd3` match `child node 3`). Default is `false`.
56964		 * @name $.jstree.defaults.search.fuzzy
56965		 * @plugin search
56966		 */
56967		fuzzy : false,
56968		/**
56969		 * Indicates if the search should be case sensitive. Default is `false`.
56970		 * @name $.jstree.defaults.search.case_sensitive
56971		 * @plugin search
56972		 */
56973		case_sensitive : false,
56974		/**
56975		 * Indicates if the tree should be filtered (by default) to show only matching nodes (keep in mind this can be a heavy on large trees in old browsers).
56976		 * This setting can be changed at runtime when calling the search method. Default is `false`.
56977		 * @name $.jstree.defaults.search.show_only_matches
56978		 * @plugin search
56979		 */
56980		show_only_matches : false,
56981		/**
56982		 * Indicates if the children of matched element are shown (when show_only_matches is true)
56983		 * This setting can be changed at runtime when calling the search method. Default is `false`.
56984		 * @name $.jstree.defaults.search.show_only_matches_children
56985		 * @plugin search
56986		 */
56987		show_only_matches_children : false,
56988		/**
56989		 * Indicates if all nodes opened to reveal the search result, should be closed when the search is cleared or a new search is performed. Default is `true`.
56990		 * @name $.jstree.defaults.search.close_opened_onclear
56991		 * @plugin search
56992		 */
56993		close_opened_onclear : true,
56994		/**
56995		 * Indicates if only leaf nodes should be included in search results. Default is `false`.
56996		 * @name $.jstree.defaults.search.search_leaves_only
56997		 * @plugin search
56998		 */
56999		search_leaves_only : false,
57000		/**
57001		 * If set to a function it wil be called in the instance's scope with two arguments - search string and node (where node will be every node in the structure, so use with caution).
57002		 * If the function returns a truthy value the node will be considered a match (it might not be displayed if search_only_leaves is set to true and the node is not a leaf). Default is `false`.
57003		 * @name $.jstree.defaults.search.search_callback
57004		 * @plugin search
57005		 */
57006		search_callback : false
57007	};
57008
57009	$.jstree.plugins.search = function (options, parent) {
57010		this.bind = function () {
57011			parent.bind.call(this);
57012
57013			this._data.search.str = "";
57014			this._data.search.dom = $();
57015			this._data.search.res = [];
57016			this._data.search.opn = [];
57017			this._data.search.som = false;
57018			this._data.search.smc = false;
57019			this._data.search.hdn = [];
57020
57021			this.element
57022				.on("search.jstree", 
vendor: 44,906 bytes, lines 57022-58204
57022$.proxy(function (e, data) {
57023						if(this._data.search.som && data.res.length) {
57024							var m = this._model.data, i, j, p = [], k, l;
57025							for(i = 0, j = data.res.length; i < j; i++) {
57026								if(m[data.res[i]] && !m[data.res[i]].state.hidden) {
57027									p.push(data.res[i]);
57028									p = p.concat(m[data.res[i]].parents);
57029									if(this._data.search.smc) {
57030										for (k = 0, l = m[data.res[i]].children_d.length; k < l; k++) {
57031											if (m[m[data.res[i]].children_d[k]] && !m[m[data.res[i]].children_d[k]].state.hidden) {
57032												p.push(m[data.res[i]].children_d[k]);
57033											}
57034										}
57035									}
57036								}
57037							}
57038							p = $.vakata.array_remove_item($.vakata.array_unique(p), $.jstree.root);
57039							this._data.search.hdn = this.hide_all(true);
57040							this.show_node(p, true);
57041							this.redraw(true);
57042						}
57043					}, this))
57044				.on("clear_search.jstree", $.proxy(function (e, data) {
57045						if(this._data.search.som && data.res.length) {
57046							this.show_node(this._data.search.hdn, true);
57047							this.redraw(true);
57048						}
57049					}, this));
57050		};
57051		/**
57052		 * used to search the tree nodes for a given string
57053		 * @name search(str [, skip_async])
57054		 * @param {String} str the search string
57055		 * @param {Boolean} skip_async if set to true server will not be queried even if configured
57056		 * @param {Boolean} show_only_matches if set to true only matching nodes will be shown (keep in mind this can be very slow on large trees or old browsers)
57057		 * @param {mixed} inside an optional node to whose children to limit the search
57058		 * @param {Boolean} append if set to true the results of this search are appended to the previous search
57059		 * @plugin search
57060		 * @trigger search.jstree
57061		 */
57062		this.search = function (str, skip_async, show_only_matches, inside, append, show_only_matches_children) {
57063			if(str === false || $.trim(str.toString()) === "") {
57064				return this.clear_search();
57065			}
57066			inside = this.get_node(inside);
57067			inside = inside && inside.id ? inside.id : null;
57068			str = str.toString();
57069			var s = this.settings.search,
57070				a = s.ajax ? s.ajax : false,
57071				m = this._model.data,
57072				f = null,
57073				r = [],
57074				p = [], i, j;
57075			if(this._data.search.res.length && !append) {
57076				this.clear_search();
57077			}
57078			if(show_only_matches === undefined) {
57079				show_only_matches = s.show_only_matches;
57080			}
57081			if(show_only_matches_children === undefined) {
57082				show_only_matches_children = s.show_only_matches_children;
57083			}
57084			if(!skip_async && a !== false) {
57085				if($.isFunction(a)) {
57086					return a.call(this, str, $.proxy(function (d) {
57087							if(d && d.d) { d = d.d; }
57088							this._load_nodes(!$.isArray(d) ? [] : $.vakata.array_unique(d), function () {
57089								this.search(str, true, show_only_matches, inside, append, show_only_matches_children);
57090							});
57091						}, this), inside);
57092				}
57093				else {
57094					a = $.extend({}, a);
57095					if(!a.data) { a.data = {}; }
57096					a.data.str = str;
57097					if(inside) {
57098						a.data.inside = inside;
57099					}
57100					if (this._data.search.lastRequest) {
57101						this._data.search.lastRequest.abort();
57102					}
57103					this._data.search.lastRequest = $.ajax(a)
57104						.fail($.proxy(function () {
57105							this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'search', 'id' : 'search_01', 'reason' : 'Could not load search parents', 'data' : JSON.stringify(a) };
57106							this.settings.core.error.call(this, this._data.core.last_error);
57107						}, this))
57108						.done($.proxy(function (d) {
57109							if(d && d.d) { d = d.d; }
57110							this._load_nodes(!$.isArray(d) ? [] : $.vakata.array_unique(d), function () {
57111								this.search(str, true, show_only_matches, inside, append, show_only_matches_children);
57112							});
57113						}, this));
57114					return this._data.search.lastRequest;
57115				}
57116			}
57117			if(!append) {
57118				this._data.search.str = str;
57119				this._data.search.dom = $();
57120				this._data.search.res = [];
57121				this._data.search.opn = [];
57122				this._data.search.som = show_only_matches;
57123				this._data.search.smc = show_only_matches_children;
57124			}
57125
57126			f = new $.vakata.search(str, true, { caseSensitive : s.case_sensitive, fuzzy : s.fuzzy });
57127			$.each(m[inside ? inside : $.jstree.root].children_d, function (ii, i) {
57128				var v = m[i];
57129				if(v.text && !v.state.hidden && (!s.search_leaves_only || (v.state.loaded && v.children.length === 0)) && ( (s.search_callback && s.search_callback.call(this, str, v)) || (!s.search_callback && f.search(v.text).isMatch) ) ) {
57130					r.push(i);
57131					p = p.concat(v.parents);
57132				}
57133			});
57134			if(r.length) {
57135				p = $.vakata.array_unique(p);
57136				for(i = 0, j = p.length; i < j; i++) {
57137					if(p[i] !== $.jstree.root && m[p[i]] && this.open_node(p[i], null, 0) === true) {
57138						this._data.search.opn.push(p[i]);
57139					}
57140				}
57141				if(!append) {
57142					this._data.search.dom = $(this.element[0].querySelectorAll('#' + $.map(r, function (v) { return "0123456789".indexOf(v[0]) !== -1 ? '\\3' + v[0] + ' ' + v.substr(1).replace($.jstree.idregex,'\\$&') : v.replace($.jstree.idregex,'\\$&'); }).join(', #')));
57143					this._data.search.res = r;
57144				}
57145				else {
57146					this._data.search.dom = this._data.search.dom.add($(this.element[0].querySelectorAll('#' + $.map(r, function (v) { return "0123456789".indexOf(v[0]) !== -1 ? '\\3' + v[0] + ' ' + v.substr(1).replace($.jstree.idregex,'\\$&') : v.replace($.jstree.idregex,'\\$&'); }).join(', #'))));
57147					this._data.search.res = $.vakata.array_unique(this._data.search.res.concat(r));
57148				}
57149				this._data.search.dom.children(".jstree-anchor").addClass('jstree-search');
57150			}
57151			/**
57152			 * triggered after search is complete
57153			 * @event
57154			 * @name search.jstree
57155			 * @param {jQuery} nodes a jQuery collection of matching nodes
57156			 * @param {String} str the search string
57157			 * @param {Array} res a collection of objects represeing the matching nodes
57158			 * @plugin search
57159			 */
57160			this.trigger('search', { nodes : this._data.search.dom, str : str, res : this._data.search.res, show_only_matches : show_only_matches });
57161		};
57162		/**
57163		 * used to clear the last search (removes classes and shows all nodes if filtering is on)
57164		 * @name clear_search()
57165		 * @plugin search
57166		 * @trigger clear_search.jstree
57167		 */
57168		this.clear_search = function () {
57169			if(this.settings.search.close_opened_onclear) {
57170				this.close_node(this._data.search.opn, 0);
57171			}
57172			/**
57173			 * triggered after search is complete
57174			 * @event
57175			 * @name clear_search.jstree
57176			 * @param {jQuery} nodes a jQuery collection of matching nodes (the result from the last search)
57177			 * @param {String} str the search string (the last search string)
57178			 * @param {Array} res a collection of objects represeing the matching nodes (the result from the last search)
57179			 * @plugin search
57180			 */
57181			this.trigger('clear_search', { 'nodes' : this._data.search.dom, str : this._data.search.str, res : this._data.search.res });
57182			if(this._data.search.res.length) {
57183				this._data.search.dom = $(this.element[0].querySelectorAll('#' + $.map(this._data.search.res, function (v) {
57184					return "0123456789".indexOf(v[0]) !== -1 ? '\\3' + v[0] + ' ' + v.substr(1).replace($.jstree.idregex,'\\$&') : v.replace($.jstree.idregex,'\\$&');
57185				}).join(', #')));
57186				this._data.search.dom.children(".jstree-anchor").removeClass("jstree-search");
57187			}
57188			this._data.search.str = "";
57189			this._data.search.res = [];
57190			this._data.search.opn = [];
57191			this._data.search.dom = $();
57192		};
57193
57194		this.redraw_node = function(obj, deep, callback, force_render) {
57195			obj = parent.redraw_node.apply(this, arguments);
57196			if(obj) {
57197				if($.inArray(obj.id, this._data.search.res) !== -1) {
57198					var i, j, tmp = null;
57199					for(i = 0, j = obj.childNodes.length; i < j; i++) {
57200						if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) {
57201							tmp = obj.childNodes[i];
57202							break;
57203						}
57204					}
57205					if(tmp) {
57206						tmp.className += ' jstree-search';
57207					}
57208				}
57209			}
57210			return obj;
57211		};
57212	};
57213
57214	// helpers
57215	(function ($) {
57216		// from http://kiro.me/projects/fuse.html
57217		$.vakata.search = function(pattern, txt, options) {
57218			options = options || {};
57219			options = $.extend({}, $.vakata.search.defaults, options);
57220			if(options.fuzzy !== false) {
57221				options.fuzzy = true;
57222			}
57223			pattern = options.caseSensitive ? pattern : pattern.toLowerCase();
57224			var MATCH_LOCATION	= options.location,
57225				MATCH_DISTANCE	= options.distance,
57226				MATCH_THRESHOLD	= options.threshold,
57227				patternLen = pattern.length,
57228				matchmask, pattern_alphabet, match_bitapScore, search;
57229			if(patternLen > 32) {
57230				options.fuzzy = false;
57231			}
57232			if(options.fuzzy) {
57233				matchmask = 1 << (patternLen - 1);
57234				pattern_alphabet = (function () {
57235					var mask = {},
57236						i = 0;
57237					for (i = 0; i < patternLen; i++) {
57238						mask[pattern.charAt(i)] = 0;
57239					}
57240					for (i = 0; i < patternLen; i++) {
57241						mask[pattern.charAt(i)] |= 1 << (patternLen - i - 1);
57242					}
57243					return mask;
57244				}());
57245				match_bitapScore = function (e, x) {
57246					var accuracy = e / patternLen,
57247						proximity = Math.abs(MATCH_LOCATION - x);
57248					if(!MATCH_DISTANCE) {
57249						return proximity ? 1.0 : accuracy;
57250					}
57251					return accuracy + (proximity / MATCH_DISTANCE);
57252				};
57253			}
57254			search = function (text) {
57255				text = options.caseSensitive ? text : text.toLowerCase();
57256				if(pattern === text || text.indexOf(pattern) !== -1) {
57257					return {
57258						isMatch: true,
57259						score: 0
57260					};
57261				}
57262				if(!options.fuzzy) {
57263					return {
57264						isMatch: false,
57265						score: 1
57266					};
57267				}
57268				var i, j,
57269					textLen = text.length,
57270					scoreThreshold = MATCH_THRESHOLD,
57271					bestLoc = text.indexOf(pattern, MATCH_LOCATION),
57272					binMin, binMid,
57273					binMax = patternLen + textLen,
57274					lastRd, start, finish, rd, charMatch,
57275					score = 1,
57276					locations = [];
57277				if (bestLoc !== -1) {
57278					scoreThreshold = Math.min(match_bitapScore(0, bestLoc), scoreThreshold);
57279					bestLoc = text.lastIndexOf(pattern, MATCH_LOCATION + patternLen);
57280					if (bestLoc !== -1) {
57281						scoreThreshold = Math.min(match_bitapScore(0, bestLoc), scoreThreshold);
57282					}
57283				}
57284				bestLoc = -1;
57285				for (i = 0; i < patternLen; i++) {
57286					binMin = 0;
57287					binMid = binMax;
57288					while (binMin < binMid) {
57289						if (match_bitapScore(i, MATCH_LOCATION + binMid) <= scoreThreshold) {
57290							binMin = binMid;
57291						} else {
57292							binMax = binMid;
57293						}
57294						binMid = Math.floor((binMax - binMin) / 2 + binMin);
57295					}
57296					binMax = binMid;
57297					start = Math.max(1, MATCH_LOCATION - binMid + 1);
57298					finish = Math.min(MATCH_LOCATION + binMid, textLen) + patternLen;
57299					rd = new Array(finish + 2);
57300					rd[finish + 1] = (1 << i) - 1;
57301					for (j = finish; j >= start; j--) {
57302						charMatch = pattern_alphabet[text.charAt(j - 1)];
57303						if (i === 0) {
57304							rd[j] = ((rd[j + 1] << 1) | 1) & charMatch;
57305						} else {
57306							rd[j] = ((rd[j + 1] << 1) | 1) & charMatch | (((lastRd[j + 1] | lastRd[j]) << 1) | 1) | lastRd[j + 1];
57307						}
57308						if (rd[j] & matchmask) {
57309							score = match_bitapScore(i, j - 1);
57310							if (score <= scoreThreshold) {
57311								scoreThreshold = score;
57312								bestLoc = j - 1;
57313								locations.push(bestLoc);
57314								if (bestLoc > MATCH_LOCATION) {
57315									start = Math.max(1, 2 * MATCH_LOCATION - bestLoc);
57316								} else {
57317									break;
57318								}
57319							}
57320						}
57321					}
57322					if (match_bitapScore(i + 1, MATCH_LOCATION) > scoreThreshold) {
57323						break;
57324					}
57325					lastRd = rd;
57326				}
57327				return {
57328					isMatch: bestLoc >= 0,
57329					score: score
57330				};
57331			};
57332			return txt === true ? { 'search' : search } : search(txt);
57333		};
57334		$.vakata.search.defaults = {
57335			location : 0,
57336			distance : 100,
57337			threshold : 0.6,
57338			fuzzy : false,
57339			caseSensitive : false
57340		};
57341	}($));
57342
57343	// include the search plugin by default
57344	// $.jstree.defaults.plugins.push("search");
57345
57346
57347/**
57348 * ### Sort plugin
57349 *
57350 * Automatically sorts all siblings in the tree according to a sorting function.
57351 */
57352
57353	/**
57354	 * the settings function used to sort the nodes.
57355	 * It is executed in the tree's context, accepts two nodes as arguments and should return `1` or `-1`.
57356	 * @name $.jstree.defaults.sort
57357	 * @plugin sort
57358	 */
57359	$.jstree.defaults.sort = function (a, b) {
57360		//return this.get_type(a) === this.get_type(b) ? (this.get_text(a) > this.get_text(b) ? 1 : -1) : this.get_type(a) >= this.get_type(b);
57361		return this.get_text(a) > this.get_text(b) ? 1 : -1;
57362	};
57363	$.jstree.plugins.sort = function (options, parent) {
57364		this.bind = function () {
57365			parent.bind.call(this);
57366			this.element
57367				.on("model.jstree", $.proxy(function (e, data) {
57368						this.sort(data.parent, true);
57369					}, this))
57370				.on("rename_node.jstree create_node.jstree", $.proxy(function (e, data) {
57371						this.sort(data.parent || data.node.parent, false);
57372						this.redraw_node(data.parent || data.node.parent, true);
57373					}, this))
57374				.on("move_node.jstree copy_node.jstree", $.proxy(function (e, data) {
57375						this.sort(data.parent, false);
57376						this.redraw_node(data.parent, true);
57377					}, this));
57378		};
57379		/**
57380		 * used to sort a node's children
57381		 * @private
57382		 * @name sort(obj [, deep])
57383		 * @param  {mixed} obj the node
57384		 * @param {Boolean} deep if set to `true` nodes are sorted recursively.
57385		 * @plugin sort
57386		 * @trigger search.jstree
57387		 */
57388		this.sort = function (obj, deep) {
57389			var i, j;
57390			obj = this.get_node(obj);
57391			if(obj && obj.children && obj.children.length) {
57392				obj.children.sort($.proxy(this.settings.sort, this));
57393				if(deep) {
57394					for(i = 0, j = obj.children_d.length; i < j; i++) {
57395						this.sort(obj.children_d[i], false);
57396					}
57397				}
57398			}
57399		};
57400	};
57401
57402	// include the sort plugin by default
57403	// $.jstree.defaults.plugins.push("sort");
57404
57405/**
57406 * ### State plugin
57407 *
57408 * Saves the state of the tree (selected nodes, opened nodes) on the user's computer using available options (localStorage, cookies, etc)
57409 */
57410
57411	var to = false;
57412	/**
57413	 * stores all defaults for the state plugin
57414	 * @name $.jstree.defaults.state
57415	 * @plugin state
57416	 */
57417	$.jstree.defaults.state = {
57418		/**
57419		 * A string for the key to use when saving the current tree (change if using multiple trees in your project). Defaults to `jstree`.
57420		 * @name $.jstree.defaults.state.key
57421		 * @plugin state
57422		 */
57423		key		: 'jstree',
57424		/**
57425		 * A space separated list of events that trigger a state save. Defaults to `changed.jstree open_node.jstree close_node.jstree`.
57426		 * @name $.jstree.defaults.state.events
57427		 * @plugin state
57428		 */
57429		events	: 'changed.jstree open_node.jstree close_node.jstree check_node.jstree uncheck_node.jstree',
57430		/**
57431		 * Time in milliseconds after which the state will expire. Defaults to 'false' meaning - no expire.
57432		 * @name $.jstree.defaults.state.ttl
57433		 * @plugin state
57434		 */
57435		ttl		: false,
57436		/**
57437		 * A function that will be executed prior to restoring state with one argument - the state object. Can be used to clear unwanted parts of the state.
57438		 * @name $.jstree.defaults.state.filter
57439		 * @plugin state
57440		 */
57441		filter	: false,
57442		/**
57443		 * Should loaded nodes be restored (setting this to true means that it is possible that the whole tree will be loaded for some users - use with caution). Defaults to `false`
57444		 * @name $.jstree.defaults.state.preserve_loaded
57445		 * @plugin state
57446		 */
57447		preserve_loaded : false
57448	};
57449	$.jstree.plugins.state = function (options, parent) {
57450		this.bind = function () {
57451			parent.bind.call(this);
57452			var bind = $.proxy(function () {
57453				this.element.on(this.settings.state.events, $.proxy(function () {
57454					if(to) { clearTimeout(to); }
57455					to = setTimeout($.proxy(function () { this.save_state(); }, this), 100);
57456				}, this));
57457				/**
57458				 * triggered when the state plugin is finished restoring the state (and immediately after ready if there is no state to restore).
57459				 * @event
57460				 * @name state_ready.jstree
57461				 * @plugin state
57462				 */
57463				this.trigger('state_ready');
57464			}, this);
57465			this.element
57466				.on("ready.jstree", $.proxy(function (e, data) {
57467						this.element.one("restore_state.jstree", bind);
57468						if(!this.restore_state()) { bind(); }
57469					}, this));
57470		};
57471		/**
57472		 * save the state
57473		 * @name save_state()
57474		 * @plugin state
57475		 */
57476		this.save_state = function () {
57477			var tm = this.get_state();
57478			if (!this.settings.state.preserve_loaded) {
57479				delete tm.core.loaded;
57480			}
57481			var st = { 'state' : tm, 'ttl' : this.settings.state.ttl, 'sec' : +(new Date()) };
57482			$.vakata.storage.set(this.settings.state.key, JSON.stringify(st));
57483		};
57484		/**
57485		 * restore the state from the user's computer
57486		 * @name restore_state()
57487		 * @plugin state
57488		 */
57489		this.restore_state = function () {
57490			var k = $.vakata.storage.get(this.settings.state.key);
57491			if(!!k) { try { k = JSON.parse(k); } catch(ex) { return false; } }
57492			if(!!k && k.ttl && k.sec && +(new Date()) - k.sec > k.ttl) { return false; }
57493			if(!!k && k.state) { k = k.state; }
57494			if(!!k && $.isFunction(this.settings.state.filter)) { k = this.settings.state.filter.call(this, k); }
57495			if(!!k) {
57496				if (!this.settings.state.preserve_loaded) {
57497					delete k.core.loaded;
57498				}
57499				this.element.one("set_state.jstree", function (e, data) { data.instance.trigger('restore_state', { 'state' : $.extend(true, {}, k) }); });
57500				this.set_state(k);
57501				return true;
57502			}
57503			return false;
57504		};
57505		/**
57506		 * clear the state on the user's computer
57507		 * @name clear_state()
57508		 * @plugin state
57509		 */
57510		this.clear_state = function () {
57511			return $.vakata.storage.del(this.settings.state.key);
57512		};
57513	};
57514
57515	(function ($, undefined) {
57516		$.vakata.storage = {
57517			// simply specifying the functions in FF throws an error
57518			set : function (key, val) { return window.localStorage.setItem(key, val); },
57519			get : function (key) { return window.localStorage.getItem(key); },
57520			del : function (key) { return window.localStorage.removeItem(key); }
57521		};
57522	}($));
57523
57524	// include the state plugin by default
57525	// $.jstree.defaults.plugins.push("state");
57526
57527/**
57528 * ### Types plugin
57529 *
57530 * Makes it possible to add predefined types for groups of nodes, which make it possible to easily control nesting rules and icon for each group.
57531 */
57532
57533	/**
57534	 * An object storing all types as key value pairs, where the key is the type name and the value is an object that could contain following keys (all optional).
57535	 *
57536	 * * `max_children` the maximum number of immediate children this node type can have. Do not specify or set to `-1` for unlimited.
57537	 * * `max_depth` the maximum number of nesting this node type can have. A value of `1` would mean that the node can have children, but no grandchildren. Do not specify or set to `-1` for unlimited.
57538	 * * `valid_children` an array of node type strings, that nodes of this type can have as children. Do not specify or set to `-1` for no limits.
57539	 * * `icon` a string - can be a path to an icon or a className, if using an image that is in the current directory use a `./` prefix, otherwise it will be detected as a class. Omit to use the default icon from your theme.
57540	 * * `li_attr` an object of values which will be used to add HTML attributes on the resulting LI DOM node (merged with the node's own data)
57541	 * * `a_attr` an object of values which will be used to add HTML attributes on the resulting A DOM node (merged with the node's own data)
57542	 *
57543	 * There are two predefined types:
57544	 *
57545	 * * `#` represents the root of the tree, for example `max_children` would control the maximum number of root nodes.
57546	 * * `default` represents the default node - any settings here will be applied to all nodes that do not have a type specified.
57547	 *
57548	 * @name $.jstree.defaults.types
57549	 * @plugin types
57550	 */
57551	$.jstree.defaults.types = {
57552		'default' : {}
57553	};
57554	$.jstree.defaults.types[$.jstree.root] = {};
57555
57556	$.jstree.plugins.types = function (options, parent) {
57557		this.init = function (el, options) {
57558			var i, j;
57559			if(options && options.types && options.types['default']) {
57560				for(i in options.types) {
57561					if(i !== "default" && i !== $.jstree.root && options.types.hasOwnProperty(i)) {
57562						for(j in options.types['default']) {
57563							if(options.types['default'].hasOwnProperty(j) && options.types[i][j] === undefined) {
57564								options.types[i][j] = options.types['default'][j];
57565							}
57566						}
57567					}
57568				}
57569			}
57570			parent.init.call(this, el, options);
57571			this._model.data[$.jstree.root].type = $.jstree.root;
57572		};
57573		this.refresh = function (skip_loading, forget_state) {
57574			parent.refresh.call(this, skip_loading, forget_state);
57575			this._model.data[$.jstree.root].type = $.jstree.root;
57576		};
57577		this.bind = function () {
57578			this.element
57579				.on('model.jstree', $.proxy(function (e, data) {
57580						var m = this._model.data,
57581							dpc = data.nodes,
57582							t = this.settings.types,
57583							i, j, c = 'default', k;
57584						for(i = 0, j = dpc.length; i < j; i++) {
57585							c = 'default';
57586							if(m[dpc[i]].original && m[dpc[i]].original.type && t[m[dpc[i]].original.type]) {
57587								c = m[dpc[i]].original.type;
57588							}
57589							if(m[dpc[i]].data && m[dpc[i]].data.jstree && m[dpc[i]].data.jstree.type && t[m[dpc[i]].data.jstree.type]) {
57590								c = m[dpc[i]].data.jstree.type;
57591							}
57592							m[dpc[i]].type = c;
57593							if(m[dpc[i]].icon === true && t[c].icon !== undefined) {
57594								m[dpc[i]].icon = t[c].icon;
57595							}
57596							if(t[c].li_attr !== undefined && typeof t[c].li_attr === 'object') {
57597								for (k in t[c].li_attr) {
57598									if (t[c].li_attr.hasOwnProperty(k)) {
57599										if (k === 'id') {
57600											continue;
57601										}
57602										else if (m[dpc[i]].li_attr[k] === undefined) {
57603											m[dpc[i]].li_attr[k] = t[c].li_attr[k];
57604										}
57605										else if (k === 'class') {
57606											m[dpc[i]].li_attr['class'] = t[c].li_attr['class'] + ' ' + m[dpc[i]].li_attr['class'];
57607										}
57608									}
57609								}
57610							}
57611							if(t[c].a_attr !== undefined && typeof t[c].a_attr === 'object') {
57612								for (k in t[c].a_attr) {
57613									if (t[c].a_attr.hasOwnProperty(k)) {
57614										if (k === 'id') {
57615											continue;
57616										}
57617										else if (m[dpc[i]].a_attr[k] === undefined) {
57618											m[dpc[i]].a_attr[k] = t[c].a_attr[k];
57619										}
57620										else if (k === 'href' && m[dpc[i]].a_attr[k] === '#') {
57621											m[dpc[i]].a_attr['href'] = t[c].a_attr['href'];
57622										}
57623										else if (k === 'class') {
57624											m[dpc[i]].a_attr['class'] = t[c].a_attr['class'] + ' ' + m[dpc[i]].a_attr['class'];
57625										}
57626									}
57627								}
57628							}
57629						}
57630						m[$.jstree.root].type = $.jstree.root;
57631					}, this));
57632			parent.bind.call(this);
57633		};
57634		this.get_json = function (obj, options, flat) {
57635			var i, j,
57636				m = this._model.data,
57637				opt = options ? $.extend(true, {}, options, {no_id:false}) : {},
57638				tmp = parent.get_json.call(this, obj, opt, flat);
57639			if(tmp === false) { return false; }
57640			if($.isArray(tmp)) {
57641				for(i = 0, j = tmp.length; i < j; i++) {
57642					tmp[i].type = tmp[i].id && m[tmp[i].id] && m[tmp[i].id].type ? m[tmp[i].id].type : "default";
57643					if(options && options.no_id) {
57644						delete tmp[i].id;
57645						if(tmp[i].li_attr && tmp[i].li_attr.id) {
57646							delete tmp[i].li_attr.id;
57647						}
57648						if(tmp[i].a_attr && tmp[i].a_attr.id) {
57649							delete tmp[i].a_attr.id;
57650						}
57651					}
57652				}
57653			}
57654			else {
57655				tmp.type = tmp.id && m[tmp.id] && m[tmp.id].type ? m[tmp.id].type : "default";
57656				if(options && options.no_id) {
57657					tmp = this._delete_ids(tmp);
57658				}
57659			}
57660			return tmp;
57661		};
57662		this._delete_ids = function (tmp) {
57663			if($.isArray(tmp)) {
57664				for(var i = 0, j = tmp.length; i < j; i++) {
57665					tmp[i] = this._delete_ids(tmp[i]);
57666				}
57667				return tmp;
57668			}
57669			delete tmp.id;
57670			if(tmp.li_attr && tmp.li_attr.id) {
57671				delete tmp.li_attr.id;
57672			}
57673			if(tmp.a_attr && tmp.a_attr.id) {
57674				delete tmp.a_attr.id;
57675			}
57676			if(tmp.children && $.isArray(tmp.children)) {
57677				tmp.children = this._delete_ids(tmp.children);
57678			}
57679			return tmp;
57680		};
57681		this.check = function (chk, obj, par, pos, more) {
57682			if(parent.check.call(this, chk, obj, par, pos, more) === false) { return false; }
57683			obj = obj && obj.id ? obj : this.get_node(obj);
57684			par = par && par.id ? par : this.get_node(par);
57685			var m = obj && obj.id ? (more && more.origin ? more.origin : $.jstree.reference(obj.id)) : null, tmp, d, i, j;
57686			m = m && m._model && m._model.data ? m._model.data : null;
57687			switch(chk) {
57688				case "create_node":
57689				case "move_node":
57690				case "copy_node":
57691					if(chk !== 'move_node' || $.inArray(obj.id, par.children) === -1) {
57692						tmp = this.get_rules(par);
57693						if(tmp.max_children !== undefined && tmp.max_children !== -1 && tmp.max_children === par.children.length) {
57694							this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_01', 'reason' : 'max_children prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
57695							return false;
57696						}
57697						if(tmp.valid_children !== undefined && tmp.valid_children !== -1 && $.inArray((obj.type || 'default'), tmp.valid_children) === -1) {
57698							this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_02', 'reason' : 'valid_children prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
57699							return false;
57700						}
57701						if(m && obj.children_d && obj.parents) {
57702							d = 0;
57703							for(i = 0, j = obj.children_d.length; i < j; i++) {
57704								d = Math.max(d, m[obj.children_d[i]].parents.length);
57705							}
57706							d = d - obj.parents.length + 1;
57707						}
57708						if(d <= 0 || d === undefined) { d = 1; }
57709						do {
57710							if(tmp.max_depth !== undefined && tmp.max_depth !== -1 && tmp.max_depth < d) {
57711								this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_03', 'reason' : 'max_depth prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
57712								return false;
57713							}
57714							par = this.get_node(par.parent);
57715							tmp = this.get_rules(par);
57716							d++;
57717						} while(par);
57718					}
57719					break;
57720			}
57721			return true;
57722		};
57723		/**
57724		 * used to retrieve the type settings object for a node
57725		 * @name get_rules(obj)
57726		 * @param {mixed} obj the node to find the rules for
57727		 * @return {Object}
57728		 * @plugin types
57729		 */
57730		this.get_rules = function (obj) {
57731			obj = this.get_node(obj);
57732			if(!obj) { return false; }
57733			var tmp = this.get_type(obj, true);
57734			if(tmp.max_depth === undefined) { tmp.max_depth = -1; }
57735			if(tmp.max_children === undefined) { tmp.max_children = -1; }
57736			if(tmp.valid_children === undefined) { tmp.valid_children = -1; }
57737			return tmp;
57738		};
57739		/**
57740		 * used to retrieve the type string or settings object for a node
57741		 * @name get_type(obj [, rules])
57742		 * @param {mixed} obj the node to find the rules for
57743		 * @param {Boolean} rules if set to `true` instead of a string the settings object will be returned
57744		 * @return {String|Object}
57745		 * @plugin types
57746		 */
57747		this.get_type = function (obj, rules) {
57748			obj = this.get_node(obj);
57749			return (!obj) ? false : ( rules ? $.extend({ 'type' : obj.type }, this.settings.types[obj.type]) : obj.type);
57750		};
57751		/**
57752		 * used to change a node's type
57753		 * @name set_type(obj, type)
57754		 * @param {mixed} obj the node to change
57755		 * @param {String} type the new type
57756		 * @plugin types
57757		 */
57758		this.set_type = function (obj, type) {
57759			var m = this._model.data, t, t1, t2, old_type, old_icon, k, d, a;
57760			if($.isArray(obj)) {
57761				obj = obj.slice();
57762				for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
57763					this.set_type(obj[t1], type);
57764				}
57765				return true;
57766			}
57767			t = this.settings.types;
57768			obj = this.get_node(obj);
57769			if(!t[type] || !obj) { return false; }
57770			d = this.get_node(obj, true);
57771			if (d && d.length) {
57772				a = d.children('.jstree-anchor');
57773			}
57774			old_type = obj.type;
57775			old_icon = this.get_icon(obj);
57776			obj.type = type;
57777			if(old_icon === true || !t[old_type] || (t[old_type].icon !== undefined && old_icon === t[old_type].icon)) {
57778				this.set_icon(obj, t[type].icon !== undefined ? t[type].icon : true);
57779			}
57780
57781			// remove old type props
57782			if(t[old_type] && t[old_type].li_attr !== undefined && typeof t[old_type].li_attr === 'object') {
57783				for (k in t[old_type].li_attr) {
57784					if (t[old_type].li_attr.hasOwnProperty(k)) {
57785						if (k === 'id') {
57786							continue;
57787						}
57788						else if (k === 'class') {
57789							m[obj.id].li_attr['class'] = (m[obj.id].li_attr['class'] || '').replace(t[old_type].li_attr[k], '');
57790							if (d) { d.removeClass(t[old_type].li_attr[k]); }
57791						}
57792						else if (m[obj.id].li_attr[k] === t[old_type].li_attr[k]) {
57793							m[obj.id].li_attr[k] = null;
57794							if (d) { d.removeAttr(k); }
57795						}
57796					}
57797				}
57798			}
57799			if(t[old_type] && t[old_type].a_attr !== undefined && typeof t[old_type].a_attr === 'object') {
57800				for (k in t[old_type].a_attr) {
57801					if (t[old_type].a_attr.hasOwnProperty(k)) {
57802						if (k === 'id') {
57803							continue;
57804						}
57805						else if (k === 'class') {
57806							m[obj.id].a_attr['class'] = (m[obj.id].a_attr['class'] || '').replace(t[old_type].a_attr[k], '');
57807							if (a) { a.removeClass(t[old_type].a_attr[k]); }
57808						}
57809						else if (m[obj.id].a_attr[k] === t[old_type].a_attr[k]) {
57810							if (k === 'href') {
57811								m[obj.id].a_attr[k] = '#';
57812								if (a) { a.attr('href', '#'); }
57813							}
57814							else {
57815								delete m[obj.id].a_attr[k];
57816								if (a) { a.removeAttr(k); }
57817							}
57818						}
57819					}
57820				}
57821			}
57822
57823			// add new props
57824			if(t[type].li_attr !== undefined && typeof t[type].li_attr === 'object') {
57825				for (k in t[type].li_attr) {
57826					if (t[type].li_attr.hasOwnProperty(k)) {
57827						if (k === 'id') {
57828							continue;
57829						}
57830						else if (m[obj.id].li_attr[k] === undefined) {
57831							m[obj.id].li_attr[k] = t[type].li_attr[k];
57832							if (d) {
57833								if (k === 'class') {
57834									d.addClass(t[type].li_attr[k]);
57835								}
57836								else {
57837									d.attr(k, t[type].li_attr[k]);
57838								}
57839							}
57840						}
57841						else if (k === 'class') {
57842							m[obj.id].li_attr['class'] = t[type].li_attr[k] + ' ' + m[obj.id].li_attr['class'];
57843							if (d) { d.addClass(t[type].li_attr[k]); }
57844						}
57845					}
57846				}
57847			}
57848			if(t[type].a_attr !== undefined && typeof t[type].a_attr === 'object') {
57849				for (k in t[type].a_attr) {
57850					if (t[type].a_attr.hasOwnProperty(k)) {
57851						if (k === 'id') {
57852							continue;
57853						}
57854						else if (m[obj.id].a_attr[k] === undefined) {
57855							m[obj.id].a_attr[k] = t[type].a_attr[k];
57856							if (a) {
57857								if (k === 'class') {
57858									a.addClass(t[type].a_attr[k]);
57859								}
57860								else {
57861									a.attr(k, t[type].a_attr[k]);
57862								}
57863							}
57864						}
57865						else if (k === 'href' && m[obj.id].a_attr[k] === '#') {
57866							m[obj.id].a_attr['href'] = t[type].a_attr['href'];
57867							if (a) { a.attr('href', t[type].a_attr['href']); }
57868						}
57869						else if (k === 'class') {
57870							m[obj.id].a_attr['class'] = t[type].a_attr['class'] + ' ' + m[obj.id].a_attr['class'];
57871							if (a) { a.addClass(t[type].a_attr[k]); }
57872						}
57873					}
57874				}
57875			}
57876
57877			return true;
57878		};
57879	};
57880	// include the types plugin by default
57881	// $.jstree.defaults.plugins.push("types");
57882
57883
57884/**
57885 * ### Unique plugin
57886 *
57887 * Enforces that no nodes with the same name can coexist as siblings.
57888 */
57889
57890	/**
57891	 * stores all defaults for the unique plugin
57892	 * @name $.jstree.defaults.unique
57893	 * @plugin unique
57894	 */
57895	$.jstree.defaults.unique = {
57896		/**
57897		 * Indicates if the comparison should be case sensitive. Default is `false`.
57898		 * @name $.jstree.defaults.unique.case_sensitive
57899		 * @plugin unique
57900		 */
57901		case_sensitive : false,
57902		/**
57903		 * Indicates if white space should be trimmed before the comparison. Default is `false`.
57904		 * @name $.jstree.defaults.unique.trim_whitespace
57905		 * @plugin unique
57906		 */
57907		trim_whitespace : false,
57908		/**
57909		 * A callback executed in the instance's scope when a new node is created and the name is already taken, the two arguments are the conflicting name and the counter. The default will produce results like `New node (2)`.
57910		 * @name $.jstree.defaults.unique.duplicate
57911		 * @plugin unique
57912		 */
57913		duplicate : function (name, counter) {
57914			return name + ' (' + counter + ')';
57915		}
57916	};
57917
57918	$.jstree.plugins.unique = function (options, parent) {
57919		this.check = function (chk, obj, par, pos, more) {
57920			if(parent.check.call(this, chk, obj, par, pos, more) === false) { return false; }
57921			obj = obj && obj.id ? obj : this.get_node(obj);
57922			par = par && par.id ? par : this.get_node(par);
57923			if(!par || !par.children) { return true; }
57924			var n = chk === "rename_node" ? pos : obj.text,
57925				c = [],
57926				s = this.settings.unique.case_sensitive,
57927				w = this.settings.unique.trim_whitespace,
57928				m = this._model.data, i, j, t;
57929			for(i = 0, j = par.children.length; i < j; i++) {
57930				t = m[par.children[i]].text;
57931				if (!s) {
57932					t = t.toLowerCase();
57933				}
57934				if (w) {
57935					t = t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
57936				}
57937				c.push(t);
57938			}
57939			if(!s) { n = n.toLowerCase(); }
57940			if (w) { n = n.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); }
57941			switch(chk) {
57942				case "delete_node":
57943					return true;
57944				case "rename_node":
57945					t = obj.text || '';
57946					if (!s) {
57947						t = t.toLowerCase();
57948					}
57949					if (w) {
57950						t = t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
57951					}
57952					i = ($.inArray(n, c) === -1 || (obj.text && t === n));
57953					if(!i) {
57954						this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_01', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
57955					}
57956					return i;
57957				case "create_node":
57958					i = ($.inArray(n, c) === -1);
57959					if(!i) {
57960						this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_04', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
57961					}
57962					return i;
57963				case "copy_node":
57964					i = ($.inArray(n, c) === -1);
57965					if(!i) {
57966						this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_02', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
57967					}
57968					return i;
57969				case "move_node":
57970					i = ( (obj.parent === par.id && (!more || !more.is_multi)) || $.inArray(n, c) === -1);
57971					if(!i) {
57972						this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_03', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
57973					}
57974					return i;
57975			}
57976			return true;
57977		};
57978		this.create_node = function (par, node, pos, callback, is_loaded) {
57979			if(!node || node.text === undefined) {
57980				if(par === null) {
57981					par = $.jstree.root;
57982				}
57983				par = this.get_node(par);
57984				if(!par) {
57985					return parent.create_node.call(this, par, node, pos, callback, is_loaded);
57986				}
57987				pos = pos === undefined ? "last" : pos;
57988				if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) {
57989					return parent.create_node.call(this, par, node, pos, callback, is_loaded);
57990				}
57991				if(!node) { node = {}; }
57992				var tmp, n, dpc, i, j, m = this._model.data, s = this.settings.unique.case_sensitive, w = this.settings.unique.trim_whitespace, cb = this.settings.unique.duplicate, t;
57993				n = tmp = this.get_string('New node');
57994				dpc = [];
57995				for(i = 0, j = par.children.length; i < j; i++) {
57996					t = m[par.children[i]].text;
57997					if (!s) {
57998						t = t.toLowerCase();
57999					}
58000					if (w) {
58001						t = t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
58002					}
58003					dpc.push(t);
58004				}
58005				i = 1;
58006				t = n;
58007				if (!s) {
58008					t = t.toLowerCase();
58009				}
58010				if (w) {
58011					t = t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
58012				}
58013				while($.inArray(t, dpc) !== -1) {
58014					n = cb.call(this, tmp, (++i)).toString();
58015					t = n;
58016					if (!s) {
58017						t = t.toLowerCase();
58018					}
58019					if (w) {
58020						t = t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
58021					}
58022				}
58023				node.text = n;
58024			}
58025			return parent.create_node.call(this, par, node, pos, callback, is_loaded);
58026		};
58027	};
58028
58029	// include the unique plugin by default
58030	// $.jstree.defaults.plugins.push("unique");
58031
58032
58033/**
58034 * ### Wholerow plugin
58035 *
58036 * Makes each node appear block level. Making selection easier. May cause slow down for large trees in old browsers.
58037 */
58038
58039	var div = document.createElement('DIV');
58040	div.setAttribute('unselectable','on');
58041	div.setAttribute('role','presentation');
58042	div.className = 'jstree-wholerow';
58043	div.innerHTML = '&#160;';
58044	$.jstree.plugins.wholerow = function (options, parent) {
58045		this.bind = function () {
58046			parent.bind.call(this);
58047
58048			this.element
58049				.on('ready.jstree set_state.jstree', $.proxy(function () {
58050						this.hide_dots();
58051					}, this))
58052				.on("init.jstree loading.jstree ready.jstree", $.proxy(function () {
58053						//div.style.height = this._data.core.li_height + 'px';
58054						this.get_container_ul().addClass('jstree-wholerow-ul');
58055					}, this))
58056				.on("deselect_all.jstree", $.proxy(function (e, data) {
58057						this.element.find('.jstree-wholerow-clicked').removeClass('jstree-wholerow-clicked');
58058					}, this))
58059				.on("changed.jstree", $.proxy(function (e, data) {
58060						this.element.find('.jstree-wholerow-clicked').removeClass('jstree-wholerow-clicked');
58061						var tmp = false, i, j;
58062						for(i = 0, j = data.selected.length; i < j; i++) {
58063							tmp = this.get_node(data.selected[i], true);
58064							if(tmp && tmp.length) {
58065								tmp.children('.jstree-wholerow').addClass('jstree-wholerow-clicked');
58066							}
58067						}
58068					}, this))
58069				.on("open_node.jstree", $.proxy(function (e, data) {
58070						this.get_node(data.node, true).find('.jstree-clicked').parent().children('.jstree-wholerow').addClass('jstree-wholerow-clicked');
58071					}, this))
58072				.on("hover_node.jstree dehover_node.jstree", $.proxy(function (e, data) {
58073						if(e.type === "hover_node" && this.is_disabled(data.node)) { return; }
58074						this.get_node(data.node, true).children('.jstree-wholerow')[e.type === "hover_node"?"addClass":"removeClass"]('jstree-wholerow-hovered');
58075					}, this))
58076				.on("contextmenu.jstree", ".jstree-wholerow", $.proxy(function (e) {
58077						if (this._data.contextmenu) {
58078							e.preventDefault();
58079							var tmp = $.Event('contextmenu', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey, pageX : e.pageX, pageY : e.pageY });
58080							$(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp);
58081						}
58082					}, this))
58083				/*!
58084				.on("mousedown.jstree touchstart.jstree", ".jstree-wholerow", function (e) {
58085						if(e.target === e.currentTarget) {
58086							var a = $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor");
58087							e.target = a[0];
58088							a.trigger(e);
58089						}
58090					})
58091				*/
58092				.on("click.jstree", ".jstree-wholerow", function (e) {
58093						e.stopImmediatePropagation();
58094						var tmp = $.Event('click', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey });
58095						$(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).focus();
58096					})
58097				.on("dblclick.jstree", ".jstree-wholerow", function (e) {
58098						e.stopImmediatePropagation();
58099						var tmp = $.Event('dblclick', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey });
58100						$(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).focus();
58101					})
58102				.on("click.jstree", ".jstree-leaf > .jstree-ocl", $.proxy(function (e) {
58103						e.stopImmediatePropagation();
58104						var tmp = $.Event('click', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey });
58105						$(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).focus();
58106					}, this))
58107				.on("mouseover.jstree", ".jstree-wholerow, .jstree-icon", $.proxy(function (e) {
58108						e.stopImmediatePropagation();
58109						if(!this.is_disabled(e.currentTarget)) {
58110							this.hover_node(e.currentTarget);
58111						}
58112						return false;
58113					}, this))
58114				.on("mouseleave.jstree", ".jstree-node", $.proxy(function (e) {
58115						this.dehover_node(e.currentTarget);
58116					}, this));
58117		};
58118		this.teardown = function () {
58119			if(this.settings.wholerow) {
58120				this.element.find(".jstree-wholerow").remove();
58121			}
58122			parent.teardown.call(this);
58123		};
58124		this.redraw_node = function(obj, deep, callback, force_render) {
58125			obj = parent.redraw_node.apply(this, arguments);
58126			if(obj) {
58127				var tmp = div.cloneNode(true);
58128				//tmp.style.height = this._data.core.li_height + 'px';
58129				if($.inArray(obj.id, this._data.core.selected) !== -1) { tmp.className += ' jstree-wholerow-clicked'; }
58130				if(this._data.core.focused && this._data.core.focused === obj.id) { tmp.className += ' jstree-wholerow-hovered'; }
58131				obj.insertBefore(tmp, obj.childNodes[0]);
58132			}
58133			return obj;
58134		};
58135	};
58136	// include the wholerow plugin by default
58137	// $.jstree.defaults.plugins.push("wholerow");
58138	if(window.customElements && Object && Object.create) {
58139		var proto = Object.create(HTMLElement.prototype);
58140		proto.createdCallback = function () {
58141			var c = { core : {}, plugins : [] }, i;
58142			for(i in $.jstree.plugins) {
58143				if($.jstree.plugins.hasOwnProperty(i) && this.attributes[i]) {
58144					c.plugins.push(i);
58145					if(this.getAttribute(i) && JSON.parse(this.getAttribute(i))) {
58146						c[i] = JSON.parse(this.getAttribute(i));
58147					}
58148				}
58149			}
58150			for(i in $.jstree.defaults.core) {
58151				if($.jstree.defaults.core.hasOwnProperty(i) && this.attributes[i]) {
58152					c.core[i] = JSON.parse(this.getAttribute(i)) || this.getAttribute(i);
58153				}
58154			}
58155			$(this).jstree(c);
58156		};
58157		// proto.attributeChangedCallback = function (name, previous, value) { };
58158		try {
58159			window.customElements.define("vakata-jstree", function() {}, { prototype: proto });
58160		} catch (ignore) { }
58161	}
58162
58163}));
58164// ┌───────────────────────────────────────────────────────────────────────────────────────────────────────┐ \\
58165// │ Raphaël 2.2.0 - JavaScript Vector Library                                                             │ \\
58166// ├───────────────────────────────────────────────────────────────────────────────────────────────────────┤ \\
58167// │ Copyright © 2008-2016 Dmitry Baranovskiy (http://raphaeljs.com)                                       │ \\
58168// │ Copyright © 2008-2016 Sencha Labs (http://sencha.com)                                                 │ \\
58169// ├───────────────────────────────────────────────────────────────────────────────────────────────────────┤ \\
58170// │ Licensed under the MIT (https://github.com/DmitryBaranovskiy/raphael/blob/master/license.txt) license.│ \\
58171// └───────────────────────────────────────────────────────────────────────────────────────────────────────┘ \\
58172
58173(function webpackUniversalModuleDefinition(root, factory) {
58174	if(typeof exports === 'object' && typeof module === 'object')
58175		module.exports = factory();
58176	else if(typeof define === 'function' && define.amd)
58177		define([], factory);
58178	else if(typeof exports === 'object')
58179		exports["Raphael"] = factory();
58180	else
58181		root["Raphael"] = factory();
58182})(this, function() {
58183return /******/ (function(modules) { // webpackBootstrap
58184/******/ 	// The module cache
58185/******/ 	var installedModules = {};
58186
58187/******/ 	// The require function
58188/******/ 	function __webpack_require__(moduleId) {
58189
58190/******/ 		// Check if module is in cache
58191/******/ 		if(installedModules[moduleId])
58192/******/ 			return installedModules[moduleId].exports;
58193
58194/******/ 		// Create a new module (and put it into the cache)
58195/******/ 		var module = installedModules[moduleId] = {
58196/******/ 			exports: {},
58197/******/ 			id: moduleId,
58198/******/ 			loaded: false
58199/******/ 		};
58200
58201/******/ 		// Execute the module function
58202/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
58203
58204/******/ 		// Flag the module as loaded
58205/******/ 		module.loaded = true;
58206
58207/******/ 		// Return the exports of the module
58208/******/ 		return module.exports;
58209/******/ 	}
58210
58211
58212/******/ 	// expose the modules object (__webpack_modules__)
58213/******/ 	__webpack_require__.m = modules;
58214
58215/******/ 	// expose the module cache
58216/******/ 	__webpack_require__.c = installedModules;
58217
58218/******/ 	// __webpack_public_path__
58219/******/ 	__webpack_require__.p = "";
58220
58221/******/ 	// Load entry module and return exports
58222/******/ 	return __webpack_require__(0);
58223/******/ })
58224/************************************************************************/
58225/******/ ([
58226/* 0 */
58227/***/ function(module, exports, __webpack_require__) {
58228
58229	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1), __webpack_require__(3), __webpack_require__(4)], __WEBPACK_AMD_DEFINE_RESULT__ = function(R) {
58230
58231	    return R;
58232
58233	}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
58234
58235/***/ },
58236/* 1 */
58237/***/ function(module, exports, __webpack_require__) {
58238
58239	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(2)], __WEBPACK_AMD_DEFINE_RESULT__ = function(eve) {
58240
58241	    /*\
58242	     * Raphael
58243	     [ method ]
58244	     **
58245	     * Creates a canvas object on which to draw.
58246	     * You must do this first, as all future calls to drawing methods
58247	     * from this instance will be bound to this canvas.
58248	     > Parameters
58249	     **
58250	     - container (HTMLElement|string) DOM element or its ID which is going to be a parent for drawing surface
58251	     - width (number)
58252	     - height (number)
58253	     - callback (function) #optional callback function which is going to be executed in the context of newly created paper
58254	     * or
58255	     - x (number)
58256	     - y (number)
58257	     - width (number)
58258	     - height (number)
58259	     - callback (function) #optional callback function which is going to be executed in the context of newly created paper
58260	     * or
58261	     - all (array) (first 3 or 4 elements in the array are equal to [containerID, width, height] or [x, y, width, height]. The rest are element descriptions in format {type: type, <attributes>}). See @Paper.add.
58262	     - callback (function) #optional callback function which is going to be executed in the context of newly created paper
58263	     * or
58264	     - onReadyCallback (function) function that is going to be called on DOM ready event. You can also subscribe to this event via Eve’s “DOMLoad” event. In this case method returns `undefined`.
58265	     = (object) @Paper
58266	     > Usage
58267	     | // Each of the following examples create a canvas
58268	     | // that is 320px wide by 200px high.
58269	     | // Canvas is created at the viewport’s 10,50 coordinate.
58270	     | var paper = Raphael(10, 50, 320, 200);
58271	     | // Canvas is created at the top left corner of the #notepad element
58272	     | // (or its top right corner in dir="rtl" elements)
58273	     | var paper = Raphael(document.getElementById("notepad"), 320, 200);
58274	     | // Same as above
58275	     | var paper = Raphael("notepad", 320, 200);
58276	     | // Image dump
58277	     | var set = Raphael(["notepad", 320, 200, {
58278	     |     type: "rect",
58279	     |     x: 10,
58280	     |     y: 10,
58281	     |     width: 25,
58282	     |     height: 25,
58283	     |     stroke: "#f00"
58284	     | }, {
58285	     |     type: "text",
58286	     |     x: 30,
58287	     |     y: 40,
58288	     |     text: "Dump"
58289	     | }]);
58290	    \*/
58291	    function R(first) {
58292	        if (R.is(first, "function")) {
58293	            return loaded ? first() : eve.on("raphael.DOMload", first);
58294	        } else if (R.is(first, array)) {
58295	            return R._engine.create[apply](R, first.splice(0, 3 + R.is(first[0], nu))).add(first);
58296	        } else {
58297	            var args = Array.prototype.slice.call(arguments, 0);
58298	            if (R.is(args[args.length - 1], "function")) {
58299	                var f = args.pop();
58300	                return loaded ? f.call(R._engine.create[apply](R, args)) : eve.on("raphael.DOMload", function () {
58301	                    f.call(R._engine.create[apply](R, args));
58302	                });
58303	            } else {
58304	                return R._engine.create[apply](R, arguments);
58305	            }
58306	        }
58307	    }
58308	    R.version = "2.2.0";
58309	    R.eve = eve;
58310	    var loaded,
58311	        separator = /[, ]+/,
58312	        elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1},
58313	        formatrg = /\{(\d+)\}/g,
58314	        proto = "prototype",
58315	        has = "hasOwnProperty",
58316	        g = {
58317	            doc: document,
58318	            win: window
58319	        },
58320	        oldRaphael = {
58321	            was: Object.prototype[has].call(g.win, "Raphael"),
58322	            is: g.win.Raphael
58323	        },
58324	        Paper = function () {
58325	            /*\
58326	             * Paper.ca
58327	             [ property (object) ]
58328	             **
58329	             * Shortcut for @Paper.customAttributes
58330	            \*/
58331	            /*\
58332	             * Paper.customAttributes
58333	             [ property (object) ]
58334	             **
58335	             * If you have a set of attributes that you would like to represent
58336	             * as a function of some number you can do it easily with custom attributes:
58337	             > Usage
58338	             | paper.customAttributes.hue = function (num) {
58339	             |     num = num % 1;
58340	             |     return {fill: "hsb(" + num + ", 0.75, 1)"};
58341	             | };
58342	             | // Custom attribute “hue” will change fill
58343	             | // to be given hue with fixed saturation and brightness.
58344	             | // Now you can use it like this:
58345	             | var c = paper.circle(10, 10, 10).attr({hue: .45});
58346	             | // or even like this:
58347	             | c.animate({hue: 1}, 1e3);
58348	             |
58349	             | // You could also create custom attribute
58350	             | // with multiple parameters:
58351	             | paper.customAttributes.hsb = function (h, s, b) {
58352	             |     return {fill: "hsb(" + [h, s, b].join(",") + ")"};
58353	             | };
58354	             | c.attr({hsb: "0.5 .8 1"});
58355	             | c.animate({hsb: [1, 0, 0.5]}, 1e3);
58356	            \*/
58357	            this.ca = this.customAttributes = {};
58358	        },
58359	        paperproto,
58360	        appendChild = "appendChild",
58361	        apply = "apply",
58362	        concat = "concat",
58363	        supportsTouch = ('ontouchstart' in g.win) || g.win.DocumentTouch && g.doc instanceof DocumentTouch, //taken from Modernizr touch test
58364	        E = "",
58365	        S = " ",
58366	        Str = String,
58367	        split = "split",
58368	        events = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel"[split](S),
58369	        touchMap = {
58370	            mousedown: "touchstart",
58371	            mousemove: "touchmove",
58372	            mouseup: "touchend"
58373	        },
58374	        lowerCase = Str.prototype.toLowerCase,
58375	        math = Math,
58376	        mmax = math.max,
58377	        mmin = math.min,
58378	        abs = math.abs,
58379	        pow = math.pow,
58380	        PI = math.PI,
58381	        nu = "number",
58382	        string = "string",
58383	        array = "array",
58384	        toString = "toString",
58385	        fillString = "fill",
58386	        objectToString = Object.prototype.toString,
58387	        paper = {},
58388	        push = "push",
58389	        ISURL = R._ISURL = /^url\(['"]?(.+?)['"]?\)$/i,
58390	        colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i,
58391	        isnan = {"NaN": 1, "Infinity": 1, "-Infinity": 1},
58392	        bezierrg = /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,
58393	        round = math.round,
58394	        setAttribute = "setAttribute",
58395	        toFloat = parseFloat,
58396	        toInt = parseInt,
58397	        upperCase = Str.prototype.toUpperCase,
58398	        availableAttrs = R._availableAttrs = {
58399	            "arrow-end": "none",
58400	            "arrow-start": "none",
58401	            blur: 0,
58402	            "clip-rect": "0 0 1e9 1e9",
58403	            cursor: "default",
58404	            cx: 0,
58405	            cy: 0,
58406	            fill: "#fff",
58407	            "fill-opacity": 1,
58408	            font: '10px "Arial"',
58409	            "font-family": '"Arial"',
58410	            "font-size": "10",
58411	            "font-style": "normal",
58412	            "font-weight": 400,
58413	            gradient: 0,
58414	            height: 0,
58415	            href: "http://raphaeljs.com/",
58416	            "letter-spacing": 0,
58417	            opacity: 1,
58418	            path: "M0,0",
58419	            r: 0,
58420	            rx: 0,
58421	            ry: 0,
58422	            src: "",
58423	            stroke: "#000",
58424	            "stroke-dasharray": "",
58425	            "stroke-linecap": "butt",
58426	            "stroke-linejoin": "butt",
58427	            "stroke-miterlimit": 0,
58428	            "stroke-opacity": 1,
58429	            "stroke-width": 1,
58430	            target: "_blank",
58431	            "text-anchor": "middle",
58432	            title: "Raphael",
58433	            transform: "",
58434	            width: 0,
58435	            x: 0,
58436	            y: 0,
58437	            "class": ""
58438	        },
58439	        availableAnimAttrs = R._availableAnimAttrs = {
58440	            blur: nu,
58441	            "clip-rect": "csv",
58442	            cx: nu,
58443	            cy: nu,
58444	            fill: "colour",
58445	            "fill-opacity": nu,
58446	            "font-size": nu,
58447	            height: nu,
58448	            opacity: nu,
58449	            path: "path",
58450	            r: nu,
58451	            rx: nu,
58452	            ry: nu,
58453	            stroke: "colour",
58454	            "stroke-opacity": nu,
58455	            "stroke-width": nu,
58456	            transform: "transform",
58457	            width: nu,
58458	            x: nu,
58459	            y: nu
58460	        },
58461	        whitespace = /[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]/g,
58462	        commaSpaces = /[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/,
58463	        hsrg = {hs: 1, rg: 1},
58464	        p2s = /,?([achlmqrstvxz]),?/gi,
58465	        pathCommand = /([achlmrqstvz])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/ig,
58466	        tCommand = /([rstm])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/ig,
58467	        pathValues = /(-?\d*\.?\d*(?:e[\-+]?\d+)?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/ig,
58468	        radial_gradient = R._radial_gradient = /^r(?:\(([^,]+?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*([^\)]+?)\))?/,
58469	        eldata = {},
58470	        sortByKey = function (a, b) {
58471	            return a.key - b.key;
58472	        },
58473	        sortByNumber = function (a, b) {
58474	            return toFloat(a) - toFloat(b);
58475	        },
58476	        fun = function () {},
58477	        pipe = function (x) {
58478	            return x;
58479	        },
58480	        rectPath = R._rectPath = function (x, y, w, h, r) {
58481	            if (r) {
58482	                return [["M", x + r, y], ["l", w - r * 2, 0], ["a", r, r, 0, 0, 1, r, r], ["l", 0, h - r * 2], ["a", r, r, 0, 0, 1, -r, r], ["l", r * 2 - w, 0], ["a", r, r, 0, 0, 1, -r, -r], ["l", 0, r * 2 - h], ["a", r, r, 0, 0, 1, r, -r], ["z"]];
58483	            }
58484	            return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]];
58485	        },
58486	        ellipsePath = function (x, y, rx, ry) {
58487	            if (ry == null) {
58488	                ry = rx;
58489	            }
58490	            return [["M", x, y], ["m", 0, -ry], ["a", rx, ry, 0, 1, 1, 0, 2 * ry], ["a", rx, ry, 0, 1, 1, 0, -2 * ry], ["z"]];
58491	        },
58492	        getPath = R._getPath = {
58493	            path: function (el) {
58494	                return el.attr("path");
58495	            },
58496	            circle: function (el) {
58497	                var a = el.attrs;
58498	                return ellipsePath(a.cx, a.cy, a.r);
58499	            },
58500	            ellipse: function (el) {
58501	                var a = el.attrs;
58502	                return ellipsePath(a.cx, a.cy, a.rx, a.ry);
58503	            },
58504	            rect: function (el) {
58505	                var a = el.attrs;
58506	                return rectPath(a.x, a.y, a.width, a.height, a.r);
58507	            },
58508	            image: function (el) {
58509	                var a = el.attrs;
58510	                return rectPath(a.x, a.y, a.width, a.height);
58511	            },
58512	            text: function (el) {
58513	                var bbox = el._getBBox();
58514	                return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
58515	            },
58516	            set : function(el) {
58517	                var bbox = el._getBBox();
58518	                return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
58519	            }
58520	        },
58521	        /*\
58522	         * Raphael.mapPath
58523	         [ method ]
58524	         **
58525	         * Transform the path string with given matrix.
58526	         > Parameters
58527	         - path (string) path string
58528	         - matrix (object) see @Matrix
58529	         = (string) transformed path string
58530	        \*/
58531	        mapPath = R.mapPath = function (path, matrix) {
58532	            if (!matrix) {
58533	                return path;
58534	            }
58535	            var x, y, i, j, ii, jj, pathi;
58536	            path = path2curve(path);
58537	            for (i = 0, ii = path.length; i < ii; i++) {
58538	                pathi = path[i];
58539	                for (j = 1, jj = pathi.length; j < jj; j += 2) {
58540	                    x = matrix.x(pathi[j], pathi[j + 1]);
58541	                    y = matrix.y(pathi[j], pathi[j + 1]);
58542	                    pathi[j] = x;
58543	                    pathi[j + 1] = y;
58544	                }
58545	            }
58546	            return path;
58547	        };
58548
58549	    R._g = g;
58550	    /*\
58551	     * Raphael.type
58552	     [ property (string) ]
58553	     **
58554	     * Can be “SVG”, “VML” or empty, depending on browser support.
58555	    \*/
58556	    R.type = (g.win.SVGAngle || g.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML");
58557	    if (R.type == "VML") {
58558	        var d = g.doc.createElement("div"),
58559	            b;
58560	        d.innerHTML = '<v:shape adj="1"/>';
58561	        b = d.firstChild;
58562	        b.style.behavior = "url(#default#VML)";
58563	        if (!(b && typeof b.adj == "object")) {
58564	            return (R.type = E);
58565	        }
58566	        d = null;
58567	    }
58568	    /*\
58569	     * Raphael.svg
58570	     [ property (boolean) ]
58571	     **
58572	     * `true` if browser supports SVG.
58573	    \*/
58574	    /*\
58575	     * Raphael.vml
58576	     [ property (boolean) ]
58577	     **
58578	     * `true` if browser supports VML.
58579	    \*/
58580	    R.svg = !(R.vml = R.type == "VML");
58581	    R._Paper = Paper;
58582	    /*\
58583	     * Raphael.fn
58584	     [ property (object) ]
58585	     **
58586	     * You can add your own method to the canvas. For example if you want to draw a pie chart,
58587	     * you can create your own pie chart function and ship it as a Raphaël plugin. To do this
58588	     * you need to extend the `Raphael.fn` object. You should modify the `fn` object before a
58589	     * Raphaël instance is created, otherwise it will take no effect. Please note that the
58590	     * ability for namespaced plugins was removed in Raphael 2.0. It is up to the plugin to
58591	     * ensure any namespacing ensures proper context.
58592	     > Usage
58593	     | Raphael.fn.arrow = function (x1, y1, x2, y2, size) {
58594	     |     return this.path( ... );
58595	     | };
58596	     | // or create namespace
58597	     | Raphael.fn.mystuff = {
58598	     |     arrow: function () {…},
58599	     |     star: function () {…},
58600	     |     // etc…
58601	     | };
58602	     | var paper = Raphael(10, 10, 630, 480);
58603	     | // then use it
58604	     | paper.arrow(10, 10, 30, 30, 5).attr({fill: "#f00"});
58605	     | paper.mystuff.arrow();
58606	     | paper.mystuff.star();
58607	    \*/
58608	    R.fn = paperproto = Paper.prototype = R.prototype;
58609	    R._id = 0;
58610	    /*\
58611	     * Raphael.is
58612	     [ method ]
58613	     **
58614	     * Handful of replacements for `typeof` operator.
58615	     > Parameters
58616	     - o (…) any object or primitive
58617	     - type (string) name of the type, i.e. “string”, “function”, “number”, etc.
58618	     = (boolean) is given value is of given type
58619	    \*/
58620	    R.is = function (o, type) {
58621	        type = lowerCase.call(type);
58622	        if (type == "finite") {
58623	            return !isnan[has](+o);
58624	        }
58625	        if (type == "array") {
58626	            return o instanceof Array;
58627	        }
58628	        return  (type == "null" && o === null) ||
58629	                (type == typeof o && o !== null) ||
58630	                (type == "object" && o === Object(o)) ||
58631	                (type == "array" && Array.isArray && Array.isArray(o)) ||
58632	                objectToString.call(o).slice(8, -1).toLowerCase() == type;
58633	    };
58634
58635	    function clone(obj) {
58636	        if (typeof obj == "function" || Object(obj) !== obj) {
58637	            return obj;
58638	        }
58639	        var res = new obj.constructor;
58640	        for (var key in obj) if (obj[has](key)) {
58641	            res[key] = clone(obj[key]);
58642	        }
58643	        return res;
58644	    }
58645
58646	    /*\
58647	     * Raphael.angle
58648	     [ method ]
58649	     **
58650	     * Returns angle between two or three points
58651	     > Parameters
58652	     - x1 (number) x coord of first point
58653	     - y1 (number) y coord of first point
58654	     - x2 (number) x coord of second point
58655	     - y2 (number) y coord of second point
58656	     - x3 (number) #optional x coord of third point
58657	     - y3 (number) #optional y coord of third point
58658	     = (number) angle in degrees.
58659	    \*/
58660	    R.angle = function (x1, y1, x2, y2, x3, y3) {
58661	        if (x3 == null) {
58662	            var x = x1 - x2,
58663	                y = y1 - y2;
58664	            if (!x && !y) {
58665	                return 0;
58666	            }
58667	            return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360;
58668	        } else {
58669	            return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3);
58670	        }
58671	    };
58672	    /*\
58673	     * Raphael.rad
58674	     [ method ]
58675	     **
58676	     * Transform angle to radians
58677	     > Parameters
58678	     - deg (number) angle in degrees
58679	     = (number) angle in radians.
58680	    \*/
58681	    R.rad = function (deg) {
58682	        return deg % 360 * PI / 180;
58683	    };
58684	    /*\
58685	     * Raphael.deg
58686	     [ method ]
58687	     **
58688	     * Transform angle to degrees
58689	     > Parameters
58690	     - rad (number) angle in radians
58691	     = (number) angle in degrees.
58692	    \*/
58693	    R.deg = function (rad) {
58694	        return Math.round ((rad * 180 / PI% 360)* 1000) / 1000;
58695	    };
58696	    /*\
58697	     * Raphael.snapTo
58698	     [ method ]
58699	     **
58700	     * Snaps given value to given grid.
58701	     > Parameters
58702	     - values (array|number) given array of values or step of the grid
58703	     - value (number) value to adjust
58704	     - tolerance (number) #optional tolerance for snapping. Default is `10`.
58705	     = (number) adjusted value.
58706	    \*/
58707	    R.snapTo = function (values, value, tolerance) {
58708	        tolerance = R.is(tolerance, "finite") ? tolerance : 10;
58709	        if (R.is(values, array)) {
58710	            var i = values.length;
58711	            while (i--) if (abs(values[i] - value) <= tolerance) {
58712	                return values[i];
58713	            }
58714	        } else {
58715	            values = +values;
58716	            var rem = value % values;
58717	            if (rem < tolerance) {
58718	                return value - rem;
58719	            }
58720	            if (rem > values - tolerance) {
58721	                return value - rem + values;
58722	            }
58723	        }
58724	        return value;
58725	    };
58726
58727	    /*\
58728	     * Raphael.createUUID
58729	     [ method ]
58730	     **
58731	     * Returns RFC4122, version 4 ID
58732	    \*/
58733	    var createUUID = R.createUUID = (function (uuidRegEx, uuidReplacer) {
58734	        return function () {
58735	            return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(uuidRegEx, uuidReplacer).toUpperCase();
58736	        };
58737	    })(/[xy]/g, function (c) {
58738	        var r = math.random() * 16 | 0,
58739	            v = c == "x" ? r : (r & 3 | 8);
58740	        return v.toString(16);
58741	    });
58742
58743	    /*\
58744	     * Raphael.setWindow
58745	     [ method ]
58746	     **
58747	     * Used when you need to draw in `&lt;iframe>`. Switched window to the iframe one.
58748	     > Parameters
58749	     - newwin (window) new window object
58750	    \*/
58751	    R.setWindow = function (newwin) {
58752	        eve("raphael.setWindow", R, g.win, newwin);
58753	        g.win = newwin;
58754	        g.doc = g.win.document;
58755	        if (R._engine.initWin) {
58756	            R._engine.initWin(g.win);
58757	        }
58758	    };
58759	    var toHex = function (color) {
58760	        if (R.vml) {
58761	            // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/
58762	            var trim = /^\s+|\s+$/g;
58763	            var bod;
58764	            try {
58765	                var docum = new ActiveXObject("htmlfile");
58766	                docum.write("<body>");
58767	                docum.close();
58768	                bod = docum.body;
58769	            } catch(e) {
58770	                bod = createPopup().document.body;
58771	            }
58772	            var range = bod.createTextRange();
58773	            toHex = cacher(function (color) {
58774	                try {
58775	                    bod.style.color = Str(color).replace(trim, E);
58776	                    var value = range.queryCommandValue("ForeColor");
58777	                    value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16);
58778	                    return "#" + ("000000" + value.toString(16)).slice(-6);
58779	                } catch(e) {
58780	                    return "none";
58781	                }
58782	            });
58783	        } else {
58784	            var i = g.doc.createElement("i");
58785	            i.title = "Rapha\xebl Colour Picker";
58786	            i.style.display = "none";
58787	            g.doc.body.appendChild(i);
58788	            toHex = cacher(function (color) {
58789	                i.style.color = color;
58790	                return g.doc.defaultView.getComputedStyle(i, E).getPropertyValue("color");
58791	            });
58792	        }
58793	        return toHex(color);
58794	    },
58795	    hsbtoString = function () {
58796	        return "hsb(" + [this.h, this.s, this.b] + ")";
58797	    },
58798	    hsltoString = function () {
58799	        return "hsl(" + [this.h, this.s, this.l] + ")";
58800	    },
58801	    rgbtoString = function () {
58802	        return this.hex;
58803	    },
58804	    prepareRGB = function (r, g, b) {
58805	        if (g == null && R.is(r, "object") && "r" in r && "g" in r && "b" in r) {
58806	            b = r.b;
58807	            g = r.g;
58808	            r = r.r;
58809	        }
58810	        if (g == null && R.is(r, string)) {
58811	            var clr = R.getRGB(r);
58812	            r = clr.r;
58813	            g = clr.g;
58814	            b = clr.b;
58815	        }
58816	        if (r > 1 || g > 1 || b > 1) {
58817	            r /= 255;
58818	            g /= 255;
58819	            b /= 255;
58820	        }
58821
58822	        return [r, g, b];
58823	    },
58824	    packageRGB = function (r, g, b, o) {
58825	        r *= 255;
58826	        g *= 255;
58827	        b *= 255;
58828	        var rgb = {
58829	            r: r,
58830	            g: g,
58831	            b: b,
58832	            hex: R.rgb(r, g, b),
58833	            toString: rgbtoString
58834	        };
58835	        R.is(o, "finite") && (rgb.opacity = o);
58836	        return rgb;
58837	    };
58838
58839	    /*\
58840	     * Raphael.color
58841	     [ method ]
58842	     **
58843	     * Parses the color string and returns object with all values for the given color.
58844	     > Parameters
58845	     - clr (string) color string in one of the supported formats (see @Raphael.getRGB)
58846	     = (object) Combined RGB & HSB object in format:
58847	     o {
58848	     o     r (number) red,
58849	     o     g (number) green,
58850	     o     b (number) blue,
58851	     o     hex (string) color in HTML/CSS format: #••••••,
58852	     o     error (boolean) `true` if string can’t be parsed,
58853	     o     h (number) hue,
58854	     o     s (number) saturation,
58855	     o     v (number) value (brightness),
58856	     o     l (number) lightness
58857	     o }
58858	    \*/
58859	    R.color = function (clr) {
58860	        var rgb;
58861	        if (R.is(clr, "object") && "h" in clr && "s" in clr && "b" in clr) {
58862	            rgb = R.hsb2rgb(clr);
58863	            clr.r = rgb.r;
58864	            clr.g = rgb.g;
58865	            clr.b = rgb.b;
58866	            clr.hex = rgb.hex;
58867	        } else if (R.is(clr, "object") && "h" in clr && "s" in clr && "l" in clr) {
58868	            rgb = R.hsl2rgb(clr);
58869	            clr.r = rgb.r;
58870	            clr.g = rgb.g;
58871	            clr.b = rgb.b;
58872	            clr.hex = rgb.hex;
58873	        } else {
58874	            if (R.is(clr, "string")) {
58875	                clr = R.getRGB(clr);
58876	            }
58877	            if (R.is(clr, "object") && "r" in clr && "g" in clr && "b" in clr) {
58878	                rgb = R.rgb2hsl(clr);
58879	                clr.h = rgb.h;
58880	                clr.s = rgb.s;
58881	                clr.l = rgb.l;
58882	                rgb = R.rgb2hsb(clr);
58883	                clr.v = rgb.b;
58884	            } else {
58885	                clr = {hex: "none"};
58886	                clr.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1;
58887	            }
58888	        }
58889	        clr.toString = rgbtoString;
58890	        return clr;
58891	    };
58892	    /*\
58893	     * Raphael.hsb2rgb
58894	     [ method ]
58895	     **
58896	     * Converts HSB values to RGB object.
58897	     > Parameters
58898	     - h (number) hue
58899	     - s (number) saturation
58900	     - v (number) value or brightness
58901	     = (object) RGB object in format:
58902	     o {
58903	     o     r (number) red,
58904	     o     g (number) green,
58905	     o     b (number) blue,
58906	     o     hex (string) color in HTML/CSS format: #••••••
58907	     o }
58908	    \*/
58909	    R.hsb2rgb = function (h, s, v, o) {
58910	        if (this.is(h, "object") && "h" in h && "s" in h && "b" in h) {
58911	            v = h.b;
58912	            s = h.s;
58913	            o = h.o;
58914	            h = h.h;
58915	        }
58916	        h *= 360;
58917	        var R, G, B, X, C;
58918	        h = (h % 360) / 60;
58919	        C = v * s;
58920	        X = C * (1 - abs(h % 2 - 1));
58921	        R = G = B = v - C;
58922
58923	        h = ~~h;
58924	        R += [C, X, 0, 0, X, C][h];
58925	        G += [X, C, C, X, 0, 0][h];
58926	        B += [0, 0, X, C, C, X][h];
58927	        return packageRGB(R, G, B, o);
58928	    };
58929	    /*\
58930	     * Raphael.hsl2rgb
58931	     [ method ]
58932	     **
58933	     * Converts HSL values to RGB object.
58934	     > Parameters
58935	     - h (number) hue
58936	     - s (number) saturation
58937	     - l (number) luminosity
58938	     = (object) RGB object in format:
58939	     o {
58940	     o     r (number) red,
58941	     o     g (number) green,
58942	     o     b (number) blue,
58943	     o     hex (string) color in HTML/CSS format: #••••••
58944	     o }
58945	    \*/
58946	    R.hsl2rgb = function (h, s, l, o) {
58947	        if (this.is(h, "object") && "h" in h && "s" in h && "l" in h) {
58948	            l = h.l;
58949	            s = h.s;
58950	            h = h.h;
58951	        }
58952	        if (h > 1 || s > 1 || l > 1) {
58953	            h /= 360;
58954	            s /= 100;
58955	            l /= 100;
58956	        }
58957	        h *= 360;
58958	        var R, G, B, X, C;
58959	        h = (h % 360) / 60;
58960	        C = 2 * s * (l < .5 ? l : 1 - l);
58961	        X = C * (1 - abs(h % 2 - 1));
58962	        R = G = B = l - C / 2;
58963
58964	        h = ~~h;
58965	        R += [C, X, 0, 0, X, C][h];
58966	        G += [X, C, C, X, 0, 0][h];
58967	        B += [0, 0, X, C, C, X][h];
58968	        return packageRGB(R, G, B, o);
58969	    };
58970	    /*\
58971	     * Raphael.rgb2hsb
58972	     [ method ]
58973	     **
58974	     * Converts RGB values to HSB object.
58975	     > Parameters
58976	     - r (number) red
58977	     - g (number) green
58978	     - b (number) blue
58979	     = (object) HSB object in format:
58980	     o {
58981	     o     h (number) hue
58982	     o     s (number) saturation
58983	     o     b (number) brightness
58984	     o }
58985	    \*/
58986	    R.rgb2hsb = function (r, g, b) {
58987	        b = prepareRGB(r, g, b);
58988	        r = b[0];
58989	        g = b[1];
58990	        b = b[2];
58991
58992	        var H, S, V, C;
58993	        V = mmax(r, g, b);
58994	        C = V - mmin(r, g, b);
58995	        H = (C == 0 ? null :
58996	             V == r ? (g - b) / C :
58997	             V == g ? (b - r) / C + 2 :
58998	                      (r - g) / C + 4
58999	            );
59000	        H = ((H + 360) % 6) * 60 / 360;
59001	        S = C == 0 ? 0 : C / V;
59002	        return {h: H, s: S, b: V, toString: hsbtoString};
59003	    };
59004	    /*\
59005	     * Raphael.rgb2hsl
59006	     [ method ]
59007	     **
59008	     * Converts RGB values to HSL object.
59009	     > Parameters
59010	     - r (number) red
59011	     - g (number) green
59012	     - b (number) blue
59013	     = (object) HSL object in format:
59014	     o {
59015	     o     h (number) hue
59016	     o     s (number) saturation
59017	     o     l (number) luminosity
59018	     o }
59019	    \*/
59020	    R.rgb2hsl = function (r, g, b) {
59021	        b = prepareRGB(r, g, b);
59022	        r = b[0];
59023	        g = b[1];
59024	        b = b[2];
59025
59026	        var H, S, L, M, m, C;
59027	        M = mmax(r, g, b);
59028	        m = mmin(r, g, b);
59029	        C = M - m;
59030	        H = (C == 0 ? null :
59031	             M == r ? (g - b) / C :
59032	             M == g ? (b - r) / C + 2 :
59033	                      (r - g) / C + 4);
59034	        H = ((H + 360) % 6) * 60 / 360;
59035	        L = (M + m) / 2;
59036	        S = (C == 0 ? 0 :
59037	             L < .5 ? C / (2 * L) :
59038	                      C / (2 - 2 * L));
59039	        return {h: H, s: S, l: L, toString: hsltoString};
59040	    };
59041	    R._path2string = function () {
59042	        return this.join(",").replace(p2s, "$1");
59043	    };
59044	    function repush(array, item) {
59045	        for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) {
59046	            return array.push(array.splice(i, 1)[0]);
59047	        }
59048	    }
59049	    function cacher(f, scope, postprocessor) {
59050	        function newf() {
59051	            var arg = Array.prototype.slice.call(arguments, 0),
59052	                args = arg.join("\u2400"),
59053	                cache = newf.cache = newf.cache || {},
59054	                count = newf.count = newf.count || [];
59055	            if (cache[has](args)) {
59056	                repush(count, args);
59057	                return postprocessor ? postprocessor(cache[args]) : cache[args];
59058	            }
59059	            count.length >= 1e3 && delete cache[count.shift()];
59060	            count.push(args);
59061	            cache[args] = f[apply](scope, arg);
59062	            return postprocessor ? postprocessor(cache[args]) : cache[args];
59063	        }
59064	        return newf;
59065	    }
59066
59067	    var preload = R._preload = function (src, f) {
59068	        var img = g.doc.createElement("img");
59069	        img.style.cssText = "position:absolute;
59069left:-9999em;top:-9999em";
59070	        img.onload = function () {
59071	            f.call(this);
59072	            this.onload = null;
59073	            g.doc.body.removeChild(this);
59074	        };
59075	        img.onerror = function () {
59076	            g.doc.body.removeChild(this);
59077	        };
59078	        g.doc.body.appendChild(img);
59079	        img.src = src;
59080	    };
59081
59082	    function clrToString() {
59083	        return this.hex;
59084	    }
59085
59086	    /*\
59087	     * Raphael.getRGB
59088	     [ method ]
59089	     **
59090	     * Parses colour string as RGB object
59091	     > Parameters
59092	     - colour (string) colour string in one of formats:
59093	     # <ul>
59094	     #     <li>Colour name (“<code>red</code>”, “<code>green</code>”, “<code>cornflowerblue</code>”, etc)</li>
59095	     #     <li>#••• — shortened HTML colour: (“<code>#000</code>”, “<code>#fc0</code>”, etc)</li>
59096	     #     <li>#•••••• — full length HTML colour: (“<code>#000000</code>”, “<code>#bd2300</code>”)</li>
59097	     #     <li>rgb(•••, •••, •••) — red, green and blue channels’ values: (“<code>rgb(200,&nbsp;100,&nbsp;0)</code>”)</li>
59098	     #     <li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<code>rgb(100%,&nbsp;175%,&nbsp;0%)</code>”)</li>
59099	     #     <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<code>hsb(0.5,&nbsp;0.25,&nbsp;1)</code>”)</li>
59100	     #     <li>hsb(•••%, •••%, •••%) — same as above, but in %</li>
59101	     #     <li>hsl(•••, •••, •••) — same as hsb</li>
59102	     #     <li>hsl(•••%, •••%, •••%) — same as hsb</li>
59103	     # </ul>
59104	     = (object) RGB object in format:
59105	     o {
59106	     o     r (number) red,
59107	     o     g (number) green,
59108	     o     b (number) blue
59109	     o     hex (string) color in HTML/CSS format: #••••••,
59110	     o     error (boolean) true if string can’t be parsed
59111	     o }
59112	    \*/
59113	    R.getRGB = cacher(function (colour) {
59114	        if (!colour || !!((colour = Str(colour)).indexOf("-") + 1)) {
59115	            return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString};
59116	        }
59117	        if (colour == "none") {
59118	            return {r: -1, g: -1, b: -1, hex: "none", toString: clrToString};
59119	        }
59120	        !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour));
59121	        var res,
59122	            red,
59123	            green,
59124	            blue,
59125	            opacity,
59126	            t,
59127	            values,
59128	            rgb = colour.match(colourRegExp);
59129	        if (rgb) {
59130	            if (rgb[2]) {
59131	                blue = toInt(rgb[2].substring(5), 16);
59132	                green = toInt(rgb[2].substring(3, 5), 16);
59133	                red = toInt(rgb[2].substring(1, 3), 16);
59134	            }
59135	            if (rgb[3]) {
59136	                blue = toInt((t = rgb[3].charAt(3)) + t, 16);
59137	                green = toInt((t = rgb[3].charAt(2)) + t, 16);
59138	                red = toInt((t = rgb[3].charAt(1)) + t, 16);
59139	            }
59140	            if (rgb[4]) {
59141	                values = rgb[4][split](commaSpaces);
59142	                red = toFloat(values[0]);
59143	                values[0].slice(-1) == "%" && (red *= 2.55);
59144	                green = toFloat(values[1]);
59145	                values[1].slice(-1) == "%" && (green *= 2.55);
59146	                blue = toFloat(values[2]);
59147	                values[2].slice(-1) == "%" && (blue *= 2.55);
59148	                rgb[1].toLowerCase().slice(0, 4) == "rgba" && (opacity = toFloat(values[3]));
59149	                values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
59150	            }
59151	            if (rgb[5]) {
59152	                values = rgb[5][split](commaSpaces);
59153	                red = toFloat(values[0]);
59154	                values[0].slice(-1) == "%" && (red *= 2.55);
59155	                green = toFloat(values[1]);
59156	                values[1].slice(-1) == "%" && (green *= 2.55);
59157	                blue = toFloat(values[2]);
59158	                values[2].slice(-1) == "%" && (blue *= 2.55);
59159	                (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360);
59160	                rgb[1].toLowerCase().slice(0, 4) == "hsba" && (opacity = toFloat(values[3]));
59161	                values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
59162	                return R.hsb2rgb(red, green, blue, opacity);
59163	            }
59164	            if (rgb[6]) {
59165	                values = rgb[6][split](commaSpaces);
59166	                red = toFloat(values[0]);
59167	                values[0].slice(-1) == "%" && (red *= 2.55);
59168	                green = toFloat(values[1]);
59169	                values[1].slice(-1) == "%" && (green *= 2.55);
59170	                blue = toFloat(values[2]);
59171	                values[2].slice(-1) == "%" && (blue *= 2.55);
59172	                (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360);
59173	                rgb[1].toLowerCase().slice(0, 4) == "hsla" && (opacity = toFloat(values[3]));
59174	                values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
59175	                return R.hsl2rgb(red, green, blue, opacity);
59176	            }
59177	            rgb = {r: red, g: green, b: blue, toString: clrToString};
59178	            rgb.hex = "#" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1);
59179	            R.is(opacity, "finite") && (rgb.opacity = opacity);
59180	            return rgb;
59181	        }
59182	        return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString};
59183	    }, R);
59184	    /*\
59185	     * Raphael.hsb
59186	     [ method ]
59187	     **
59188	     * Converts HSB values to hex representation of the colour.
59189	     > Parameters
59190	     - h (number) hue
59191	     - s (number) saturation
59192	     - b (number) value or brightness
59193	     = (string) hex representation of the colour.
59194	    \*/
59195	    R.hsb = cacher(function (h, s, b) {
59196	        return R.hsb2rgb(h, s, b).hex;
59197	    });
59198	    /*\
59199	     * Raphael.hsl
59200	     [ method ]
59201	     **
59202	     * Converts HSL values to hex representation of the colour.
59203	     > Parameters
59204	     - h (number) hue
59205	     - s (number) saturation
59206	     - l (number) luminosity
59207	     = (string) hex representation of the colour.
59208	    \*/
59209	    R.hsl = cacher(function (h, s, l) {
59210	        return R.hsl2rgb(h, s, l).hex;
59211	    });
59212	    /*\
59213	     * Raphael.rgb
59214	     [ method ]
59215	     **
59216	     * Converts RGB values to hex representation of the colour.
59217	     > Parameters
59218	     - r (number) red
59219	     - g (number) green
59220	     - b (number) blue
59221	     = (string) hex representation of the colour.
59222	    \*/
59223	    R.rgb = cacher(function (r, g, b) {
59224	        function round(x) { return (x + 0.5) | 0; }
59225	        return "#" + (16777216 | round(b) | (round(g) << 8) | (round(r) << 16)).toString(16).slice(1);
59226	    });
59227	    /*\
59228	     * Raphael.getColor
59229	     [ method ]
59230	     **
59231	     * On each call returns next colour in the spectrum. To reset it back to red call @Raphael.getColor.reset
59232	     > Parameters
59233	     - value (number) #optional brightness, default is `0.75`
59234	     = (string) hex representation of the colour.
59235	    \*/
59236	    R.getColor = function (value) {
59237	        var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75},
59238	            rgb = this.hsb2rgb(start.h, start.s, start.b);
59239	        start.h += .075;
59240	        if (start.h > 1) {
59241	            start.h = 0;
59242	            start.s -= .2;
59243	            start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b});
59244	        }
59245	        return rgb.hex;
59246	    };
59247	    /*\
59248	     * Raphael.getColor.reset
59249	     [ method ]
59250	     **
59251	     * Resets spectrum position for @Raphael.getColor back to red.
59252	    \*/
59253	    R.getColor.reset = function () {
59254	        delete this.start;
59255	    };
59256
59257	    // http://schepers.cc/getting-to-the-point
59258	    function catmullRom2bezier(crp, z) {
59259	        var d = [];
59260	        for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) {
59261	            var p = [
59262	                        {x: +crp[i - 2], y: +crp[i - 1]},
59263	                        {x: +crp[i],     y: +crp[i + 1]},
59264	                        {x: +crp[i + 2], y: +crp[i + 3]},
59265	                        {x: +crp[i + 4], y: +crp[i + 5]}
59266	                    ];
59267	            if (z) {
59268	                if (!i) {
59269	                    p[0] = {x: +crp[iLen - 2], y: +crp[iLen - 1]};
59270	                } else if (iLen - 4 == i) {
59271	                    p[3] = {x: +crp[0], y: +crp[1]};
59272	                }
vendor: 14,564 bytes, lines 59272-59668
59272 else if (iLen - 2 == i) {
59273	                    p[2] = {x: +crp[0], y: +crp[1]};
59274	                    p[3] = {x: +crp[2], y: +crp[3]};
59275	                }
59276	            } else {
59277	                if (iLen - 4 == i) {
59278	                    p[3] = p[2];
59279	                } else if (!i) {
59280	                    p[0] = {x: +crp[i], y: +crp[i + 1]};
59281	                }
59282	            }
59283	            d.push(["C",
59284	                  (-p[0].x + 6 * p[1].x + p[2].x) / 6,
59285	                  (-p[0].y + 6 * p[1].y + p[2].y) / 6,
59286	                  (p[1].x + 6 * p[2].x - p[3].x) / 6,
59287	                  (p[1].y + 6*p[2].y - p[3].y) / 6,
59288	                  p[2].x,
59289	                  p[2].y
59290	            ]);
59291	        }
59292
59293	        return d;
59294	    }
59295	    /*\
59296	     * Raphael.parsePathString
59297	     [ method ]
59298	     **
59299	     * Utility method
59300	     **
59301	     * Parses given path string into an array of arrays of path segments.
59302	     > Parameters
59303	     - pathString (string|array) path string or array of segments (in the last case it will be returned straight away)
59304	     = (array) array of segments.
59305	    \*/
59306	    R.parsePathString = function (pathString) {
59307	        if (!pathString) {
59308	            return null;
59309	        }
59310	        var pth = paths(pathString);
59311	        if (pth.arr) {
59312	            return pathClone(pth.arr);
59313	        }
59314
59315	        var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0},
59316	            data = [];
59317	        if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption
59318	            data = pathClone(pathString);
59319	        }
59320	        if (!data.length) {
59321	            Str(pathString).replace(pathCommand, function (a, b, c) {
59322	                var params = [],
59323	                    name = b.toLowerCase();
59324	                c.replace(pathValues, function (a, b) {
59325	                    b && params.push(+b);
59326	                });
59327	                if (name == "m" && params.length > 2) {
59328	                    data.push([b][concat](params.splice(0, 2)));
59329	                    name = "l";
59330	                    b = b == "m" ? "l" : "L";
59331	                }
59332	                if (name == "r") {
59333	                    data.push([b][concat](params));
59334	                } else while (params.length >= paramCounts[name]) {
59335	                    data.push([b][concat](params.splice(0, paramCounts[name])));
59336	                    if (!paramCounts[name]) {
59337	                        break;
59338	                    }
59339	                }
59340	            });
59341	        }
59342	        data.toString = R._path2string;
59343	        pth.arr = pathClone(data);
59344	        return data;
59345	    };
59346	    /*\
59347	     * Raphael.parseTransformString
59348	     [ method ]
59349	     **
59350	     * Utility method
59351	     **
59352	     * Parses given path string into an array of transformations.
59353	     > Parameters
59354	     - TString (string|array) transform string or array of transformations (in the last case it will be returned straight away)
59355	     = (array) array of transformations.
59356	    \*/
59357	    R.parseTransformString = cacher(function (TString) {
59358	        if (!TString) {
59359	            return null;
59360	        }
59361	        var paramCounts = {r: 3, s: 4, t: 2, m: 6},
59362	            data = [];
59363	        if (R.is(TString, array) && R.is(TString[0], array)) { // rough assumption
59364	            data = pathClone(TString);
59365	        }
59366	        if (!data.length) {
59367	            Str(TString).replace(tCommand, function (a, b, c) {
59368	                var params = [],
59369	                    name = lowerCase.call(b);
59370	                c.replace(pathValues, function (a, b) {
59371	                    b && params.push(+b);
59372	                });
59373	                data.push([b][concat](params));
59374	            });
59375	        }
59376	        data.toString = R._path2string;
59377	        return data;
59378	    });
59379	    // PATHS
59380	    var paths = function (ps) {
59381	        var p = paths.ps = paths.ps || {};
59382	        if (p[ps]) {
59383	            p[ps].sleep = 100;
59384	        } else {
59385	            p[ps] = {
59386	                sleep: 100
59387	            };
59388	        }
59389	        setTimeout(function () {
59390	            for (var key in p) if (p[has](key) && key != ps) {
59391	                p[key].sleep--;
59392	                !p[key].sleep && delete p[key];
59393	            }
59394	        });
59395	        return p[ps];
59396	    };
59397	    /*\
59398	     * Raphael.findDotsAtSegment
59399	     [ method ]
59400	     **
59401	     * Utility method
59402	     **
59403	     * Find dot coordinates on the given cubic bezier curve at the given t.
59404	     > Parameters
59405	     - p1x (number) x of the first point of the curve
59406	     - p1y (number) y of the first point of the curve
59407	     - c1x (number) x of the first anchor of the curve
59408	     - c1y (number) y of the first anchor of the curve
59409	     - c2x (number) x of the second anchor of the curve
59410	     - c2y (number) y of the second anchor of the curve
59411	     - p2x (number) x of the second point of the curve
59412	     - p2y (number) y of the second point of the curve
59413	     - t (number) position on the curve (0..1)
59414	     = (object) point information in format:
59415	     o {
59416	     o     x: (number) x coordinate of the point
59417	     o     y: (number) y coordinate of the point
59418	     o     m: {
59419	     o         x: (number) x coordinate of the left anchor
59420	     o         y: (number) y coordinate of the left anchor
59421	     o     }
59422	     o     n: {
59423	     o         x: (number) x coordinate of the right anchor
59424	     o         y: (number) y coordinate of the right anchor
59425	     o     }
59426	     o     start: {
59427	     o         x: (number) x coordinate of the start of the curve
59428	     o         y: (number) y coordinate of the start of the curve
59429	     o     }
59430	     o     end: {
59431	     o         x: (number) x coordinate of the end of the curve
59432	     o         y: (number) y coordinate of the end of the curve
59433	     o     }
59434	     o     alpha: (number) angle of the curve derivative at the point
59435	     o }
59436	    \*/
59437	    R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
59438	        var t1 = 1 - t,
59439	            t13 = pow(t1, 3),
59440	            t12 = pow(t1, 2),
59441	            t2 = t * t,
59442	            t3 = t2 * t,
59443	            x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x,
59444	            y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y,
59445	            mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x),
59446	            my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y),
59447	            nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x),
59448	            ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y),
59449	            ax = t1 * p1x + t * c1x,
59450	            ay = t1 * p1y + t * c1y,
59451	            cx = t1 * c2x + t * p2x,
59452	            cy = t1 * c2y + t * p2y,
59453	            alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI);
59454	        (mx > nx || my < ny) && (alpha += 180);
59455	        return {
59456	            x: x,
59457	            y: y,
59458	            m: {x: mx, y: my},
59459	            n: {x: nx, y: ny},
59460	            start: {x: ax, y: ay},
59461	            end: {x: cx, y: cy},
59462	            alpha: alpha
59463	        };
59464	    };
59465	    /*\
59466	     * Raphael.bezierBBox
59467	     [ method ]
59468	     **
59469	     * Utility method
59470	     **
59471	     * Return bounding box of a given cubic bezier curve
59472	     > Parameters
59473	     - p1x (number) x of the first point of the curve
59474	     - p1y (number) y of the first point of the curve
59475	     - c1x (number) x of the first anchor of the curve
59476	     - c1y (number) y of the first anchor of the curve
59477	     - c2x (number) x of the second anchor of the curve
59478	     - c2y (number) y of the second anchor of the curve
59479	     - p2x (number) x of the second point of the curve
59480	     - p2y (number) y of the second point of the curve
59481	     * or
59482	     - bez (array) array of six points for bezier curve
59483	     = (object) point information in format:
59484	     o {
59485	     o     min: {
59486	     o         x: (number) x coordinate of the left point
59487	     o         y: (number) y coordinate of the top point
59488	     o     }
59489	     o     max: {
59490	     o         x: (number) x coordinate of the right point
59491	     o         y: (number) y coordinate of the bottom point
59492	     o     }
59493	     o }
59494	    \*/
59495	    R.bezierBBox = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
59496	        if (!R.is(p1x, "array")) {
59497	            p1x = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y];
59498	        }
59499	        var bbox = curveDim.apply(null, p1x);
59500	        return {
59501	            x: bbox.min.x,
59502	            y: bbox.min.y,
59503	            x2: bbox.max.x,
59504	            y2: bbox.max.y,
59505	            width: bbox.max.x - bbox.min.x,
59506	            height: bbox.max.y - bbox.min.y
59507	        };
59508	    };
59509	    /*\
59510	     * Raphael.isPointInsideBBox
59511	     [ method ]
59512	     **
59513	     * Utility method
59514	     **
59515	     * Returns `true` if given point is inside bounding boxes.
59516	     > Parameters
59517	     - bbox (string) bounding box
59518	     - x (string) x coordinate of the point
59519	     - y (string) y coordinate of the point
59520	     = (boolean) `true` if point inside
59521	    \*/
59522	    R.isPointInsideBBox = function (bbox, x, y) {
59523	        return x >= bbox.x && x <= bbox.x2 && y >= bbox.y && y <= bbox.y2;
59524	    };
59525	    /*\
59526	     * Raphael.isBBoxIntersect
59527	     [ method ]
59528	     **
59529	     * Utility method
59530	     **
59531	     * Returns `true` if two bounding boxes intersect
59532	     > Parameters
59533	     - bbox1 (string) first bounding box
59534	     - bbox2 (string) second bounding box
59535	     = (boolean) `true` if they intersect
59536	    \*/
59537	    R.isBBoxIntersect = function (bbox1, bbox2) {
59538	        var i = R.isPointInsideBBox;
59539	        return i(bbox2, bbox1.x, bbox1.y)
59540	            || i(bbox2, bbox1.x2, bbox1.y)
59541	            || i(bbox2, bbox1.x, bbox1.y2)
59542	            || i(bbox2, bbox1.x2, bbox1.y2)
59543	            || i(bbox1, bbox2.x, bbox2.y)
59544	            || i(bbox1, bbox2.x2, bbox2.y)
59545	            || i(bbox1, bbox2.x, bbox2.y2)
59546	            || i(bbox1, bbox2.x2, bbox2.y2)
59547	            || (bbox1.x < bbox2.x2 && bbox1.x > bbox2.x || bbox2.x < bbox1.x2 && bbox2.x > bbox1.x)
59548	            && (bbox1.y < bbox2.y2 && bbox1.y > bbox2.y || bbox2.y < bbox1.y2 && bbox2.y > bbox1.y);
59549	    };
59550	    function base3(t, p1, p2, p3, p4) {
59551	        var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4,
59552	            t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;
59553	        return t * t2 - 3 * p1 + 3 * p2;
59554	    }
59555	    function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) {
59556	        if (z == null) {
59557	            z = 1;
59558	        }
59559	        z = z > 1 ? 1 : z < 0 ? 0 : z;
59560	        var z2 = z / 2,
59561	            n = 12,
59562	            Tvalues = [-0.1252,0.1252,-0.3678,0.3678,-0.5873,0.5873,-0.7699,0.7699,-0.9041,0.9041,-0.9816,0.9816],
59563	            Cvalues = [0.2491,0.2491,0.2335,0.2335,0.2032,0.2032,0.1601,0.1601,0.1069,0.1069,0.0472,0.0472],
59564	            sum = 0;
59565	        for (var i = 0; i < n; i++) {
59566	            var ct = z2 * Tvalues[i] + z2,
59567	                xbase = base3(ct, x1, x2, x3, x4),
59568	                ybase = base3(ct, y1, y2, y3, y4),
59569	                comb = xbase * xbase + ybase * ybase;
59570	            sum += Cvalues[i] * math.sqrt(comb);
59571	        }
59572	        return z2 * sum;
59573	    }
59574	    function getTatLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) {
59575	        if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) {
59576	            return;
59577	        }
59578	        var t = 1,
59579	            step = t / 2,
59580	            t2 = t - step,
59581	            l,
59582	            e = .01;
59583	        l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
59584	        while (abs(l - ll) > e) {
59585	            step /= 2;
59586	            t2 += (l < ll ? 1 : -1) * step;
59587	            l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
59588	        }
59589	        return t2;
59590	    }
59591	    function intersect(x1, y1, x2, y2, x3, y3, x4, y4) {
59592	        if (
59593	            mmax(x1, x2) < mmin(x3, x4) ||
59594	            mmin(x1, x2) > mmax(x3, x4) ||
59595	            mmax(y1, y2) < mmin(y3, y4) ||
59596	            mmin(y1, y2) > mmax(y3, y4)
59597	        ) {
59598	            return;
59599	        }
59600	        var nx = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4),
59601	            ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4),
59602	            denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
59603
59604	        if (!denominator) {
59605	            return;
59606	        }
59607	        var px = nx / denominator,
59608	            py = ny / denominator,
59609	            px2 = +px.toFixed(2),
59610	            py2 = +py.toFixed(2);
59611	        if (
59612	            px2 < +mmin(x1, x2).toFixed(2) ||
59613	            px2 > +mmax(x1, x2).toFixed(2) ||
59614	            px2 < +mmin(x3, x4).toFixed(2) ||
59615	            px2 > +mmax(x3, x4).toFixed(2) ||
59616	            py2 < +mmin(y1, y2).toFixed(2) ||
59617	            py2 > +mmax(y1, y2).toFixed(2) ||
59618	            py2 < +mmin(y3, y4).toFixed(2) ||
59619	            py2 > +mmax(y3, y4).toFixed(2)
59620	        ) {
59621	            return;
59622	        }
59623	        return {x: px, y: py};
59624	    }
59625	    function inter(bez1, bez2) {
59626	        return interHelper(bez1, bez2);
59627	    }
59628	    function interCount(bez1, bez2) {
59629	        return interHelper(bez1, bez2, 1);
59630	    }
59631	    function interHelper(bez1, bez2, justCount) {
59632	        var bbox1 = R.bezierBBox(bez1),
59633	            bbox2 = R.bezierBBox(bez2);
59634	        if (!R.isBBoxIntersect(bbox1, bbox2)) {
59635	            return justCount ? 0 : [];
59636	        }
59637	        var l1 = bezlen.apply(0, bez1),
59638	            l2 = bezlen.apply(0, bez2),
59639	            n1 = mmax(~~(l1 / 5), 1),
59640	            n2 = mmax(~~(l2 / 5), 1),
59641	            dots1 = [],
59642	            dots2 = [],
59643	            xy = {},
59644	            res = justCount ? 0 : [];
59645	        for (var i = 0; i < n1 + 1; i++) {
59646	            var p = R.findDotsAtSegment.apply(R, bez1.concat(i / n1));
59647	            dots1.push({x: p.x, y: p.y, t: i / n1});
59648	        }
59649	        for (i = 0; i < n2 + 1; i++) {
59650	            p = R.findDotsAtSegment.apply(R, bez2.concat(i / n2));
59651	            dots2.push({x: p.x, y: p.y, t: i / n2});
59652	        }
59653	        for (i = 0; i < n1; i++) {
59654	            for (var j = 0; j < n2; j++) {
59655	                var di = dots1[i],
59656	                    di1 = dots1[i + 1],
59657	                    dj = dots2[j],
59658	                    dj1 = dots2[j + 1],
59659	                    ci = abs(di1.x - di.x) < .001 ? "y" : "x",
59660	                    cj = abs(dj1.x - dj.x) < .001 ? "y" : "x",
59661	                    is = intersect(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y);
59662	                if (is) {
59663	                    if (xy[is.x.toFixed(4)] == is.y.toFixed(4)) {
59664	                        continue;
59665	                    }
59666	                    xy[is.x.toFixed(4)] = is.y.toFixed(4);
59667	                    var t1 = di.t + abs((is[ci] - di[ci]) / (di1[ci] - di[ci])) * (di1.t - di.t),
59668	                        t2 = dj.t + abs((is[cj] - dj[cj]) / (dj1[cj] 
59668- dj[cj])) * (dj1.t - dj.t);
59669	                    if (t1 >= 0 && t1 <= 1.001 && t2 >= 0 && t2 <= 1.001) {
59670	                        if (justCount) {
59671	                            res++;
59672	                        } else {
59673	                            res.push({
59674	                                x: is.x,
59675	                                y: is.y,
59676	                                t1: mmin(t1, 1),
59677	                                t2: mmin(t2, 1)
59678	                            });
59679	                        }
59680	                    }
59681	                }
59682	            }
59683	        }
59684	        return res;
59685	    }
59686	    /*\
59687	     * Raphael.pathIntersection
59688	     [ method ]
59689	     **
59690	     * Utility method
59691	     **
59692	     * Finds intersections of two paths
59693	     > Parameters
59694	     - path1 (string) path string
59695	     - path2 (string) path string
59696	     = (array) dots of intersection
59697	     o [
59698	     o     {
59699	     o         x: (number) x coordinate of the point
59700	     o         y: (number) y coordinate of the point
59701	     o         t1: (number) t value for segment of path1
59702	     o         t2: (number) t value for segment of path2
59703	     o         segment1: (number) order number for segment of path1
59704	     o         segment2: (number) order number for segment of path2
59705	     o         bez1: (array) eight coordinates representing beziér curve for the segment of path1
59706	     o         bez2: (array) eight coordinates representing beziér curve for the segment of path2
59707	     o     }
59708	     o ]
59709	    \*/
59710	    R.pathIntersection = function (path1, path2) {
59711	        return interPathHelper(path1, path2);
59712	    };
59713	    R.pathIntersectionNumber = function (path1, path2) {
59714	        return interPathHelper(path1, path2, 1);
59715	    };
59716	    function interPathHelper(path1, path2, justCount) {
59717	        path1 = R._path2curve(path1);
59718	        path2 = R._path2curve(path2);
59719	        var x1, y1, x2, y2, x1m, y1m, x2m, y2m, bez1, bez2,
59720	            res = justCount ? 0 : [];
59721	        for (var i = 0, ii = path1.length; i < ii; i++) {
59722	            var pi = path1[i];
59723	            if (pi[0] == "M") {
59724	                x1 = x1m = pi[1];
59725	                y1 = y1m = pi[2];
59726	            } else {
59727	                if (pi[0] == "C") {
59728	                    bez1 = [x1, y1].concat(pi.slice(1));
59729	                    x1 = bez1[6];
59730	                    y1 = bez1[7];
59731	                } else {
59732	                    bez1 = [x1, y1, x1, y1, x1m, y1m, x1m, y1m];
59733	                    x1 = x1m;
59734	                    y1 = y1m;
59735	                }
59736	                for (var j = 0, jj = path2.length; j < jj; j++) {
59737	                    var pj = path2[j];
59738	                    if (pj[0] == "M") {
59739	                        x2 = x2m = pj[1];
59740	                        y2 = y2m = pj[2];
59741	                    } else {
59742	                        if (pj[0] == "C") {
59743	                            bez2 = [x2, y2].concat(pj.slice(1));
59744	                            x2 = bez2[6];
59745	                            y2 = bez2[7];
59746	                        } else {
59747	                            bez2 = [x2, y2, x2, y2, x2m, y2m, x2m, y2m];
59748	                            x2 = x2m;
59749	                            y2 = y2m;
59750	                        }
59751	                        var intr = interHelper(bez1, bez2, justCount);
59752	                        if (justCount) {
59753	                            res += intr;
59754	                        } else {
59755	                            for (var k = 0, kk = intr.length; k < kk; k++) {
59756	                                intr[k].segment1 = i;
59757	                                intr[k].segment2 = j;
59758	                                intr[k].bez1 = bez1;
59759	                                intr[k].bez2 = bez2;
59760	                            }
59761	                            res = res.concat(intr);
59762	                        }
59763	                    }
59764	                }
59765	            }
59766	        }
59767	        return res;
59768	    }
59769	    /*\
59770	     * Raphael.isPointInsidePath
59771	     [ method ]
59772	     **
59773	     * Utility method
59774	     **
59775	     * Returns `true` if given point is inside a given closed path.
59776	     > Parameters
59777	     - path (string) path string
59778	     - x (number) x of the point
59779	     - y (number) y of the point
59780	     = (boolean) true, if point is inside the path
59781	    \*/
59782	    R.isPointInsidePath = function (path, x, y) {
59783	        var bbox = R.pathBBox(path);
59784	        return R.isPointInsideBBox(bbox, x, y) &&
59785	               interPathHelper(path, [["M", x, y], ["H", bbox.x2 + 10]], 1) % 2 == 1;
59786	    };
59787	    R._removedFactory = function (methodname) {
59788	        return function () {
59789	            eve("raphael.log", null, "Rapha\xebl: you are calling to method \u201c" + methodname + "\u201d of removed object", methodname);
59790	        };
59791	    };
59792	    /*\
59793	     * Raphael.pathBBox
59794	     [ method ]
59795	     **
59796	     * Utility method
59797	     **
59798	     * Return bounding box of a given path
59799	     > Parameters
59800	     - path (string) path string
59801	     = (object) bounding box
59802	     o {
59803	     o     x: (number) x coordinate of the left top point of the box
59804	     o     y: (number) y coordinate of the left top point of the box
59805	     o     x2: (number) x coordinate of the right bottom point of the box
59806	     o     y2: (number) y coordinate of the right bottom point of the box
59807	     o     width: (number) width of the box
59808	     o     height: (number) height of the box
59809	     o     cx: (number) x coordinate of the center of the box
59810	     o     cy: (number) y coordinate of the center of the box
59811	     o }
59812	    \*/
59813	    var pathDimensions = R.pathBBox = function (path) {
59814	        var pth = paths(path);
59815	        if (pth.bbox) {
59816	            return clone(pth.bbox);
59817	        }
59818	        if (!path) {
59819	            return {x: 0, y: 0, width: 0, height: 0, x2: 0, y2: 0};
59820	        }
59821	        path = path2curve(path);
59822	        var x = 0,
59823	            y = 0,
59824	            X = [],
59825	            Y = [],
59826	            p;
59827	        for (var i = 0, ii = path.length; i < ii; i++) {
59828	            p = path[i];
59829	            if (p[0] == "M") {
59830	                x = p[1];
59831	                y = p[2];
59832	                X.push(x);
59833	                Y.push(y);
59834	            } else {
59835	                var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
59836	                X = X[concat](dim.min.x, dim.max.x);
59837	                Y = Y[concat](dim.min.y, dim.max.y);
59838	                x = p[5];
59839	                y = p[6];
59840	            }
59841	        }
59842	        var xmin = mmin[apply](0, X),
59843	            ymin = mmin[apply](0, Y),
59844	            xmax = mmax[apply](0, X),
59845	            ymax = mmax[apply](0, Y),
59846	            width = xmax - xmin,
59847	            height = ymax - ymin,
59848	                bb = {
59849	                x: xmin,
59850	                y: ymin,
59851	                x2: xmax,
59852	                y2: ymax,
59853	                width: width,
59854	                height: height,
59855	                cx: xmin + width / 2,
vendor: 19,669 bytes, lines 59856-60302
59856	                cy: ymin + height / 2
59857	            };
59858	        pth.bbox = clone(bb);
59859	        return bb;
59860	    },
59861	        pathClone = function (pathArray) {
59862	            var res = clone(pathArray);
59863	            res.toString = R._path2string;
59864	            return res;
59865	        },
59866	        pathToRelative = R._pathToRelative = function (pathArray) {
59867	            var pth = paths(pathArray);
59868	            if (pth.rel) {
59869	                return pathClone(pth.rel);
59870	            }
59871	            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
59872	                pathArray = R.parsePathString(pathArray);
59873	            }
59874	            var res = [],
59875	                x = 0,
59876	                y = 0,
59877	                mx = 0,
59878	                my = 0,
59879	                start = 0;
59880	            if (pathArray[0][0] == "M") {
59881	                x = pathArray[0][1];
59882	                y = pathArray[0][2];
59883	                mx = x;
59884	                my = y;
59885	                start++;
59886	                res.push(["M", x, y]);
59887	            }
59888	            for (var i = start, ii = pathArray.length; i < ii; i++) {
59889	                var r = res[i] = [],
59890	                    pa = pathArray[i];
59891	                if (pa[0] != lowerCase.call(pa[0])) {
59892	                    r[0] = lowerCase.call(pa[0]);
59893	                    switch (r[0]) {
59894	                        case "a":
59895	                            r[1] = pa[1];
59896	                            r[2] = pa[2];
59897	                            r[3] = pa[3];
59898	                            r[4] = pa[4];
59899	                            r[5] = pa[5];
59900	                            r[6] = +(pa[6] - x).toFixed(3);
59901	                            r[7] = +(pa[7] - y).toFixed(3);
59902	                            break;
59903	                        case "v":
59904	                            r[1] = +(pa[1] - y).toFixed(3);
59905	                            break;
59906	                        case "m":
59907	                            mx = pa[1];
59908	                            my = pa[2];
59909	                        default:
59910	                            for (var j = 1, jj = pa.length; j < jj; j++) {
59911	                                r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);
59912	                            }
59913	                    }
59914	                } else {
59915	                    r = res[i] = [];
59916	                    if (pa[0] == "m") {
59917	                        mx = pa[1] + x;
59918	                        my = pa[2] + y;
59919	                    }
59920	                    for (var k = 0, kk = pa.length; k < kk; k++) {
59921	                        res[i][k] = pa[k];
59922	                    }
59923	                }
59924	                var len = res[i].length;
59925	                switch (res[i][0]) {
59926	                    case "z":
59927	                        x = mx;
59928	                        y = my;
59929	                        break;
59930	                    case "h":
59931	                        x += +res[i][len - 1];
59932	                        break;
59933	                    case "v":
59934	                        y += +res[i][len - 1];
59935	                        break;
59936	                    default:
59937	                        x += +res[i][len - 2];
59938	                        y += +res[i][len - 1];
59939	                }
59940	            }
59941	            res.toString = R._path2string;
59942	            pth.rel = pathClone(res);
59943	            return res;
59944	        },
59945	        pathToAbsolute = R._pathToAbsolute = function (pathArray) {
59946	            var pth = paths(pathArray);
59947	            if (pth.abs) {
59948	                return pathClone(pth.abs);
59949	            }
59950	            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
59951	                pathArray = R.parsePathString(pathArray);
59952	            }
59953	            if (!pathArray || !pathArray.length) {
59954	                return [["M", 0, 0]];
59955	            }
59956	            var res = [],
59957	                x = 0,
59958	                y = 0,
59959	                mx = 0,
59960	                my = 0,
59961	                start = 0;
59962	            if (pathArray[0][0] == "M") {
59963	                x = +pathArray[0][1];
59964	                y = +pathArray[0][2];
59965	                mx = x;
59966	                my = y;
59967	                start++;
59968	                res[0] = ["M", x, y];
59969	            }
59970	            var crz = pathArray.length == 3 && pathArray[0][0] == "M" && pathArray[1][0].toUpperCase() == "R" && pathArray[2][0].toUpperCase() == "Z";
59971	            for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {
59972	                res.push(r = []);
59973	                pa = pathArray[i];
59974	                if (pa[0] != upperCase.call(pa[0])) {
59975	                    r[0] = upperCase.call(pa[0]);
59976	                    switch (r[0]) {
59977	                        case "A":
59978	                            r[1] = pa[1];
59979	                            r[2] = pa[2];
59980	                            r[3] = pa[3];
59981	                            r[4] = pa[4];
59982	                            r[5] = pa[5];
59983	                            r[6] = +(pa[6] + x);
59984	                            r[7] = +(pa[7] + y);
59985	                            break;
59986	                        case "V":
59987	                            r[1] = +pa[1] + y;
59988	                            break;
59989	                        case "H":
59990	                            r[1] = +pa[1] + x;
59991	                            break;
59992	                        case "R":
59993	                            var dots = [x, y][concat](pa.slice(1));
59994	                            for (var j = 2, jj = dots.length; j < jj; j++) {
59995	                                dots[j] = +dots[j] + x;
59996	                                dots[++j] = +dots[j] + y;
59997	                            }
59998	                            res.pop();
59999	                            res = res[concat](catmullRom2bezier(dots, crz));
60000	                            break;
60001	                        case "M":
60002	                            mx = +pa[1] + x;
60003	                            my = +pa[2] + y;
60004	                        default:
60005	                            for (j = 1, jj = pa.length; j < jj; j++) {
60006	                                r[j] = +pa[j] + ((j % 2) ? x : y);
60007	                            }
60008	                    }
60009	                } else if (pa[0] == "R") {
60010	                    dots = [x, y][concat](pa.slice(1));
60011	                    res.pop();
60012	                    res = res[concat](catmullRom2bezier(dots, crz));
60013	                    r = ["R"][concat](pa.slice(-2));
60014	                } else {
60015	                    for (var k = 0, kk = pa.length; k < kk; k++) {
60016	                        r[k] = pa[k];
60017	                    }
60018	                }
60019	                switch (r[0]) {
60020	                    case "Z":
60021	                        x = mx;
60022	                        y = my;
60023	                        break;
60024	                    case "H":
60025	                        x = r[1];
60026	                        break;
60027	                    case "V":
60028	                        y = r[1];
60029	                        break;
60030	                    case "M":
60031	                        mx = r[r.length - 2];
60032	                        my = r[r.length - 1];
60033	                    default:
60034	                        x = r[r.length - 2];
60035	                        y = r[r.length - 1];
60036	                }
60037	            }
60038	            res.toString = R._path2string;
60039	            pth.abs = pathClone(res);
60040	            return res;
60041	        },
60042	        l2c = function (x1, y1, x2, y2) {
60043	            return [x1, y1, x2, y2, x2, y2];
60044	        },
60045	        q2c = function (x1, y1, ax, ay, x2, y2) {
60046	            var _13 = 1 / 3,
60047	                _23 = 2 / 3;
60048	            return [
60049	                    _13 * x1 + _23 * ax,
60050	                    _13 * y1 + _23 * ay,
60051	                    _13 * x2 + _23 * ax,
60052	                    _13 * y2 + _23 * ay,
60053	                    x2,
60054	                    y2
60055	                ];
60056	        },
60057	        a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
60058	            // for more information of where this math came from visit:
60059	            // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
60060	            var _120 = PI * 120 / 180,
60061	                rad = PI / 180 * (+angle || 0),
60062	                res = [],
60063	                xy,
60064	                rotate = cacher(function (x, y, rad) {
60065	                    var X = x * math.cos(rad) - y * math.sin(rad),
60066	                        Y = x * math.sin(rad) + y * math.cos(rad);
60067	                    return {x: X, y: Y};
60068	                });
60069	            if (!recursive) {
60070	                xy = rotate(x1, y1, -rad);
60071	                x1 = xy.x;
60072	                y1 = xy.y;
60073	                xy = rotate(x2, y2, -rad);
60074	                x2 = xy.x;
60075	                y2 = xy.y;
60076	                var cos = math.cos(PI / 180 * angle),
60077	                    sin = math.sin(PI / 180 * angle),
60078	                    x = (x1 - x2) / 2,
60079	                    y = (y1 - y2) / 2;
60080	                var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
60081	                if (h > 1) {
60082	                    h = math.sqrt(h);
60083	                    rx = h * rx;
60084	                    ry = h * ry;
60085	                }
60086	                var rx2 = rx * rx,
60087	                    ry2 = ry * ry,
60088	                    k = (large_arc_flag == sweep_flag ? -1 : 1) *
60089	                        math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),
60090	                    cx = k * rx * y / ry + (x1 + x2) / 2,
60091	                    cy = k * -ry * x / rx + (y1 + y2) / 2,
60092	                    f1 = math.asin(((y1 - cy) / ry).toFixed(9)),
60093	                    f2 = math.asin(((y2 - cy) / ry).toFixed(9));
60094
60095	                f1 = x1 < cx ? PI - f1 : f1;
60096	                f2 = x2 < cx ? PI - f2 : f2;
60097	                f1 < 0 && (f1 = PI * 2 + f1);
60098	                f2 < 0 && (f2 = PI * 2 + f2);
60099	                if (sweep_flag && f1 > f2) {
60100	                    f1 = f1 - PI * 2;
60101	                }
60102	                if (!sweep_flag && f2 > f1) {
60103	                    f2 = f2 - PI * 2;
60104	                }
60105	            } else {
60106	                f1 = recursive[0];
60107	                f2 = recursive[1];
60108	                cx = recursive[2];
60109	                cy = recursive[3];
60110	            }
60111	            var df = f2 - f1;
60112	            if (abs(df) > _120) {
60113	                var f2old = f2,
60114	                    x2old = x2,
60115	                    y2old = y2;
60116	                f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
60117	                x2 = cx + rx * math.cos(f2);
60118	                y2 = cy + ry * math.sin(f2);
60119	                res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
60120	            }
60121	            df = f2 - f1;
60122	            var c1 = math.cos(f1),
60123	                s1 = math.sin(f1),
60124	                c2 = math.cos(f2),
60125	                s2 = math.sin(f2),
60126	                t = math.tan(df / 4),
60127	                hx = 4 / 3 * rx * t,
60128	                hy = 4 / 3 * ry * t,
60129	                m1 = [x1, y1],
60130	                m2 = [x1 + hx * s1, y1 - hy * c1],
60131	                m3 = [x2 + hx * s2, y2 - hy * c2],
60132	                m4 = [x2, y2];
60133	            m2[0] = 2 * m1[0] - m2[0];
60134	            m2[1] = 2 * m1[1] - m2[1];
60135	            if (recursive) {
60136	                return [m2, m3, m4][concat](res);
60137	            } else {
60138	                res = [m2, m3, m4][concat](res).join()[split](",");
60139	                var newres = [];
60140	                for (var i = 0, ii = res.length; i < ii; i++) {
60141	                    newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;
60142	                }
60143	                return newres;
60144	            }
60145	        },
60146	        findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
60147	            var t1 = 1 - t;
60148	            return {
60149	                x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x,
60150	                y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y
60151	            };
60152	        },
60153	        curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
60154	            var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),
60155	                b = 2 * (c1x - p1x) - 2 * (c2x - c1x),
60156	                c = p1x - c1x,
60157	                t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a,
60158	                t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a,
60159	                y = [p1y, p2y],
60160	                x = [p1x, p2x],
60161	                dot;
60162	            abs(t1) > "1e12" && (t1 = .5);
60163	            abs(t2) > "1e12" && (t2 = .5);
60164	            if (t1 > 0 && t1 < 1) {
60165	                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
60166	                x.push(dot.x);
60167	                y.push(dot.y);
60168	            }
60169	            if (t2 > 0 && t2 < 1) {
60170	                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
60171	                x.push(dot.x);
60172	                y.push(dot.y);
60173	            }
60174	            a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);
60175	            b = 2 * (c1y - p1y) - 2 * (c2y - c1y);
60176	            c = p1y - c1y;
60177	            t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a;
60178	            t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a;
60179	            abs(t1) > "1e12" && (t1 = .5);
60180	            abs(t2) > "1e12" && (t2 = .5);
60181	            if (t1 > 0 && t1 < 1) {
60182	                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
60183	                x.push(dot.x);
60184	                y.push(dot.y);
60185	            }
60186	            if (t2 > 0 && t2 < 1) {
60187	                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
60188	                x.push(dot.x);
60189	                y.push(dot.y);
60190	            }
60191	            return {
60192	                min: {x: mmin[apply](0, x), y: mmin[apply](0, y)},
60193	                max: {x: mmax[apply](0, x), y: mmax[apply](0, y)}
60194	            };
60195	        }),
60196	        path2curve = R._path2curve = cacher(function (path, path2) {
60197	            var pth = !path2 && paths(path);
60198	            if (!path2 && pth.curve) {
60199	                return pathClone(pth.curve);
60200	            }
60201	            var p = pathToAbsolute(path),
60202	                p2 = path2 && pathToAbsolute(path2),
60203	                attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
60204	                attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
60205	                processPath = function (path, d, pcom) {
60206	                    var nx, ny, tq = {T:1, Q:1};
60207	                    if (!path) {
60208	                        return ["C", d.x, d.y, d.x, d.y, d.x, d.y];
60209	                    }
60210	                    !(path[0] in tq) && (d.qx = d.qy = null);
60211	                    switch (path[0]) {
60212	                        case "M":
60213	                            d.X = path[1];
60214	                            d.Y = path[2];
60215	                            break;
60216	                        case "A":
60217	                            path = ["C"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1))));
60218	                            break;
60219	                        case "S":
60220	                            if (pcom == "C" || pcom == "S") { // In "S" case we have to take into account, if the previous command is C/S.
60221	                                nx = d.x * 2 - d.bx;          // And reflect the previous
60222	                                ny = d.y * 2 - d.by;          // command's control point relative to the current point.
60223	                            }
60224	                            else {                            // or some else or nothing
60225	                                nx = d.x;
60226	                                ny = d.y;
60227	                            }
60228	                            path = ["C", nx, ny][concat](path.slice(1));
60229	                            break;
60230	                        case "T":
60231	                            if (pcom == "Q" || pcom == "T") { // In "T" case we have to take into account, if the previous command is Q/T.
60232	                                d.qx = d.x * 2 - d.qx;        // And make a reflection similar
60233	                                d.qy = d.y * 2 - d.qy;        // to case "S".
60234	                            }
60235	                            else {                            // or something else or nothing
60236	                                d.qx = d.x;
60237	                                d.qy = d.y;
60238	                            }
60239	                            path = ["C"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));
60240	                            break;
60241	                        case "Q":
60242	                            d.qx = path[1];
60243	                            d.qy = path[2];
60244	                            path = ["C"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4]));
60245	                            break;
60246	                        case "L":
60247	                            path = ["C"][concat](l2c(d.x, d.y, path[1], path[2]));
60248	                            break;
60249	                        case "H":
60250	                            path = ["C"][concat](l2c(d.x, d.y, path[1], d.y));
60251	                            break;
60252	                        case "V":
60253	                            path = ["C"][concat](l2c(d.x, d.y, d.x, path[1]));
60254	                            break;
60255	                        case "Z":
60256	                            path = ["C"][concat](l2c(d.x, d.y, d.X, d.Y));
60257	                            break;
60258	                    }
60259	                    return path;
60260	                },
60261	                fixArc = function (pp, i) {
60262	                    if (pp[i].length > 7) {
60263	                        pp[i].shift();
60264	                        var pi = pp[i];
60265	                        while (pi.length) {
60266	                            pcoms1[i]="A"; // if created multiple C:s, their original seg is saved
60267	                            p2 && (pcoms2[i]="A"); // the same as above
60268	                            pp.splice(i++, 0, ["C"][concat](pi.splice(0, 6)));
60269	                        }
60270	                        pp.splice(i, 1);
60271	                        ii = mmax(p.length, p2 && p2.length || 0);
60272	                    }
60273	                },
60274	                fixM = function (path1, path2, a1, a2, i) {
60275	                    if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") {
60276	                        path2.splice(i, 0, ["M", a2.x, a2.y]);
60277	                        a1.bx = 0;
60278	                        a1.by = 0;
60279	                        a1.x = path1[i][1];
60280	                        a1.y = path1[i][2];
60281	                        ii = mmax(p.length, p2 && p2.length || 0);
60282	                    }
60283	                },
60284	                pcoms1 = [], // path commands of original path p
60285	                pcoms2 = [], // path commands of original path p2
60286	                pfirst = "", // temporary holder for original path command
60287	                pcom = ""; // holder for previous path command of original path
60288	            for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii; i++) {
60289	                p[i] && (pfirst = p[i][0]); // save current path command
60290
60291	                if (pfirst != "C") // C is not saved yet, because it may be result of conversion
60292	                {
60293	                    pcoms1[i] = pfirst; // Save current path command
60294	                    i && ( pcom = pcoms1[i-1]); // Get previous path command pcom
60295	                }
60296	                p[i] = processPath(p[i], attrs, pcom); // Previous path command is inputted to processPath
60297
60298	                if (pcoms1[i] != "A" && pfirst == "C") pcoms1[i] = "C"; // A is the only command
60299	                // which may produce multiple C:s
60300	                // so we have to make sure that C is also C in original path
60301
60302	                fixArc(p, i);
60302 // fixArc adds also the right amount of A:s to pcoms1
60303
60304	                if (p2) { // the same procedures is done to p2
60305	                    p2[i] && (pfirst = p2[i][0]);
60306	                    if (pfirst != "C")
60307	                    {
60308	                        pcoms2[i] = pfirst;
60309	                        i && (pcom = pcoms2[i-1]);
60310	                    }
60311	                    p2[i] = processPath(p2[i], attrs2, pcom);
60312
60313	                    if (pcoms2[i]!="A" && pfirst=="C") pcoms2[i]="C";
60314
60315	                    fixArc(p2, i);
60316	                }
60317	                fixM(p, p2, attrs, attrs2, i);
60318	                fixM(p2, p, attrs2, attrs, i);
60319	                var seg = p[i],
60320	                    seg2 = p2 && p2[i],
60321	                    seglen = seg.length,
60322	                    seg2len = p2 && seg2.length;
60323	                attrs.x = seg[seglen - 2];
60324	                attrs.y = seg[seglen - 1];
60325	                attrs.bx = toFloat(seg[seglen - 4]) || attrs.x;
60326	                attrs.by = toFloat(seg[seglen - 3]) || attrs.y;
60327	                attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x);
60328	                attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y);
60329	                attrs2.x = p2 && seg2[seg2len - 2];
60330	                attrs2.y = p2 && seg2[seg2len - 1];
60331	            }
60332	            if (!p2) {
60333	                pth.curve = pathClone(p);
60334	            }
60335	            return p2 ? [p, p2] : p;
60336	        }, null, pathClone),
60337	        parseDots = R._parseDots = cacher(function (gradient) {
60338	            var dots = [];
60339	            for (var i = 0, ii = gradient.length; i < ii; i++) {
60340	                var dot = {},
60341	                    par = gradient[i].match(/^([^:]*):?([\d\.]*)/);
60342	                dot.color = R.getRGB(par[1]);
60343	                if (dot.color.error) {
60344	                    return null;
60345	                }
60346	                dot.opacity = dot.color.opacity;
60347	                dot.color = dot.color.hex;
60348	                par[2] && (dot.offset = par[2] + "%");
60349	                dots.push(dot);
60350	            }
60351	            for (i = 1, ii = dots.length - 1; i < ii; i++) {
60352	                if (!dots[i].offset) {
60353	                    var start = toFloat(dots[i - 1].offset || 0),
60354	                        end = 0;
60355	                    for (var j = i + 1; j < ii; j++) {
60356	                        if (dots[j].offset) {
60357	                            end = dots[j].offset;
60358	                            break;
60359	                        }
60360	                    }
60361	                    if (!end) {
60362	                        end = 100;
60363	                        j = ii;
60364	                    }
60365	                    end = toFloat(end);
60366	                    var d = (end - start) / (j - i + 1);
60367	                    for (; i < j; i++) {
60368	                        start += d;
60369	                        dots[i].offset = start + "%";
60370	                    }
60371	                }
60372	            }
60373	            return dots;
60374	        }),
60375	        tear = R._tear = function (el, paper) {
60376	            el == paper.top && (paper.top = el.prev);
60377	            el == paper.bottom && (paper.bottom = el.next);
60378	            el.next && (el.next.prev = el.prev);
60379	            el.prev && (el.prev.next = el.next);
60380	        },
60381	        tofront = R._tofront = function (el, paper) {
60382	            if (paper.top === el) {
60383	                return;
60384	            }
60385	            tear(el, paper);
60386	            el.next = null;
60387	            el.prev = paper.top;
60388	            paper.top.next = el;
60389	            paper.top = el;
60390	        },
60391	        toback = R._toback = function (el, paper) {
60392	            if (paper.bottom === el) {
60393	                return;
60394	            }
60395	            tear(el, paper);
60396	            el.next = paper.bottom;
60397	            el.prev = null;
60398	            paper.bottom.prev = el;
60399	            paper.bottom = el;
60400	        },
60401	        insertafter = R._insertafter = function (el, el2, paper) {
60402	            tear(el, paper);
60403	            el2 == paper.top && (paper.top = el);
60404	            el2.next && (el2.next.prev = el);
60405	            el.next = el2.next;
60406	            el.prev = el2;
60407	            el2.next = el;
60408	        },
60409	        insertbefore = R._insertbefore = function (el, el2, paper) {
60410	            tear(el, paper);
60411	            el2 == paper.bottom && (paper.bottom = el);
60412	            el2.prev && (el2.prev.next = el);
60413	            el.prev = el2.prev;
60414	            el2.prev = el;
60415	            el.next = el2;
60416	        },
60417	        /*\
60418	         * Raphael.toMatrix
60419	         [ method ]
60420	         **
60421	         * Utility method
60422	         **
60423	         * Returns matrix of transformations applied to a given path
60424	         > Parameters
60425	         - path (string) path string
60426	         - transform (string|array) transformation string
60427	         = (object) @Matrix
60428	        \*/
60429	        toMatrix = R.toMatrix = function (path, transform) {
60430	            var bb = pathDimensions(path),
60431	                el = {
60432	                    _: {
60433	                        transform: E
60434	                    },
60435	                    getBBox: function () {
60436	                        return bb;
60437	                    }
60438	                };
60439	            extractTransform(el, transform);
60440	            return el.matrix;
60441	        },
60442	        /*\
60443	         * Raphael.transformPath
60444	         [ method ]
60445	         **
60446	         * Utility method
60447	         **
60448	         * Returns path transformed by a given transformation
60449	         > Parameters
60450	         - path (string) path string
60451	         - transform (string|array) transformation string
60452	         = (string) path
60453	        \*/
60454	        transformPath = R.transformPath = function (path, transform) {
60455	            return mapPath(path, toMatrix(path, transform));
60456	        },
60457	        extractTransform = R._extractTransform = function (el, tstr) {
60458	            if (tstr == null) {
60459	                return el._.transform;
60460	            }
60461	            tstr = Str(tstr).replace(/\.{3}|\u2026/g, el._.transform || E);
60462	            var tdata = R.parseTransformString(tstr),
60463	                deg = 0,
60464	                dx = 0,
60465	                dy = 0,
60466	                sx = 1,
60467	                sy = 1,
60468	                _ = el._,
60469	                m = new Matrix;
60470	            _.transform = tdata || [];
60471	            if (tdata) {
60472	                for (var i = 0, ii = tdata.length; i < ii; i++) {
60473	                    var t = tdata[i],
60474	                        tlen = t.length,
60475	                        command = Str(t[0]).toLowerCase(),
60476	                        absolute = t[0] != command,
60477	                        inver = absolute ? m.invert() : 0,
60478	                        x1,
60479	                        y1,
60480	                        x2,
60481	                        y2,
60482	                        bb;
60483	                    if (command == "t" && tlen == 3) {
60484	                        if (absolute) {
60485	                            x1 = inver.x(0, 0);
60486	                            y1 = inver.y(0, 0);
60487	                            x2 = inver.x(t[1], t[2]);
60488	                            y2 = inver.y(t[1], t[2]);
60489	                            m.translate(x2 - x1, y2 - y1);
60490	                        } else {
60491	                            m.translate(t[1], t[2]);
60492	                        }
60493	                    } else if (command == "r") {
60494	                        if (tlen == 2) {
60495	                            bb = bb || el.getBBox(1);
60496	                            m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2);
60497	                            deg += t[1];
60498	                        } else if (tlen == 4) {
60499	                            if (absolute) {
60500	                                x2 = inver.x(t[2], t[3]);
60501	                                y2 = inver.y(t[2], t[3]);
60502	                                m.rotate(t[1], x2, y2);
60503	                            } else {
60504	                                m.rotate(t[1], t[2], t[3]);
60505	                            }
60506	                            deg += t[1];
60507	                        }
60508	                    } else if (command == "s") {
60509	                        if (tlen == 2 || tlen == 3) {
60510	                            bb = bb || el.getBBox(1);
60511	                            m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2);
60512	                            sx *= t[1];
60513	                            sy *= t[tlen - 1];
60514	                        } else if (tlen == 5) {
60515	                            if (absolute) {
60516	                                x2 = inver.x(t[3], t[4]);
60517	                                y2 = inver.y(t[3], t[4]);
60518	                                m.scale(t[1], t[2], x2, y2);
60519	                            } else {
60520	                                m.scale(t[1], t[2], t[3], t[4]);
60521	                            }
60522	                            sx *= t[1];
60523	                            sy *= t[2];
60524	                        }
60525	                    } else if (command == "m" && tlen == 7) {
60526	                        m.add(t[1], t[2], t[3], t[4], t[5], t[6]);
60527	                    }
60528	                    _.dirtyT = 1;
60529	                    el.matrix = m;
60530	                }
60531	            }
60532
60533	            /*\
60534	             * Element.matrix
60535	             [ property (object) ]
60536	             **
60537	             * Keeps @Matrix object, which represents element transformation
60538	            \*/
60539	            el.matrix = m;
60540
60541	            _.sx = sx;
60542	            _.sy = sy;
60543	            _.deg = deg;
60544	            _.dx = dx = m.e;
60545	            _.dy = dy = m.f;
60546
60547	            if (sx == 1 && sy == 1 && !deg && _.bbox) {
60548	                _.bbox.x += +dx;
60549	                _.bbox.y += +dy;
60550	            } else {
60551	                _.dirtyT = 1;
60552	            }
60553	        },
60554	        getEmpty = function (item) {
60555	            var l = item[0];
60556	            switch (l.toLowerCase()) {
60557	                case "t": return [l, 0, 0];
60558	                case "m": return [l, 1, 0, 0, 1, 0, 0];
60559	                case "r": if (item.length == 4) {
60560	                    return [l, 0, item[2], item[3]];
60561	                } else {
60562	                    return [l, 0];
60563	                }
60564	                case "s": if (item.length == 5) {
60565	                    return [l, 1, 1, item[3], item[4]];
60566	                } else if (item.length == 3) {
60567	                    return [l, 1, 1];
60568	                } else {
60569	                    return [l, 1];
60570	                }
60571	            }
60572	        },
60573	        equaliseTransform = R._equaliseTransform = function (t1, t2) {
60574	            t2 = Str(t2).replace(/\.{3}|\u2026/g, t1);
60575	            t1 = R.parseTransformString(t1) || [];
60576	            t2 = R.parseTransformString(t2) || [];
60577	            var maxlength = mmax(t1.length, t2.length),
60578	                from = [],
60579	                to = [],
60580	                i = 0, j, jj,
60581	                tt1, tt2;
60582	            for (; i < maxlength; i++) {
60583	                tt1 = t1[i] || getEmpty(t2[i]);
60584	                tt2 = t2[i] || getEmpty(tt1);
60585	                if ((tt1[0] != tt2[0]) ||
60586	                    (tt1[0].toLowerCase() == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) ||
60587	                    (tt1[0].toLowerCase() == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4]))
60588	                    ) {
60589	                    return;
60590	                }
60591	                from[i] = [];
60592	                to[i] = [];
60593	                for (j = 0, jj = mmax(tt1.length, tt2.length); j < jj; j++) {
60594	                    j in tt1 && (from[i][j] = tt1[j]);
60595	                    j in tt2 && (to[i][j] = tt2[j]);
60596	                }
60597	            }
60598	            return {
60599	                from: from,
60600	                to: to
60601	            };
60602	        };
60603	    R._getContainer = function (x, y, w, h) {
60604	        var container;
60605	        container = h == null && !R.is(x, "object") ? g.doc.getElementById(x) : x;
60606	        if (container == null) {
60607	            return;
60608	        }
60609	        if (container.tagName) {
60610	            if (y == null) {
60611	                return {
60612	                    container: container,
60613	                    width: container.style.pixelWidth || container.offsetWidth,
60614	                    height: container.style.pixelHeight || container.offsetHeight
60615	                };
60616	            } else {
60617	                return {
60618	                    container: container,
60619	                    width: y,
60620	                    height: w
60621	                };
60622	            }
60623	        }
60624	        return {
60625	            container: 1,
60626	            x: x,
60627	            y: y,
60628	            width: w,
60629	            height: h
60630	        };
60631	    };
60632	    /*\
60633	     * Raphael.pathToRelative
60634	     [ method ]
60635	     **
60636	     * Utility method
60637	     **
60638	     * Converts path to relative form
60639	     > Parameters
60640	     - pathString (string|array) path string or array of segments
60641	     = (array) array of segments.
60642	    \*/
60643	    R.pathToRelative = pathToRelative;
60644	    R._engine = {};
60645	    /*\
60646	     * Raphael.path2curve
60647	     [ method ]
60648	     **
60649	     * Utility method
60650	     **
60651	     * Converts path to a new path where all segments are cubic bezier curves.
60652	     > Parameters
60653	     - pathString (string|array) path string or array of segments
60654	     = (array) array of segments.
60655	    \*/
60656	    R.path2curve = path2curve;
60657	    /*\
60658	     * Raphael.matrix
60659	     [ method ]
60660	     **
60661	     * Utility method
60662	     **
60663	     * Returns matrix based on given parameters.
60664	     > Parameters
60665	     - a (number)
60666	     - b (number)
60667	     - c (number)
60668	     - d (number)
60669	     - e (number)
60670	     - f (number)
60671	     = (object) @Matrix
60672	    \*/
60673	    R.matrix = function (a, b, c, d, e, f) {
60674	        return new Matrix(a, b, c, d, e, f);
60675	    };
60676	    function Matrix(a, b, c, d, e, f) {
60677	        if (a != null) {
60678	            this.a = +a;
60679	            this.b = +b;
60680	            this.c = +c;
60681	            this.d = +d;
60682	            this.e = +e;
60683	            this.f = +f;
60684	        } else {
60685	            this.a = 1;
60686	            this.b = 0;
60687	            this.c = 0;
60688	            this.d = 1;
60689	            this.e = 0;
60690	            this.f = 0;
60691	        }
60692	    }
60693	    (function (matrixproto) {
60694	        /*\
60695	         * Matrix.add
60696	         [ method ]
60697	         **
60698	         * Adds given matrix to existing one.
60699	         > Parameters
60700	         - a (number)
60701	         - b (number)
60702	         - c (number)
60703	         - d (number)
60704	         - e (number)
60705	         - f (number)
60706	         or
60707	         - matrix (object) @Matrix
60708	        \*/
60709	        matrixproto.add = function (a, b, c, d, e, f) {
60710	            var out = [[], [], []],
60711	                m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]],
60712	                matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
60713	                x, y, z, res;
60714
60715	            if (a && a instanceof Matrix) {
60716	                matrix = [[a.a, a.c, a.e], [a.b, a.d, a.f], [0, 0, 1]];
60717	            }
60718
60719	            for (x = 0; x < 3; x++) {
60720	                for (y = 0; y < 3; y++) {
60721	                    res = 0;
60722	                    for (z = 0; z < 3; z++) {
60723	                        res += m[x][z] * matrix[z][y];
60724	                    }
60725	                    out[x][y] = res;
60726	                }
60727	            }
60728	            this.a = out[0][0];
60729	            this.b = out[1][0];
60730	            this.c = out[0][1];
60731	            this.d = out[1][1];
60732	            this.e = out[0][2];
60733	            this.f = out[1][2];
60734	        };
60735	        /*\
60736	         * Matrix.invert
60737	         [ method ]
60738	         **
60739	         * Returns inverted version of the matrix
60740	         = (object) @Matrix
60741	        \*/
60742	        matrixproto.invert = function () {
60743	            var me = this,
60744	                x = me.a * me.d - me.b * me.c;
60745	            return new Matrix(me.d / x, -me.b / x, -me.c / x, me.a / x, (me.c * me.f - me.d * me.e) / x, (me.b * me.e - me.a * me.f) / x);
60746	        };
60747	        /*\
60748	         * Matrix.clone
60749	         [ method ]
60750	         **
60751	         * Returns copy of the matrix
60752	         = (object) @Matrix
60753	        \*/
60754	        matrixproto.clone = function () {
60755	            return new Matrix(this.a, this.b, this.c, this.d, this.e, this.f);
60756	        };
60757	        /*\
60758	         * Matrix.translate
60759	         [ method ]
60760	         **
60761	         * Translate the matrix
60762	         > Parameters
60763	         - x (number)
60764	         - y (number)
60765	        \*/
60766	        matrixproto.translate = function (x, y) {
60767	            this.add(1, 0, 0, 1, x, y);
60768	        };
60769	        /*\
60770	         * Matrix.scale
60771	         [ method ]
60772	         **
60773	         * Scales the matrix
60774	         > Parameters
60775	         - x (number)
60776	         - y (number) #optional
60777	         - cx (number) #optional
60778	         - cy (number) #optional
60779	        \*/
60780	        matrixproto.scale = function (x, y, cx, cy) {
60781	            y == null && (y = x);
60782	            (cx || cy) && this.add(1, 0, 0, 1, cx, cy);
60783	            this.add(x, 0, 0, y, 0, 0);
60784	            (cx || cy) && this.add(1, 0, 0, 1, -cx, -cy);
60785	        };
60786	        /*\
60787	         * Matrix.rotate
60788	         [ method ]
60789	         **
60790	         * Rotates the matrix
60791	         > Parameters
60792	         - a (number)
60793	         - x (number)
60794	         - y (number)
60795	        \*/
60796	        matrixproto.rotate = function (a, x, y) {
60797	            a = R.rad(a);
60798	            x = x || 0;
60799	            y = y || 0;
60800	            var cos = +math.cos(a).toFixed(9),
60801	                sin = +math.sin(a).toFixed(9);
60802	            this.add(cos, sin, -sin, cos, x, y);
60803	            this.add(1, 0, 0, 1, -x, -y);
60804	        };
60805	        /*\
60806	         * Matrix.x
60807	         [ method ]
60808	         **
60809	         * Return x coordinate for given point after transformation described by the matrix. See also @Matrix.y
60810	         > Parameters
60811	         - x (number)
60812	         - y (number)
60813	         = (number) x
60814	        \*/
60815	        matrixproto.x = function (x, y) {
60816	            return x * this.a + y * this.c + this.e;
60817	        };
60818	        /*\
60819	         * Matrix.y
60820	         [ method ]
60821	         **
60822	         * Return y coordinate for given point after transformation described by the matrix. See also @Matrix.x
60823	         > Parameters
60824	         - x (number)
60825	         - y (number)
60826	         = (number) y
60827	        \*/
60828	        matrixproto.y = function (x, y) {
60829	            return x * this.b + y * this.d + this.f;
60830	        };
60831	        matrixproto.get = function (i) {
60832	            return +this[Str.fromCharCode(97 + i)].toFixed(4);
60833	        };
60834	        matrixproto.toString = function () {
60835	            return R.svg ?
60836	                "matrix(" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)].join() + ")" :
60837	                [this.get(0), this.get(2), this.get(1), this.get(3), 0, 0].join();
60838	        };
60839	        matrixproto.toFilter = function () {
60840	            return "progid:DXImageTransform.Microsoft.Matrix(M11=" + this.get(0) +
60841	                ", M12=" + this.get(2) + ", M21=" + this.get(1) + ", M22=" + this.get(3) +
60842	                ", Dx=" + this.get(4) + ", Dy=" + this.get(5) + ", sizingmethod='auto expand')";
60843	        };
60844	        matrixproto.offset = function () {
60845	            return [this.e.toFixed(4), this.f.toFixed(4)];
60846	        };
60847	        function norm(a) {
60848	            return a[0] * a[0] + a[1] * a[1];
60849	        }
60850	        function normalize(a) {
60851	            var mag = math.sqrt(norm(a));
60852	            a[0] && (a[0] /= mag);
60853	            a[1] && (a[1] /= mag);
60854	        }
60855	        /*\
60856	         * Matrix.split
60857	         [ method ]
60858	         **
60859	         * Splits matrix into primitive transformations
60860	         = (object) in format:
60861	         o dx (number) translation by x
60862	         o dy (number) translation by y
60863	         o scalex (number) scale by x
60864	         o scaley (number) scale by y
60865	         o shear (number) shear
60866	         o rotate (number) rotation in deg
60867	         o isSimple (boolean) could it be represented via simple transformations
60868	        \*/
60869	        matrixproto.split = function () {
60870	            var out = {};
60871	            // translation
60872	            out.dx = this.e;
60873	            out.dy = this.f;
60874
60875	            // scale and shear
60876	            var row = [[this.a, this.c], [this.b, this.d]];
60877	            out.scalex = math.sqrt(norm(row[0]));
60878	            normalize(row[0]);
60879
60880	            out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];
60881	            row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];
60882
60883	            out.scaley = math.sqrt(norm(row[1]));
60884	            normalize(row[1]);
60885	            out.shear /= out.scaley;
60886
60887	            // rotation
60888	            var sin = -row[0][1],
60889	                cos = row[1][1];
60890	            if (cos < 0) {
60891	                out.rotate = R.deg(math.acos(cos));
60892	                if (sin < 0) {
60893	                    out.rotate = 360 - out.rotate;
60894	                }
60895	            } else {
60896	                out.rotate = R.deg(math.asin(sin));
60897	            }
60898
60899	            out.isSimple = !+out.shear.toFixed(9) && (out.scalex.toFixed(9) == out.scaley.toFixed(9) || !out.rotate);
60900	            out.isSuperSimple = !+out.shear.toFixed(9) && out.scalex.toFixed(9) == out.scaley.toFixed(9) && !out.rotate;
60901	            out.noRotation = !+out.shear.toFixed(9) && !out.rotate;
60902	            return out;
60903	        };
60904	        /*\
60905	         * Matrix.toTransformString
60906	         [ method ]
60907	         **
60908	         * Return transform string that represents given matrix
60909	         = (string) transform string
60910	        \*/
60911	        matrixproto.toTransformString = function (shorter) {
60912	            var s = shorter || this[split]();
60913	            if (s.isSimple) {
60914	                s.scalex = +s.scalex.toFixed(4);
60915	                s.scaley = +s.scaley.toFixed(4);
60916	                s.rotate = +s.rotate.toFixed(4);
60917	                return  (s.dx || s.dy ? "t" + [s.dx, s.dy] : E) +
60918	                        (s.scalex != 1 || s.scaley != 1 ? "s" + [s.scalex, s.scaley, 0, 0] : E) +
60919	                        (s.rotate ? "r" + [s.rotate, 0, 0] : E);
60920	            } else {
60921	                return "m" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)];
60922	            }
60923	        };
60924	    })(Matrix.prototype);
60925
60926	    var preventDefault = function () {
60927	        this.returnValue = false;
60928	    },
60929	    preventTouch = function () {
60930	        return this.originalEvent.preventDefault();
60931	    },
60932	    stopPropagation = function () {
60933	        this.cancelBubble = true;
60934	    },
60935	    stopTouch = function () {
60936	        return this.originalEvent.stopPropagation();
60937	    },
60938	    getEventPosition = function (e) {
60939	        var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
60940	            scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;
60941
60942	        return {
60943	            x: e.clientX + scrollX,
60944	            y: e.clientY + scrollY
60945	        };
60946	    },
60947	    addEvent = (function () {
60948	        if (g.doc.addEventListener) {
60949	            return function (obj, type, fn, element) {
60950	                var f = function (e) {
60951	                    var pos = getEventPosition(e);
60952	                    return fn.call(element, e, pos.x, pos.y);
60953	                };
60954	                obj.addEventListener(type, f, false);
60955
60956	                if (supportsTouch && touchMap[type]) {
60957	                    var _f = function (e) {
60958	                        var pos = getEventPosition(e),
60959	                            olde = e;
60960
60961	                        for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) {
60962	                            if (e.targetTouches[i].target == obj) {
60963	                                e = e.targetTouches[i];
60964	                                e.originalEvent = olde;
60965	                                e.preventDefault = preventTouch;
60966	                                e.stopPropagation = stopTouch;
60967	                                break;
60968	                            }
60969	                        }
60970
60971	                        return fn.call(element, e, pos.x, pos.y);
60972	                    };
60973	                    obj.addEventListener(touchMap[type], _f, false);
60974	                }
60975
60976	                return function () {
60977	                    obj.removeEventListener(type, f, false);
60978
60979	                    if (supportsTouch && touchMap[type])
60980	                        obj.removeEventListener(touchMap[type], _f, false);
60981
60982	                    return true;
60983	                };
60984	            };
60985	        } else if (g.doc.attachEvent) {
60986	            return function (obj, type, fn, element) {
60987	                var f = function (e) {
60988	                    e = e || g.win.event;
60989	                    var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
60990	                        scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,
60991	                        x = e.clientX + scrollX,
60992	                        y = e.clientY + scrollY;
60993	                    e.preventDefault = e.preventDefault || preventDefault;
60994	                    e.stopPropagation = e.stopPropagation || stopPropagation;
60995	                    return fn.call(element, e, x, y);
60996	                };
60997	                obj.attachEvent("on" + type, f);
60998	                var detacher = function () {
60999	                    obj.detachEvent("on" + type, f);
61000	                    return true;
61001	                };
61002	                return detacher;
61003	            };
61004	        }
61005	    })(),
61006	    drag = [],
61007	    dragMove = function (e) {
61008	        var x = e.clientX,
61009	            y = e.clientY,
61010	            scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
61011	            scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,
61012	            dragi,
61013	            j = drag.length;
61014	        while (j--) {
61015	            dragi = drag[j];
61016	            if (supportsTouch && e.touches) {
61017	                var i = e.touches.length,
61018	                    touch;
61019	                while (i--) {
61020	                    touch = e.touches[i];
61021	                    if (touch.identifier == dragi.el._drag.id) {
61022	                        x = touch.clientX;
61023	                        y = touch.clientY;
61024	                        (e.originalEvent ? e.originalEvent : e).preventDefault();
61025	                        break;
61026	                    }
61027	                }
61028	            } else {
61029	                e.preventDefault();
61030	            }
61031	            var node = dragi.el.node,
61032	                o,
61033	                next = node.nextSibling,
61034	                parent = node.parentNode,
61035	                display = node.style.display;
61036	            g.win.opera && parent.removeChild(node);
61037	            node.style.display = "none";
61038	            o = dragi.el.paper.getElementByPoint(x, y);
61039	            node.style.display = display;
61040	            g.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node));
61041	            o && eve("raphael.drag.over." + dragi.el.id, dragi.el, o);
61042	            x += scrollX;
61043	            y += scrollY;
61044	            eve("raphael.drag.move." + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e);
61045	        }
61046	    },
61047	    dragUp = function (e) {
61048	        R.unmousemove(dragMove).unmouseup(dragUp);
61049	        var i = drag.length,
61050	            dragi;
61051	        while (i--) {
61052	            dragi = drag[i];
61053	            dragi.el._drag = {};
61054	            eve("raphael.drag.end." + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e);
61055	        }
61056	        drag = [];
61057	    },
61058	    /*\
61059	     * Raphael.el
61060	     [ property (object) ]
61061	     **
61062	     * You can add your own method to elements. This is useful when you want to hack default functionality or
61063	     * want to wrap some common transformation or attributes in one method. In difference to canvas methods,
61064	     * you can redefine element method at any time. Expending element methods wouldn’t affect set.
61065	     > Usage
61066	     | Raphael.el.red = function () {
61067	     |     this.attr({fill: "#f00"});
61068	     | };
61069	     | // then use it
61070	     | paper.circle(100, 100, 20).red();
61071	    \*/
61072	    elproto = R.el = {};
61073	    /*\
61074	     * Element.click
61075	     [ method ]
61076	     **
61077	     * Adds event handler for click for the element.
61078	     > Parameters
61079	     - handler (function) handler for the event
61080	     = (object) @Element
61081	    \*/
61082	    /*\
61083	     * Element.unclick
61084	     [ method ]
61085	     **
61086	     * Removes event handler for click for the element.
61087	     > Parameters
61088	     - handler (function) #optional handler for the event
61089	     = (object) @Element
61090	    \*/
61091
61092	    /*\
61093	     * Element.dblclick
61094	     [ method ]
61095	     **
61096	     * Adds event handler for double click for the element.
61097	     > Parameters
61098	     - handler (function) handler for the event
61099	     = (object) @Element
61100	    \*/
61101	    /*\
61102	     * Element.undblclick
61103	     [ method ]
61104	     **
61105	     * Removes event handler for double click for the element.
61106	     > Parameters
61107	     - handler (function) #optional handler for the event
61108	     = (object) @Element
61109	    \*/
61110
61111	    /*\
61112	     * Element.mousedown
61113	     [ method ]
61114	     **
61115	     * Adds event handler for mousedown for the element.
61116	     > Parameters
61117	     - handler (function) handler for the event
61118	     = (object) @Element
61119	    \*/
61120	    /*\
61121	     * Element.unmousedown
61122	     [ method ]
61123	     **
61124	     * Removes event handler for mousedown for the element.
61125	     > Parameters
61126	     - handler (function) #optional handler for the event
61127	     = (object) @Element
61128	    \*/
61129
61130	    /*\
61131	     * Element.mousemove
61132	     [ method ]
61133	     **
61134	     * Adds event handler for mousemove for the element.
61135	     > Parameters
61136	     - handler (function) handler for the event
61137	     = (object) @Element
61138	    \*/
61139	    /*\
61140	     * Element.unmousemove
61141	     [ method ]
61142	     **
61143	     * Removes event handler for mousemove for the element.
61144	     > Parameters
61145	     - handler (function) #optional handler for the event
61146	     = (object) @Element
61147	    \*/
61148
61149	    /*\
61150	     * Element.mouseout
61151	     [ method ]
61152	     **
61153	     * Adds event handler for mouseout for the element.
61154	     > Parameters
61155	     - handler (function) handler for the event
61156	     = (object) @Element
61157	    \*/
61158	    /*\
61159	     * Element.unmouseout
61160	     [ method ]
61161	     **
61162	     * Removes event handler for mouseout for the element.
61163	     > Parameters
61164	     - handler (function) #optional handler for the event
61165	     = (object) @Element
61166	    \*/
61167
61168	    /*\
61169	     * Element.mouseover
61170	     [ method ]
61171	     **
61172	     * Adds event handler for mouseover for the element.
61173	     > Parameters
61174	     - handler (function) handler for the event
61175	     = (object) @Element
61176	    \*/
61177	    /*\
61178	     * Element.unmouseover
61179	     [ method ]
61180	     **
61181	     * Removes event handler for mouseover for the element.
61182	     > Parameters
61183	     - handler (function) #optional handler for the event
61184	     = (object) @Element
61185	    \*/
61186
61187	    /*\
61188	     * Element.mouseup
61189	     [ method ]
61190	     **
61191	     * Adds event handler for mouseup for the element.
61192	     > Parameters
61193	     - handler (function) handler for the event
61194	     = (object) @Element
61195	    \*/
61196	    /*\
61197	     * Element.unmouseup
61198	     [ method ]
61199	     **
61200	     * Removes event handler for mouseup for the element.
61201	     > Parameters
61202	     - handler (function) #optional handler for the event
61203	     = (object) @Element
61204	    \*/
61205
61206	    /*\
61207	     * Element.touchstart
61208	     [ method ]
61209	     **
61210	     * Adds event handler for touchstart for the element.
61211	     > Parameters
61212	     - handler (function) handler for the event
61213	     = (object) @Element
61214	    \*/
61215	    /*\
61216	     * Element.untouchstart
61217	     [ method ]
61218	     **
61219	     * Removes event handler for touchstart for the element.
61220	     > Parameters
61221	     - handler (function) #optional handler for the event
61222	     = (object) @Element
61223	    \*/
61224
61225	    /*\
61226	     * Element.touchmove
61227	     [ method ]
61228	     **
61229	     * Adds event handler for touchmove for the element.
61230	     > Parameters
61231	     - handler (function) handler for the event
61232	     = (object) @Element
61233	    \*/
61234	    /*\
61235	     * Element.untouchmove
61236	     [ method ]
61237	     **
61238	     * Removes event handler for touchmove for the element.
61239	     > Parameters
61240	     - handler (function) #optional handler for the event
61241	     = (object) @Element
61242	    \*/
61243
61244	    /*\
61245	     * Element.touchend
61246	     [ method ]
61247	     **
61248	     * Adds event handler for touchend for the element.
61249	     > Parameters
61250	     - handler (function) handler for the event
61251	     = (object) @Element
61252	    \*/
61253	    /*\
61254	     * Element.untouchend
61255	     [ method ]
61256	     **
61257	     * Removes event handler for touchend for the element.
61258	     > Parameters
61259	     - handler (function) #optional handler for the event
61260	     = (object) @Element
61261	    \*/
61262
61263	    /*\
61264	     * Element.touchcancel
61265	     [ method ]
61266	     **
61267	     * Adds event handler for touchcancel for the element.
61268	     > Parameters
61269	     - handler (function) handler for the event
61270	     = (object) @Element
61271	    \*/
61272	    /*\
61273	     * Element.untouchcancel
61274	     [ method ]
61275	     **
61276	     * Removes event handler for touchcancel for the element.
61277	     > Parameters
61278	     - handler (function) #optional handler for the event
61279	     = (object) @Element
61280	    \*/
61281	    for (var i = events.length; i--;) {
61282	        (function (eventName) {
61283	            R[eventName] = elproto[eventName] = function (fn, scope) {
61284	                if (R.is(fn, "function")) {
61285	                    this.events = this.events || [];
61286	                    this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || g.doc, eventName, fn, scope || this)});
61287	                }
61288	                return this;
61289	            };
61290	            R["un" + eventName] = elproto["un" + eventName] = function (fn) {
61291	                var events = this.events || [],
61292	                    l = events.length;
61293	                while (l--){
61294	                    if (events[l].name == eventName && (R.is(fn, "undefined") || events[l].f == fn)) {
61295	                        events[l].unbind();
61296	                        events.splice(l, 1);
61297	                        !events.length && delete this.events;
61298	                    }
61299	                }
61300	                return this;
61301	            };
61302	        })(events[i]);
61303	    }
61304
61305	    /*\
61306	     * Element.data
61307	     [ method ]
61308	     **
61309	     * Adds or retrieves given value associated with given key.
61310	     **
61311	     * See also @Element.removeData
61312	     > Parameters
61313	     - key (string) key to store data
61314	     - value (any) #optional value to store
61315	     = (object) @Element
61316	     * or, if value is not specified:
61317	     = (any) value
61318	     * or, if key and value are not specified:
61319	     = (object) Key/value pairs for all the data associated with the element.
61320	     > Usage
61321	     | for (var i = 0, i < 5, i++) {
61322	     |     paper.circle(10 + 15 * i, 10, 10)
61323	     |          .attr({fill: "#000"})
61324	     |          .data("i", i)
61325	     |          .click(function () {
61326	     |             alert(this.data("i"));
61327	     |          });
61328	     | }
61329	    \*/
61330	    elproto.data = function (key, value) {
61331	        var data = eldata[this.id] = eldata[this.id] || {};
61332	        if (arguments.length == 0) {
61333	            return data;
61334	        }
61335	        if (arguments.length == 1) {
61336	            if (R.is(key, "object")) {
61337	                for (var i in key) if (key[has](i)) {
61338	                    this.data(i, key[i]);
61339	                }
61340	                return this;
61341	            }
61342	            eve("raphael.data.get." + this.id, this, data[key], key);
61343	            return data[key];
61344	        }
61345	        data[key] = value;
61346	        eve("raphael.data.set." + this.id, this, value, key);
61347	        return this;
61348	    };
61349	    /*\
61350	     * Element.removeData
61351	     [ method ]
61352	     **
61353	     * Removes value associated with an element by given key.
61354	     * If key is not provided, removes all the data of the element.
61355	     > Parameters
61356	     - key (string) #optional key
61357	     = (object) @Element
61358	    \*/
61359	    elproto.removeData = function (key) {
61360	        if (key == null) {
61361	            eldata[this.id] = {};
61362	        } else {
61363	            eldata[this.id] && delete eldata[this.id][key];
61364	        }
61365	        return this;
61366	    };
61367	     /*\
61368	     * Element.getData
61369	     [ method ]
61370	     **
61371	     * Retrieves the element data
61372	     = (object) data
61373	    \*/
61374	    elproto.getData = function () {
61375	        return clone(eldata[this.id] || {});
61376	    };
61377	    /*\
61378	     * Element.hover
61379	     [ method ]
61380	     **
61381	     * Adds event handlers for hover for the element.
61382	     > Parameters
61383	     - f_in (function) handler for hover in
61384	     - f_out (function) handler for hover out
61385	     - icontext (object) #optional context for hover in handler
61386	     - ocontext (object) #optional context for hover out handler
61387	     = (object) @Element
61388	    \*/
61389	    elproto.hover = function (f_in, f_out, scope_in, scope_out) {
61390	        return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in);
61391	    };
61392	    /*\
61393	     * Element.unhover
61394	     [ method ]
61395	     **
61396	     * Removes event handlers for hover for the element.
61397	     > Parameters
61398	     - f_in (function) handler for hover in
61399	     - f_out (function) handler for hover out
61400	     = (object) @Element
61401	    \*/
61402	    elproto.unhover = function (f_in, f_out) {
61403	        return this.unmouseover(f_in).unmouseout(f_out);
61404	    };
61405	    var draggable = [];
61406	    /*\
61407	     * Element.drag
61408	     [ method ]
61409	     **
61410	     * Adds event handlers for drag of the element.
61411	     > Parameters
61412	     - onmove (function) handler for moving
61413	     - onstart (function) handler for drag start
61414	     - onend (function) handler for drag end
61415	     - mcontext (object) #optional context for moving handler
61416	     - scontext (object) #optional context for drag start handler
61417	     - econtext (object) #optional context for drag end handler
61418	     * Additionally following `drag` events will be triggered: `drag.start.<id>` on start,
61419	     * `drag.end.<id>` on end and `drag.move.<id>` on every move. When element will be dragged over another element
61420	     * `drag.over.<id>` will be fired as well.
61421	     *
61422	     * Start event and start handler will be called in specified context or in context of the element with following parameters:
61423	     o x (number) x position of the mouse
61424	     o y (number) y position of the mouse
61425	     o event (object) DOM event object
61426	     * Move event and move handler will be called in specified context or in context of the element with following parameters:
61427	     o dx (number) shift by x from the start point
61428	     o dy (number) shift by y from the start point
61429	     o x (number) x position of the mouse
61430	     o y (number) y position of the mouse
61431	     o event (object) DOM event object
61432	     * End event and end handler will be called in specified context or in context of the element with following parameters:
61433	     o event (object) DOM event object
61434	     = (object) @Element
61435	    \*/
61436	    elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) {
61437	        function start(e) {
61438	            (e.originalEvent || e).preventDefault();
61439	            var x = e.clientX,
61440	                y = e.clientY,
61441	                scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
61442	                scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;
61443	            this._drag.id = e.identifier;
61444	            if (supportsTouch && e.touches) {
61445	                var i = e.touches.length, touch;
61446	                while (i--) {
61447	                    touch = e.touches[i];
61448	                    this._drag.id = tou
61448ch.identifier;
61449	                    if (touch.identifier == this._drag.id) {
61450	                        x = touch.clientX;
61451	                        y = touch.clientY;
61452	                        break;
61453	                    }
61454	                }
61455	            }
61456	            this._drag.x = x + scrollX;
61457	            this._drag.y = y + scrollY;
61458	            !drag.length && R.mousemove(dragMove).mouseup(dragUp);
61459	            drag.push({el: this, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope});
61460	            onstart && eve.on("raphael.drag.start." + this.id, onstart);
61461	            onmove && eve.on("raphael.drag.move." + this.id, onmove);
61462	            onend && eve.on("raphael.drag.end." + this.id, onend);
61463	            eve("raphael.drag.start." + this.id, start_scope || move_scope || this, e.clientX + scrollX, e.clientY + scrollY, e);
61464	        }
61465	        this._drag = {};
61466	        draggable.push({el: this, start: start});
61467	        this.mousedown(start);
61468	        return this;
61469	    };
61470	    /*\
61471	     * Element.onDragOver
61472	     [ method ]
61473	     **
61474	     * Shortcut for assigning event handler for `drag.over.<id>` event, where id is id of the element (see @Element.id).
61475	     > Parameters
61476	     - f (function) handler for event, first argument would be the element you are dragging over
61477	    \*/
61478	    elproto.onDragOver = function (f) {
61479	        f ? eve.on("raphael.drag.over." + this.id, f) : eve.unbind("raphael.drag.over." + this.id);
61480	    };
61481	    /*\
61482	     * Element.undrag
61483	     [ method ]
61484	     **
61485	     * Removes all drag event handlers from given element.
61486	    \*/
61487	    elproto.undrag = function () {
61488	        var i = draggable.length;
61489	        while (i--) if (draggable[i].el == this) {
61490	            this.unmousedown(draggable[i].start);
61491	            draggable.splice(i, 1);
61492	            eve.unbind("raphael.drag.*." + this.id);
61493	        }
61494	        !draggable.length && R.unmousemove(dragMove).unmouseup(dragUp);
61495	        drag = [];
61496	    };
61497	    /*\
61498	     * Paper.circle
61499	     [ method ]
61500	     **
61501	     * Draws a circle.
61502	     **
61503	     > Parameters
61504	     **
61505	     - x (number) x coordinate of the centre
61506	     - y (number) y coordinate of the centre
61507	     - r (number) radius
61508	     = (object) Raphaël element object with type “circle”
61509	     **
61510	     > Usage
61511	     | var c = paper.circle(50, 50, 40);
61512	    \*/
61513	    paperproto.circle = function (x, y, r) {
61514	        var out = R._engine.circle(this, x || 0, y || 0, r || 0);
61515	        this.__set__ && this.__set__.push(out);
61516	        return out;
61517	    };
61518	    /*\
61519	     * Paper.rect
61520	     [ method ]
61521	     *
61522	     * Draws a rectangle.
61523	     **
61524	     > Parameters
61525	     **
61526	     - x (number) x coordinate of the top left corner
61527	     - y (number) y coordinate of the top left corner
61528	     - width (number) width
61529	     - height (number) height
61530	     - r (number) #optional radius for rounded corners, default is 0
61531	     = (object) Raphaël element object with type “rect”
61532	     **
61533	     > Usage
61534	     | // regular rectangle
61535	     | var c = paper.rect(10, 10, 50, 50);
61536	     | // rectangle with rounded corners
61537	     | var c = paper.rect(40, 40, 50, 50, 10);
61538	    \*/
61539	    paperproto.rect = function (x, y, w, h, r) {
61540	        var out = R._engine.rect(this, x || 0, y || 0, w || 0, h || 0, r || 0);
61541	        this.__set__ && this.__set__.push(out);
61542	        return out;
61543	    };
61544	    /*\
61545	     * Paper.ellipse
61546	     [ method ]
61547	     **
61548	     * Draws an ellipse.
61549	     **
61550	     > Parameters
61551	     **
61552	     - x (number) x coordinate of the centre
61553	     - y (number) y coordinate of the centre
61554	     - rx (number) horizontal radius
61555	     - ry (number) vertical radius
61556	     = (object) Raphaël element object with type “ellipse”
61557	     **
61558	     > Usage
61559	     | var c = paper.ellipse(50, 50, 40, 20);
61560	    \*/
61561	    paperproto.ellipse = function (x, y, rx, ry) {
61562	        var out = R._engine.ellipse(this, x || 0, y || 0, rx || 0, ry || 0);
61563	        this.__set__ && this.__set__.push(out);
61564	        return out;
61565	    };
61566	    /*\
61567	     * Paper.path
61568	     [ method ]
61569	     **
61570	     * Creates a path element by given path data string.
61571	     > Parameters
61572	     - pathString (string) #optional path string in SVG format.
61573	     * Path string consists of one-letter commands, followed by comma seprarated arguments in numercal form. Example:
61574	     | "M10,20L30,40"
61575	     * Here we can see two commands: “M”, with arguments `(10, 20)` and “L” with arguments `(30, 40)`. Upper case letter mean command is absolute, lower case—relative.
61576	     *
61577	     # <p>Here is short list of commands available, for more details see <a href="http://www.w3.org/TR/SVG/paths.html#PathData" title="Details of a path's data attribute's format are described 
61577in the SVG specification.">SVG path string format</a>.</p>
61578	     # <table><thead><tr><th>Command</th><th>Name</th><th>Parameters</th></tr></thead><tbody>
61579	     # <tr><td>M</td><td>moveto</td><td>(x y)+</td></tr>
61580	     # <tr><td>Z</td><td>closepath</td><td>(none)</td></tr>
61581	     # <tr><td>L</td><td>lineto</td><td>(x y)+</td></tr>
61582	     # <tr><td>H</td><td>horizontal lineto</td><td>x+</td></tr>
61583	     # <tr><td>V</td><td>vertical lineto</td><td>y+</td></tr>
61584	     # <tr><td>C</td><td>curveto</td><td>(x1 y1 x2 y2 x y)+</td></tr>
61585	     # <tr><td>S</td><td>smooth curveto</td><td>(x2 y2 x y)+</td></tr>
61586	     # <tr><td>Q</td><td>quadratic Bézier curveto</td><td>(x1 y1 x y)+</td></tr>
61587	     # <tr><td>T</td><td>smooth quadratic Bézier curveto</td><td>(x y)+</td></tr>
61588	     # <tr><td>A</td><td>elliptical arc</td><td>(rx ry x-axis-rotation large-arc-flag sweep-flag x y)+</td></tr>
61589	     # <tr><td>R</td><td><a href="http://en.wikipedia.org/wiki/Catmull–Rom_spline#Catmull.E2.80.93Rom_spline">Catmull-Rom curveto</a>*</td><td>x1 y1 (x y)+</td></tr></tbody></table>
61590	     * * “Catmull-Rom curveto” is a not standard SVG command and added in 2.0 to make life easier.
61591	     * Note: there is a special case when path consist of just three commands: “M10,10R…z”. In this case path will smoothly connects to its beginning.
61592	     > Usage
61593	     | var c = paper.path("M10 10L90 90");
61594	     | // draw a diagonal line:
61595	     | // move to 10,10, line to 90,90
61596	     * For example of path strings, check out these icons: http://raphaeljs.com/icons/
61597	    \*/
61598	    paperproto.path = function (pathString) {
61599	        pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E);
61600	        var out = R._engine.path(R.format[apply](R, arguments), this);
61601	        this.__set__ && this.__set__.push(out);
61602	        return out;
61603	    };
61604	    /*\
61605	     * Paper.image
61606	     [ method ]
61607	     **
61608	     * Embeds an image into the surface.
61609	     **
61610	     > Parameters
61611	     **
61612	     - src (string) URI of the source image
61613	     - x (number) x coordinate position
61614	     - y (number) y coordinate position
61615	     - width (number) width of the image
61616	     - height (number) height of the image
61617	     = (object) Raphaël element object with type “image”
61618	     **
61619	     > Usage
61620	     | var c = paper.image("apple.png", 10, 10, 80, 80);
61621	    \*/
61622	    paperproto.image = function (src, x, y, w, h) {
61623	        var out = R._engine.image(this, src || "about:blank", x || 0, y || 0, w || 0, h || 0);
61624	        this.__set__ && this.__set__.push(out);
61625	        return out;
61626	    };
61627	    /*\
61628	     * Paper.text
61629	     [ method ]
61630	     **
61631	     * Draws a text string. If you need line breaks, put “\n” in the string.
61632	     **
61633	     > Parameters
61634	     **
61635	     - x (number) x coordinate position
61636	     - y (number) y coordinate position
61637	     - text (string) The text string to draw
61638	     = (object) Raphaël element object with type “text”
61639	     **
61640	     > Usage
61641	     | var t = paper.text(50, 50, "Raphaël\nkicks\nbutt!");
61642	    \*/
61643	    paperproto.text = function (x, y, text) {
61644	        var out = R._engine.text(this, x || 0, y || 0, Str(text));
61645	        this.__set__ && this.__set__.push(out);
61646	        return out;
61647	    };
61648	    /*\
61649	     * Paper.set
61650	     [ method ]
61651	     **
61652	     * Creates array-like object to keep and operate several elements at once.
61653	     * Warning: it doesn’t create any elements for itself in the page, it just groups existing elements.
61654	     * Sets act as pseudo elements — all methods available to an element can be used on a set.
61655	     = (object) array-like object that represents set of elements
61656	     **
61657	     > Usage
61658	     | var st = paper.set();
61659	     | st.push(
61660	     |     paper.circle(10, 10, 5),
61661	     |     paper.circle(30, 10, 5)
61662	     | );
61663	     | st.attr({fill: "red"}); // changes the fill of both circles
61664	    \*/
61665	    paperproto.set = function (itemsArray) {
61666	        !R.is(itemsArray, "array") && (itemsArray = Array.prototype.splice.call(arguments, 0, arguments.length));
61667	        var out = new Set(itemsArray);
61668	        this.__set__ && this.__set__.push(out);
61669	        out["paper"] = this;
61670	        out["type"] = "set";
61671	        return out;
61672	    };
61673	    /*\
61674	     * Paper.setStart
61675	     [ method ]
61676	     **
61677	     * Creates @Paper.set. All elements that will be created after calling this method and before calling
61678	     * @Paper.setFinish will be added to the set.
61679	     **
61680	     > Usage
61681	     | paper.setStart();
61682	     | paper.circle(10, 10, 5),
61683	     | paper.circle(30, 10, 5)
61684	     | var st = paper.setFinish();
61685	     | st.attr({fill: "red"}); // changes the fill of both circles
61686	    \*/
61687	    paperproto.setStart = function (set) {
61688	        this.__set__ = set || this.set();
61689	    };
61690	    /*\
61691	     * Paper.setFinish
61692	     [ method ]
61693	     **
61694	     * See @Paper.setStart. This method finishes catching and returns resulting set.
61695	     **
61696	     = (object) set
61697	    \*/
61698	    paperproto.setFinish = function (set) {
61699	        var out = this.__set__;
61700	        delete this.__set__;
61701	        return out;
61702	    };
61703	    /*\
61704	     * Paper.getSize
61705	     [ method ]
61706	     **
61707	     * Obtains current paper actual size.
61708	     **
61709	     = (object)
61710	     \*/
61711	    paperproto.getSize = function () {
61712	        var container = this.canvas.parentNode;
61713	        return {
61714	            width: container.offsetWidth,
61715	            height: container.offsetHeight
61716	                };
61717	        };
61718	    /*\
61719	     * Paper.setSize
61720	     [ method ]
61721	     **
61722	     * If you need to change dimensions of the canvas call this method
61723	     **
61724	     > Parameters
61725	     **
61726	     - width (number) new width of the canvas
61727	     - height (number) new height of the canvas
61728	    \*/
61729	    paperproto.setSize = function (width, height) {
61730	        return R._engine.setSize.call(this, width, height);
61731	    };
61732	    /*\
61733	     * Paper.setViewBox
61734	     [ method ]
61735	     **
61736	     * Sets the view box of the paper. Practically it gives you ability to zoom and pan whole paper surface by
61737	     * specifying new boundaries.
61738	     **
61739	     > Parameters
61740	     **
61741	     - x (number) new x position, default is `0`
61742	     - y (number) new y position, default is `0`
61743	     - w (number) new width of the canvas
61744	     - h (number) new height of the canvas
61745	     - fit (boolean) `true` if you want graphics to fit into new boundary box
61746	    \*/
61747	    paperproto.setViewBox = function (x, y, w, h, fit) {
61748	        return R._engine.setViewBox.call(this, x, y, w, h, fit);
61749	    };
61750	    /*\
61751	     * Paper.top
61752	     [ property ]
61753	     **
61754	     * Points to the topmost element on the paper
61755	    \*/
61756	    /*\
61757	     * Paper.bottom
61758	     [ property ]
61759	     **
61760	     * Points to the bottom element on the paper
61761	    \*/
61762	    paperproto.top = paperproto.bottom = null;
61763	    /*\
61764	     * Paper.raphael
61765	     [ property ]
61766	     **
61767	     * Points to the @Raphael object/function
61768	    \*/
61769	    paperproto.raphael = R;
61770	    var getOffset = function (elem) {
61771	        var box = elem.getBoundingClientRect(),
61772	            doc = elem.ownerDocument,
61773	            body = doc.body,
61774	            docElem = doc.documentElement,
61775	            clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
61776	            top  = box.top  + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop,
61777	            left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft;
61778	        return {
61779	            y: top,
61780	            x: left
61781	        };
61782	    };
61783	    /*\
61784	     * Paper.getElementByPoint
61785	     [ method ]
61786	     **
61787	     * Returns you topmost element under given point.
61788	     **
61789	     = (object) Raphaël element object
61790	     > Parameters
61791	     **
61792	     - x (number) x coordinate from the top left corner of the window
61793	     - y (number) y coordinate from the top left corner of the window
61794	     > Usage
61795	     | paper.getElementByPoint(mouseX, mouseY).attr({stroke: "#f00"});
61796	    \*/
61797	    paperproto.getElementByPoint = function (x, y) {
61798	        var paper = this,
61799	            svg = paper.canvas,
61800	            target = g.doc.elementFromPoint(x, y);
61801	        if (g.win.opera && target.tagName == "svg") {
61802	            var so = getOffset(svg),
61803	                sr = svg.createSVGRect();
61804	            sr.x = x - so.x;
61805	            sr.y = y - so.y;
61806	            sr.width = sr.height = 1;
61807	            var hits = svg.getIntersectionList(sr, null);
61808	            if (hits.length) {
61809	                target = hits[hits.length - 1];
61810	            }
61811	        }
61812	        if (!target) {
61813	            return null;
61814	        }
61815	        while (target.parentNode && target != svg.parentNode && !target.raphael) {
61816	            target = target.parentNode;
61817	        }
61818	        target == paper.canvas.parentNode && (target = svg);
61819	        target = target && target.raphael ? paper.getById(target.raphaelid) : null;
61820	        return target;
61821	    };
61822
61823	    /*\
61824	     * Paper.getElementsByBBox
61825	     [ method ]
61826	     **
61827	     * Returns set of elements that have an intersecting bounding box
61828	     **
61829	     > Parameters
61830	     **
61831	     - bbox (object) bbox to check with
61832	     = (object) @Set
61833	     \*/
61834	    paperproto.getElementsByBBox = function (bbox) {
61835	        var set = this.set();
61836	        this.forEach(function (el) {
61837	            if (R.isBBoxIntersect(el.getBBox(), bbox)) {
61838	                set.push(el);
61839	            }
61840	        });
61841	        return set;
61842	    };
61843
61844	    /*\
61845	     * Paper.getById
61846	     [ method ]
61847	     **
61848	     * Returns you element by its internal ID.
61849	     **
61850	     > Parameters
61851	     **
61852	     - id (number) id
61853	     = (object) Raphaël element object
61854	    \*/
61855	    paperproto.getById = function (id) {
61856	        var bot = this.bottom;
61857	        while (bot) {
61858	            if (bot.id == id) {
61859	                return bot;
61860	            }
61861	            bot = bot.next;
61862	        }
61863	        return null;
61864	    };
61865	    /*\
61866	     * Paper.forEach
61867	     [ method ]
61868	     **
61869	     * Executes given function for each element on the paper
61870	     *
61871	     * If callback function returns `false` it will stop loop running.
61872	     **
61873	     > Parameters
61874	     **
61875	     - callback (function) function to run
61876	     - thisArg (object) context object for the callback
61877	     = (object) Paper object
61878	     > Usage
61879	     | paper.forEach(function (el) {
61880	     |     el.attr({ stroke: "blue" });
61881	     | });
61882	    \*/
61883	    paperproto.forEach = function (callback, thisArg) {
61884	        var bot = this.bottom;
61885	        while (bot) {
61886	            if (callback.call(thisArg, bot) === false) {
61887	                return this;
61888	            }
61889	            bot = bot.next;
61890	        }
61891	        return this;
61892	    };
61893	    /*\
61894	     * Paper.getElementsByPoint
61895	     [ method ]
61896	     **
61897	     * Returns set of elements that have common point inside
61898	     **
61899	     > Parameters
61900	     **
61901	     - x (number) x coordinate of the point
61902	     - y (number) y coordinate of the point
61903	     = (object) @Set
61904	    \*/
61905	    paperproto.getElementsByPoint = function (x, y) {
61906	        var set = this.set();
61907	        this.forEach(function (el) {
61908	            if (el.isPointInside(x, y)) {
61909	                set.push(el);
61910	            }
61911	        });
61912	        return set;
61913	    };
61914	    function x_y() {
61915	        return this.x + S + this.y;
61916	    }
61917	    function x_y_w_h() {
61918	        return this.x + S + this.y + S + this.width + " \xd7 " + this.height;
61919	    }
61920	    /*\
61921	     * Element.isPointInside
61922	     [ method ]
61923	     **
61924	     * Determine if given point is inside this element’s shape
61925	     **
61926	     > Parameters
61927	     **
61928	     - x (number) x coordinate of the point
61929	     - y (number) y coordinate of the point
61930	     = (boolean) `true` if point inside the shape
61931	    \*/
61932	    elproto.isPointInside = function (x, y) {
61933	        var rp = this.realPath = getPath[this.type](this);
61934	        if (this.attr('transform') && this.attr('transform').length) {
61935	            rp = R.transformPath(rp, this.attr('transform'));
61936	        }
61937	        return R.isPointInsidePath(rp, x, y);
61938	    };
61939	    /*\
61940	     * Element.getBBox
61941	     [ method ]
61942	     **
61943	     * Return bounding box for a given element
61944	     **
61945	     > Parameters
61946	     **
61947	     - isWithoutTransform (boolean) flag, `true` if you want to have bounding box before transformations. Default is `false`.
61948	     = (object) Bounding box object:
61949	     o {
61950	     o     x: (number) top left corner x
61951	     o     y: (number) top left corner y
61952	     o     x2: (number) bottom right corner x
61953	     o     y2: (number) bottom right corner y
61954	     o     width: (number) width
61955	     o     height: (number) height
61956	     o }
61957	    \*/
61958	    elproto.getBBox = function (isWithoutTransform) {
61959	        if (this.removed) {
61960	            return {};
61961	        }
61962	        var _ = this._;
61963	        if (isWithoutTransform) {
61964	            if (_.dirty || !_.bboxwt) {
61965	                this.realPath = getPath[this.type](this);
61966	                _.bboxwt = pathDimensions(this.realPath);
61967	                _.bboxwt.toString = x_y_w_h;
61968	                _.dirty = 0;
61969	            }
61970	            return _.bboxwt;
61971	        }
61972	        if (_.dirty || _.dirtyT || !_.bbox) {
61973	            if (_.dirty || !this.realPath) {
61974	                _.bboxwt = 0;
61975	                this.realPath = getPath[this.type](this);
61976	            }
61977	            _.bbox = pathDimensions(mapPath(this.realPath, this.matrix
61977));
61978	            _.bbox.toString = x_y_w_h;
61979	            _.dirty = _.dirtyT = 0;
61980	        }
61981	        return _.bbox;
61982	    };
61983	    /*\
61984	     * Element.clone
61985	     [ method ]
61986	     **
61987	     = (object) clone of a given element
61988	     **
61989	    \*/
61990	    elproto.clone = function () {
61991	        if (this.removed) {
61992	            return null;
61993	        }
61994	        var out = this.paper[this.type]().attr(this.attr());
61995	        this.__set__ && this.__set__.push(out);
61996	        return out;
61997	    };
61998	    /*\
61999	     * Element.glow
62000	     [ method ]
62001	     **
62002	     * Return set of elements that create glow-like effect around given element. See @Paper.set.
62003	     *
62004	     * Note: Glow is not connected to the element. If you change element attributes it won’t adjust itself.
62005	     **
62006	     > Parameters
62007	     **
62008	     - glow (object) #optional parameters object with all properties optional:
62009	     o {
62010	     o     width (number) size of the glow, default is `10`
62011	     o     fill (boolean) will it be filled, default is `false`
62012	     o     opacity (number) opacity, default is `0.5`
62013	     o     offsetx (number) horizontal offset, default is `0`
62014	     o     offsety (number) vertical offset, default is `0`
62015	     o     color (string) glow colour, default is `black`
62016	     o }
62017	     = (object) @Paper.set of elements that represents glow
62018	    \*/
62019	    elproto.glow = function (glow) {
62020	        if (this.type == "text") {
62021	            return null;
62022	        }
62023	        glow = glow || {};
62024	        var s = {
62025	            width: (glow.width || 10) + (+this.attr("stroke-width") || 1),
62026	            fill: glow.fill || false,
62027	            opacity: glow.opacity == null ? .5 : glow.opacity,
62028	            offsetx: glow.offsetx || 0,
62029	            offsety: glow.offsety || 0,
62030	            color: glow.color || "#000"
62031	        },
62032	            c = s.width / 2,
62033	            r = this.paper,
62034	            out = r.set(),
62035	            path = this.realPath || getPath[this.type](this);
62036	        path = this.matrix ? mapPath(path, this.matrix) : path;
62037	        for (var i = 1; i < c + 1; i++) {
62038	            out.push(r.path(path).attr({
62039	                stroke: s.color,
62040	                fill: s.fill ? s.color : "none",
62041	                "stroke-linejoin": "round",
62042	                "stroke-linecap": "round",
62043	                "stroke-width": +(s.width / c * i).toFixed(3),
62044	                opacity: +(s.opacity / c).toFixed(3)
62045	            }));
62046	        }
62047	        return out.insertBefore(this).translate(s.offsetx, s.offsety);
62048	    };
62049	    var curveslengths = {},
62050	    getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) {
62051	        if (length == null) {
62052	            return bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y);
62053	        } else {
62054	            return R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, getTatLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length));
62055	        }
62056	    },
62057	    getLengthFactory = function (istotal, subpath) {
62058	        return function (path, length, onlystart) {
62059	            path = path2curve(path);
62060	            var x, y, p, l, sp = "", subpaths = {}, point,
62061	                len = 0;
62062	            for (var i = 0, ii = path.length; i < ii; i++) {
62063	                p = path[i];
62064	                if (p[0] == "M") {
62065	                    x = +p[1];
62066	                    y = +p[2];
62067	                } else {
62068	                    l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
62069	                    if (len + l > length) {
62070	                        if (subpath && !subpaths.start) {
62071	                            point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
62072	                            sp += ["C" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y];
62073	                            if (onlystart) {return sp;}
62074	                            subpaths.start = sp;
62075	                            sp = ["M" + point.x, point.y + "C" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join();
62076	                            len += l;
62077	                            x = +p[5];
62078	                            y = +p[6];
62079	                            continue;
62080	                        }
62081	                        if (!istotal && !subpath) {
62082	                            point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
62083	                            return {x: point.x, y: point.y, alph
62083a: point.alpha};
62084	                        }
62085	                    }
62086	                    len += l;
62087	                    x = +p[5];
62088	                    y = +p[6];
62089	                }
62090	                sp += p.shift() + p;
62091	            }
62092	            subpaths.end = sp;
62093	            point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);
62094	            point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha});
62095	            return point;
62096	        };
62097	    };
62098	    var getTotalLength = getLengthFactory(1),
62099	        getPointAtLength = getLengthFactory(),
62100	        getSubpathsAtLength = getLengthFactory(0, 1);
62101	    /*\
62102	     * Raphael.getTotalLength
62103	     [ method ]
62104	     **
62105	     * Returns length of the given path in pixels.
62106	     **
62107	     > Parameters
62108	     **
62109	     - path (string) SVG path string.
62110	     **
62111	     = (number) length.
62112	    \*/
62113	    R.getTotalLength = getTotalLength;
62114	    /*\
62115	     * Raphael.getPointAtLength
62116	     [ method ]
62117	     **
62118	     * Return coordinates of the point located at the given length on the given path.
62119	     **
62120	     > Parameters
62121	     **
62122	     - path (string) SVG path string
62123	     - length (number)
62124	     **
62125	     = (object) representation of the point:
62126	     o {
62127	     o     x: (number) x coordinate
62128	     o     y: (number) y coordinate
62129	     o     alpha: (number) angle of derivative
62130	     o }
62131	    \*/
62132	    R.getPointAtLength = getPointAtLength;
62133	    /*\
62134	     * Raphael.getSubpath
62135	     [ method ]
62136	     **
62137	     * Return subpath of a given path from given length to given length.
62138	     **
62139	     > Parameters
62140	     **
62141	     - path (string) SVG path string
62142	     - from (number) position of the start of the segment
62143	     - to (number) position of the end of the segment
62144	     **
62145	     = (string) pathstring for the segment
62146	    \*/
62147	    R.getSubpath = function (path, from, to) {
62148	        if (this.getTotalLength(path) - to < 1e-6) {
62149	            return getSubpathsAtLength(path, from).end;
62150	        }
62151	        var a = getSubpathsAtLength(path, to, 1);
62152	        return from ? getSubpathsAtLength(a, from).end : a;
62153	    };
62154	    /*\
62155	     * Element.getTotalLength
62156	     [ method ]
62157	     **
62158	     * Returns length of the path in pixels. Only works for element of “path” type.
62159	     = (number) length.
62160	    \*/
62161	    elproto.getTotalLength = function () {
62162	        var path = this.getPath();
62163	        if (!path) {
62164	            return;
62165	        }
62166
62167	        if (this.node.getTotalLength) {
62168	            return this.node.getTotalLength();
62169	        }
62170
62171	        return getTotalLength(path);
62172	    };
62173	    /*\
62174	     * Element.getPointAtLength
62175	     [ method ]
62176	     **
62177	     * Return coordinates of the point located at the given length on the given path. Only works for element of “path” type.
62178	     **
62179	     > Parameters
62180	     **
62181	     - length (number)
62182	     **
62183	     = (object) representation of the point:
62184	     o {
62185	     o     x: (number) x coordinate
62186	     o     y: (number) y coordinate
62187	     o     alpha: (number) angle of derivative
62188	     o }
62189	    \*/
62190	    elproto.getPointAtLength = function (length) {
62191	        var path = this.getPath();
62192	        if (!path) {
62193	            return;
62194	        }
62195
62196	        return getPointAtLength(path, length);
62197	    };
62198	    /*\
62199	     * Element.getPath
62200	     [ method ]
62201	     **
62202	     * Returns path of the element. Only works for elements of “path” type and simple elements like circle.
62203	     = (object) path
62204	     **
62205	    \*/
62206	    elproto.getPath = function () {
62207	        var path,
62208	            getPath = R._getPath[this.type];
62209
62210	        if (this.type == "text" || this.type == "set") {
62211	            return;
62212	        }
62213
62214	        if (getPath) {
62215	            path = getPath(this);
62216	        }
62217
62218	        return path;
62219	    };
62220	    /*\
62221	     * Element.getSubpath
62222	     [ method ]
62223	     **
62224	     * Return subpath of a given element from given length to given length. Only works for element of “path” type.
62225	     **
62226	     > Parameters
62227	     **
62228	     - from (number) position of the start of the segment
62229	     - to (number) position of the end of the segment
62230	     **
62231	     = (string) pathstring for the segment
62232	    \*/
62233	    elproto.getSubpath = function (from, to) {
62234	        var path = this.getPath();
62235	        if (!path) {
62236	            return;
62237	        }
62238
62239	        return R.getSubpath(path, from, to);
62240	    };
62241	    /*\
62242	     * Raphael.easing_formulas
62243	     [ property ]
62244	     **
62245	     * Object that contains easing formulas for animation. You could extend it with your own. By default it has following list of easing:
62246	     # <ul>
62247	     #     <li>“linear”</li>
62248	     #     <li>“&lt;” or “easeIn” or “ease-in”</li>
62249	     #     <li>“>” or “easeOut” or “ease-out”</li>
62250	     #     <li>“&lt;>” or “easeInOut” or “ease-in-out”</li>
62251	     #     <li>“backIn” or “back-in”</li>
62252	     #     <li>
62252“backOut” or “back-out”</li>
62253	     #     <li>“elastic”</li>
62254	     #     <li>“bounce”</li>
62255	     # </ul>
62256	     # <p>See also <a href="http://raphaeljs.com/easing.html">Easing demo</a>.</p>
62257	    \*/
62258	    var ef = R.easing_formulas = {
62259	        linear: function (n) {
62260	            return n;
62261	        },
62262	        "<": function (n) {
62263	            return pow(n, 1.7);
62264	        },
62265	        ">": function (n) {
62266	            return pow(n, .48);
62267	        },
62268	        "<>": function (n) {
62269	            var q = .48 - n / 1.04,
62270	                Q = math.sqrt(.1734 + q * q),
62271	                x = Q - q,
62272	                X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1),
62273	                y = -Q - q,
62274	                Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1),
62275	                t = X + Y + .5;
62276	            return (1 - t) * 3 * t * t + t * t * t;
62277	        },
62278	        backIn: function (n) {
62279	            var s = 1.70158;
62280	            return n * n * ((s + 1) * n - s);
62281	        },
62282	        backOut: function (n) {
62283	            n = n - 1;
62284	            var s = 1.70158;
62285	            return n * n * ((s + 1) * n + s) + 1;
62286	        },
62287	        elastic: function (n) {
62288	            if (n == !!n) {
62289	                return n;
62290	            }
62291	            return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1;
62292	        },
62293	        bounce: function (n) {
62294	            var s = 7.5625,
62295	                p = 2.75,
62296	                l;
62297	            if (n < (1 / p)) {
62298	                l = s * n * n;
62299	            } else {
62300	                if (n < (2 / p)) {
62301	                    n -= (1.5 / p);
62302	                    l = s * n * n + .75;
62303	                } else {
62304	                    if (n < (2.5 / p)) {
62305	                        n -= (2.25 / p);
62306	                        l = s * n * n + .9375;
62307	                    } else {
62308	                        n -= (2.625 / p);
62309	                        l = s * n * n + .984375;
62310	                    }
62311	                }
62312	            }
62313	            return l;
62314	        }
62315	    };
62316	    ef.easeIn = ef["ease-in"] = ef["<"];
62317	    ef.easeOut = ef["ease-out"] = ef[">"];
62318	    ef.easeInOut = ef["ease-in-out"] = ef["<>"];
62319	    ef["back-in"] = ef.backIn;
62320	    ef["back-out"] = ef.backOut;
62321
62322	    var animationElements = [],
62323	        requestAnimFrame = window.requestAnimationFrame       ||
62324	                           window.webkitRequestAnimationFrame ||
62325	                           window.mozRequestAnimationFrame    ||
62326	                           window.oRequestAnimationFrame      ||
62327	                           window.msRequestAnimationFrame     ||
62328	                           function (callback) {
62329	                               setTimeout(callback, 16);
62330	                           },
62331	        animation = function () {
62332	            var Now = +new Date,
62333	                l = 0;
62334	            for (; l < animationElements.length; l++) {
62335	                var e = animationElements[l];
62336	                if (e.el.removed || e.paused) {
62337	                    continue;
62338	                }
62339	                var time = Now - e.start,
62340	                    ms = e.ms,
62341	                    easing = e.easing,
62342	                    from = e.from,
62343	                    diff = e.diff,
62344	                    to = e.to,
62345	                    t = e.t,
62346	                    that = e.el,
62347	                    set = {},
62348	                    now,
62349	                    init = {},
62350	                    key;
62351	                if (e.initstatus) {
62352	                    time = (e.initstatus * e.anim.top - e.prev) / (e.percent - e.prev) * ms;
62353	                    e.status = e.initstatus;
62354	                    delete e.initstatus;
62355	                    e.stop && animationElements.splice(l--, 1);
62356	                } else {
62357	                    e.status = (e.prev + (e.percent - e.prev) * (time / ms)) / e.anim.top;
62358	                }
62359	                if (time < 0) {
62360	                    continue;
62361	                }
62362	                if (time < ms) {
62363	                    var pos = easing(time / ms);
62364	                    for (var attr in from) if (from[has](attr)) {
62365	                        switch (availableAnimAttrs[attr]) {
62366	                            case nu:
62367	                                now = +from[attr] + pos * ms * diff[attr];
62368	                                break;
62369	                            case "colour":
62370	                                now = "rgb(" + [
62371	                                    upto255(round(from[attr].r + pos * ms * diff[attr].r)),
62372	                                    upto255(round(from[attr].g + pos * ms * diff[attr].g)),
62373	                                    upto255(round(from[attr].b + pos * ms * diff[attr].b))
62374	                                ].join(",") + ")";
62375	                                break;
62376	                            case "path":
62377	                                now = [];
62378	                                for (var i = 0, ii = from[attr].length; i < ii; i++) {
62379	                                    now[i] = [from[attr][i][0]];
62380	                                    for (var j = 1, jj = from[attr][i].length; j < jj; j++) {
62381	                                        now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j];
62382	                                    }
62383	                                    now[i] = now[i].join(S);
62384	                                }
62385	                                now = now.join(S);
62386	                                break;
62387	                            case "transform":
62388	                                if (diff[attr].real) {
62389	                                    now = [];
62390	                                    for (i = 0, ii = from[attr].length; i < ii; i++) {
62391	                                        now[i] = [from[attr][i][0]];
62392	                                        for (j = 1, jj = from[attr][i].length; j < jj; j++) {
62393	                                            now[i][j] = from[attr][i][j] + pos * ms * diff[attr][i][j];
62394	                                        }
62395	                                    }
62396	                                } else {
62397	                                    var get = function (i) {
62398	                                        return +from[attr][i] + pos * ms * diff[attr][i];
62399	                                    };
62400	                                    // now = [["r", get(2), 0, 0], ["t", get(3), get(4)], ["s", get(0), get(1), 0, 0]];
62401	                                    now = [["m", get(0), get(1), get(2), get(3), get(4), get(5)]];
62402	                                }
62403	                                break;
62404	                            case "csv":
62405	                                if (attr == "clip-rect") {
62406	                                    now = [];
62407	                                    i = 4;
62408	                                    while (i--) {
62409	                                        now[i] = +from[attr][i] + pos * ms * diff[attr][i];
62410	                                    }
62411	                                }
62412	                                break;
62413	                            default:
62414	                                var from2 = [][concat](from[attr]);
62415	                                now = [];
62416	                                i = that.paper.customAttributes[attr].length;
62417	                                while (i--) {
62418	                                    now[i] = +from2[i] + pos * ms * diff[attr][i];
62419	                                }
62420	                                break;
62421	                        }
62422	                        set[attr] = now;
62423	                    }
62424	                    that.attr(set);
62425	                    (function (id, that, anim) {
62426	                        setTimeout(function () {
62427	                            eve("raphael.anim.frame." + id, that, anim);
62428	                        });
62429	                    })(that.id, that, e.anim);
62430	                } else {
62431	                    (function(f, el, a) {
62432	                        setTimeout(function() {
62433	                            eve("raphael.anim.frame." + el.id, el, a);
62434	                            eve("raphael.anim.finish." + el.id, el, a);
62435	                            R.is(f, "function") && f.call(el);
62436	                        });
62437	                    })(e.callback, that, e.anim);
62438	                    that.attr(to);
62439	                    animationElements.splice(l--, 1);
62440	                    if (e.repeat > 1 && !e.next) {
62441	                        for (key in to) if (to[has](key)) {
62442	                            init[key] = e.totalOrigin[key];
62443	                        }
62444	                        e.el.attr(init);
62445	                        runAnimation(e.anim, e.el, e.anim.percents[0], null, e.totalOrigin, e.repeat - 1);
62446	                    }
62447	                    if (e.next && !e.stop) {
62448	                        runAnimation(e.anim, e.el, e.next, null, e.totalOrigin, e.repeat);
62449	                    }
62450	                }
62451	            }
62452	            animationElements.length && requestAnimFrame(animation);
62453	        },
62454	        upto255 = function (color) {
62455	            return color > 255 ? 255 : color < 0 ? 0 : color;
62456	        };
62457	    /*\
62458	     * Element.animateWith
62459	     [ method ]
62460	     **
62461	     * Acts similar to @Element.animate, but ensure that given animation runs in sync with another given element.
62462	     **
62463	     > Parameters
62464	     **
62465	     - el (object) element to sync with
62466	     - anim (object) animation to sync with
62467	     - params (object) #optional final attributes for the element, see also @Element.attr
62468	     - ms (number) #optional number of milliseconds for animation to run
62469	     - easing (string) #optional easing type. Accept on of @Raphael.easing_formulas or CSS format: `cubic&#x2010;bezier(XX,&#160;XX,&#160;XX,&#160;XX)`
62470	     - callback (function) #optional callback function. Will be called at the end of animation.
62471	     * or
62472	     - element (object) element to sync with
62473	     - anim (object) animation to sync with
62474	     - animation (object) #optional animation object, see @Raphael.animation
62475	     **
62476	     = (object) original element
62477	    \*/
62478	    elproto.animateWith = function (el, anim, params, ms, easing, callback) {
62479	        var element = this;
62480	        if (element.removed) {
62481	            callback && callback.call(element);
62482	            return element;
62483	        }
62484	        var a = params instanceof Animation ? params : R.animation(params, ms, easing, callback),
62485	            x, y;
62486	        runAnimation(a, element, a.percents[0], null, element.attr());
62487	        for (var i = 0, ii = animationElements.length; i < ii; i++) {
62488	            if (animationElements[i].anim == anim && animationElements[i].el == el) {
62489	                animationElements[ii - 1].start = animationElements[i].start;
62490	                break;
62491	            }
62492	        }
62493	        return element;
62494	        //
62495	        //
62496	        // var a = params ? R.animation(params, ms, easing, callback) : anim,
62497	        //     status = element.status(anim);
62498	        // return this.animate(a).status(a, status * anim.ms / a.ms);
62499	    };
62500	    function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) {
62501	        var cx = 3 * p1x,
62502	            bx = 3 * (p2x - p1x) - cx,
62503	            ax = 1 - cx - bx,
62504	            cy = 3 * p1y,
62505	            by = 3 * (p2y - p1y) - cy,
62506	            ay = 1 - cy - by;
62507	        function sampleCurveX(t) {
62508	            return ((ax * t + bx) * t + cx) * t;
62509	        }
62510	        function solve(x, epsilon) {
62511	            var t = solveCurveX(x, epsilon);
62512	            return ((ay * t + by) * t + cy) * t;
62513	        }
62514	        function solveCurveX(x, epsilon) {
62515	            var t0, t1, t2, x2, d2, i;
62516	            for(t2 = x, i = 0; i < 8; i++) {
62517	                x2 = sampleCurveX(t2) - x;
62518	                if (abs(x2) < epsilon) {
62519	                    return t2;
62520	                }
62521	                d2 = (3 * ax * t2 + 2 * bx) * t2 + cx;
62522	                if (abs(d2) < 1e-6) {
62523	                    break;
62524	                }
62525	                t2 = t2 - x2 / d2;
62526	            }
62527	            t0 = 0;
62528	            t1 = 1;
62529	            t2 = x;
62530	            if (t2 < t0) {
62531	                return t0;
62532	            }
62533	            if (t2 > t1) {
62534	                return t1;
62535	            }
62536	            while (t0 < t1) {
62537	                x2 = sampleCurveX(t2);
62538	                if (abs(x2 - x) < epsilon) {
62539	                    return t2;
62540	                }
62541	                if (x > x2) {
62542	                    t0 = t2;
62543	                } else {
62544	                    t1 = t2;
62545	                }
62546	                t2 = (t1 - t0) / 2 + t0;
62547	            }
62548	            return t2;
62549	        }
62550	        return solve(t, 1 / (200 * duration));
62551	    }
62552	    elproto.onAnimation = function (f) {
62553	        f ? eve.on("raphael.anim.frame." + this.id, f) : eve.unbind("raphael.anim.frame." + this.id);
62554	        return this;
62555	    };
62556	    function Animation(anim, ms) {
62557	        var percents = [],
62558	            newAnim = {};
62559	        this.ms = ms;
62560	        this.times = 1;
62561	        if (anim) {
62562	            for (var attr in anim) if (anim[has](attr)) {
62563	                newAnim[toFloat(attr)] = anim[attr];
62564	                percents.push(toFloat(attr));
62565	            }
62566	            percents.sort(sortByNumber);
62567	        }
62568	        this.anim = newAnim;
62569	        this.top = percents[percents.length - 1];
62570	        this.percents = percents;
62571	    }
62572	    /*\
62573	     * Animation.delay
62574	     [ method ]
62575	     **
62576	     * Creates a copy of existing animation object with given delay.
62577	     **
62578	     > Parameters
62579	     **
62580	     - delay (number) number of ms to pass between animation start and actual animation
62581	     **
62582	     = (object) new altered Animation object
62583	     | var anim = Raphael.animation({cx: 10, cy: 20}, 2e3);
62584	     | circle1.animate(anim); // run the given animation immediately
62585	     | circle2.animate(anim.delay(500)); // run the given animation after 500 ms
62586	    \*/
62587	    Animation.prototype.delay = function (delay) {
62588	        var a = new Animation(this.anim, this.ms);
62589	        a.times = this.times;
62590	        a.del = +delay || 0;
62591	        return a;
62592	    };
62593	    /*\
62594	     * Animation.repeat
62595	     [ method ]
62596	     **
62597	     * Creates a copy of existing animation object with given repetition.
62598	     **
62599	     > Parameters
62600	     **
62601	     - repeat (number) number iterations of animation. For infinite animation pass `Infinity`
62602	     **
62603	     = (object) new altered Animation object
62604	    \*/
62605	    Animation.prototype.repeat = function (times) {
62606	        var a = new Animation(this.anim, this.ms);
62607	        a.del = this.del;
62608	        a.times = math.floor(mmax(times, 0)) || 1;
62609	        return a;
62610	    };
62611	    function runAnimation(anim, element, percent, status, totalOrigin, times) {
62612	        percent = toFloat(percent);
62613	        var params,
62614	            isInAnim,
62615	            isInAnimSet,
62616	            percents = [],
62617	            next,
62618	            prev,
62619	            timestamp,
62620	            ms = anim.ms,
62621	            from = {},
62622	            to = {},
62623	            diff = {};
62624	        if (status) {
62625	            for (i = 0, ii = animationElements.length; i < ii; i++) {
62626	                var e = animationElements[i];
62627	                if (e.el.id == element.id && e.anim == anim) {
62628	                    if (e.percent != percent) {
62629	                        animationElements.splice(i, 1);
62630	                        isInAnimSet = 1;
62631	                    } else {
62632	                        isInAnim = e;
62633	                    }
62634	                    element.attr(e.totalOrigin);
62635	                    break;
62636	                }
62637	            }
62638	        } else {
62639	            status = +to; // NaN
62640	        }
62641	        for (var i = 0, ii = anim.percents.length; i < ii; i++) {
62642	            if (anim.percents[i] == percent || anim.percents[i] > status * anim.top) {
62643	                percent = anim.percents[i];
62644	                prev = anim.percents[i - 1] || 0;
62645	                ms = ms / anim.top * (percent - prev);
62646	                next = anim.percents[i + 1];
62647	                params = anim.anim[percent];
62648	                break;
62649	            } else if (status) {
62650	                element.attr(anim.anim[anim.percents[i]]);
62651	            }
62652	        }
62653	        if (!params) {
62654	            return;
62655	        }
62656	        if (!isInAnim) {
62657	            for (var attr in params) if (params[has](attr)) {
62658	                if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) {
62659	                    from[attr] = element.attr(attr);
62660	                    (from[attr] == null) && (from[attr] = availableAttrs[attr]);
62661	                    to[attr] = params[attr];
62662	                    switch (availableAnimAttrs[attr]) {
62663	                        case nu:
62664	                            diff[attr] = (to[attr] - from[attr]) / ms;
62665	                            break;
62666	                        case "colour":
62667	                            from[attr] = R.getRGB(from[attr]);
62668	                            var toColour = R.getRGB(to[attr]);
62669	                            diff[attr] = {
62670	                                r: (toColour.r - from[attr].r) / ms,
62671	                                g: (toColour.g - from[attr].g) / ms,
62672	                                b: (toColour.b - from[attr].b) / ms
62673	                            };
62674	                            break;
62675	                        case "path":
62676	                            var pathes = path2curve(from[attr], to[attr]),
62677	                                toPath = pathes[1];
62678	                            from[attr] = pathes[0];
62679	                            diff[attr] = [];
62680	                            for (i = 0, ii = from[attr].length; i < ii; i++) {
62681	                                diff[attr][i] = [0];
62682	                                for (var j = 1, jj = from[attr][i].length; j < jj; j++) {
62683	                                    diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms;
62684	                                }
62685	                            }
62686	                            break;
62687	                        case "transform":
62688	                            var _ = element._,
62689	                                eq = equaliseTransform(_[attr], to[attr]);
62690	                            if (eq) {
62691	                                from[attr] = eq.from;
62692	                                to[attr] = eq.to;
62693	                                diff[attr] = [];
62694	                                diff[attr].real = true;
62695	                                for (i = 0, ii = from[attr].length; i < ii; i++) {
62696	                                    diff[attr][i] = [from[attr][i][0]];
62697	                                    for (j = 1, jj = from[attr][i].length; j < jj; j++) {
62698	                                        diff[attr][i][j] = (to[attr][i][j] - from[attr][i][j]) / ms;
62699	                                    }
62700	                                }
62701	                            } else {
62702	                                var m = (element.matrix || new Matrix),
62703	                                    to2 = {
62704	                                        _: {transform: _.transform},
62705	                                        getBBox: function () {
62706	                                            return element.getBBox(1);
62707	                                        }
62708	                                    };
62709	                                from[attr] = [
62710	                                    m.a,
62711	                                    m.b,
62712	                                    m.c,
62713	                                    m.d,
62714	                                    m.e,
62715	                                    m.f
62716	                                ];
62717	                                extractTransform(to2, to[attr]);
62718	                                to[attr] = to2._.transform;
62719	                                diff[attr] = [
62720	                                    (to2.matrix.a - m.a) / ms,
62721	                                    (to2.matrix.b - m.b) / ms,
62722	                                    (to2.matrix.c - m.c) / ms,
62723	                                    (to2.matrix.d - m.d) / ms,
62724	                                    (to2.matrix.e - m.e) / ms,
62725	                                    (to2.matrix.f - m.f) / ms
62726	                                ];
62727	                                // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy];
62728	                                // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }};
62729	                                // extractTransform(to2, to[attr]);
62730	                                // diff[attr] = [
62731	                                //     (to2._.sx - _.sx) / ms,
62732	                                //     (to2._.sy - _.sy) / ms,
62733	                                //     (to2._.deg - _.deg) / ms,
62734	                                //     (to2._.dx - _.dx) / ms,
62735	                                //     (to2._.dy - _.dy) / ms
62736	                                // ];
62737	                            }
62738	                            break;
62739	                        case "csv":
62740	                            var values = Str(params[attr])[split](separator),
62741	                                from2 = Str(from[attr])[split](separator);
62742	                            if (attr == "clip-rect") {
62743	                                from[attr] = from2;
62744	                                diff[attr] = [];
62745	                                i = from2.length;
62746	                                while (i--) {
62747	                                    diff[attr][i] = (values[i] - from[attr][i]) / ms;
62748	                                }
62749	                            }
62750	                            to[attr] = values;
62751	                            break;
62752	                        default:
62753	                            values = [][concat](params[attr]);
62754	                            from2 = [][concat](from[attr]);
62755	                            diff[attr] = [];
62756	                            i = element.paper.customAttributes[attr].length;
62757	                            while (i--) {
62758	                                diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms;
62759	                            }
62760	                            break;
62761	                    }
62762	                }
62763	            }
62764	            var easing = params.easing,
62765	                easyeasy = R.easing_formulas[easing];
62766	            if (!easyeasy) {
62767	                easyeasy = Str(easing).match(bezierrg);
62768	                if (easyeasy && easyeasy.length == 5) {
62769	                    var curve = easyeasy;
62770	                    easyeasy = function (t) {
62771	                        return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms);
62772	                    };
62773	                } else {
62774	                    easyeasy = pipe;
62775	                }
62776	            }
62777	            timestamp = params.start || anim.start || +new Date;
62778	            e = {
62779	                anim: anim,
62780	                percent: percent,
62781	                timestamp: timestamp,
62782	                start: timestamp + (anim.del || 0),
62783	                status: 0,
62784	                initstatus: status || 0,
62785	                stop: false,
62786	                ms: ms,
62787	                easing: easyeasy,
62788	                from: from,
62789	                diff: diff,
62790	                to: to,
62791	                el: element,
62792	                callback: params.callback,
62793	                prev: prev,
62794	                next: next,
62795	                repeat: times || anim.times,
62796	                origin: element.attr(),
62797	                totalOrigin: totalOrigin
62798	            };
62799	            animationElements.push(e);
62800	            if (status && !isInAnim && !isInAnimSet) {
62801	                e.stop = true;
62802	                e.start = new Date - ms * status;
62803	                if (animationElements.length == 1) {
62804	                    return animation();
62805	                }
62806	            }
62807	            if (isInAnimSet) {
62808	                e.start = new Date - e.ms * status;
62809	            }
62810	            animationElements.length == 1 && requestAnimFrame(animation);
62811	        } else {
62812	            isInAnim.initstatus = status;
62813	            isInAnim.start = new Date - isInAnim.ms * status;
62814	        }
62815	        eve("raphael.anim.start." + element.id, element, anim);
62816	    }
62817	    /*\
62818	     * Raphael.animation
62819	     [ method ]
62820	     **
62821	     * Creates an animation object that can be passed to the @Element.animate or @Element.animateWith methods.
62822	     * See also @Animation.delay and @Animation.repeat methods.
62823	     **
62824	     > Parameters
62825	     **
62826	     - params (object) final attributes for the element, see also @Element.attr
62827	     - ms (number) number of milliseconds for animation to run
62828	     - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic&#x2010;bezier(XX,&#160;XX,&#160;XX,&#160;XX)`
62829	     - callback (function) #optional callback function. Will be called at the end of animation.
62830	     **
62831	     = (object) @Animation
62832	    \*/
62833	    R.animation = function (params, ms, easing, callback) {
62834	        if (params instanceof Animation) {
62835	            return params;
62836	        }
62837	        if (R.is(easing, "function") || !easing) {
62838	            callback = callback || easing || null;
62839	            easing = null;
62840	        }
62841	        params = Object(params);
62842	        ms = +ms || 0;
62843	        var p = {},
62844	            json,
62845	            attr;
62846	        for (attr in params) if (params[has](attr) && toFloat(attr) != attr && toFloat
62846(attr) + "%" != attr) {
62847	            json = true;
62848	            p[attr] = params[attr];
62849	        }
62850	        if (!json) {
62851	            // if percent-like syntax is used and end-of-all animation callback used
62852	            if(callback){
62853	                // find the last one
62854	                var lastKey = 0;
62855	                for(var i in params){
62856	                    var percent = toInt(i);
62857	                    if(params[has](i) && percent > lastKey){
62858	                        lastKey = percent;
62859	                    }
62860	                }
62861	                lastKey += '%';
62862	                // if already defined callback in the last keyframe, skip
62863	                !params[lastKey].callback && (params[lastKey].callback = callback);
62864	            }
62865	          return new Animation(params, ms);
62866	        } else {
62867	            easing && (p.easing = easing);
62868	            callback && (p.callback = callback);
62869	            return new Animation({100: p}, ms);
62870	        }
62871	    };
62872	    /*\
62873	     * Element.animate
62874	     [ method ]
62875	     **
62876	     * Creates and starts animation for given element.
62877	     **
62878	     > Parameters
62879	     **
62880	     - params (object) final attributes for the element, see also @Element.attr
62881	     - ms (number) number of milliseconds for animation to run
62882	     - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic&#x2010;bezier(XX,&#160;XX,&#160;XX,&#160;XX)`
62883	     - callback (function) #optional callback function. Will be called at the end of animation.
62884	     * or
62885	     - animation (object) animation object, see @Raphael.animation
62886	     **
62887	     = (object) original element
62888	    \*/
62889	    elproto.animate = function (params, ms, easing, callback) {
62890	        var element = this;
62891	        if (element.removed) {
62892	            callback && callback.call(element);
62893	            return element;
62894	        }
62895	        var anim = params instanceof Animation ? params : R.animation(params, ms, easing, callback);
62896	        runAnimation(anim, element, anim.percents[0], null, element.attr());
62897	        return element;
62898	    };
62899	    /*\
62900	     * Element.setTime
62901	     [ method ]
62902	     **
62903	     * Sets the status of animation of the element in milliseconds. Similar to @Element.status method.
62904	     **
62905	     > Parameters
62906	     **
62907	     - anim (object) animation object
62908	     - value (number) number of milliseconds from the beginning of the animation
62909	     **
62910	     = (object) original element if `value` is specified
62911	     * Note, that during animation following events are triggered:
62912	     *
62913	     * On each animation frame event `anim.frame.<id>`, on start `anim.start.<id>` and on end `anim.finish.<id>`.
62914	    \*/
62915	    elproto.setTime = function (anim, value) {
62916	        if (anim && value != null) {
62917	            this.status(anim, mmin(value, anim.ms) / anim.ms);
62918	        }
62919	        return this;
62920	    };
62921	    /*\
62922	     * Element.status
62923	     [ method ]
62924	     **
62925	     * Gets or sets the status of animation of the element.
62926	     **
62927	     > Parameters
62928	     **
62929	     - anim (object) #optional animation object
62930	     - value (number) #optional 0 – 1. If specified, method works like a setter and sets the status of a given animation to the value. This will cause animation to jump to the given position.
62931	     **
62932	     = (number) status
62933	     * or
62934	     = (array) status if `anim` is not specified. Array of objects in format:
62935	     o {
62936	     o     anim: (object) animation object
62937	     o     status: (number) status
62938	     o }
62939	     * or
62940	     = (object) original element if `value` is specified
62941	    \*/
62942	    elproto.status = function (anim, value) {
62943	        var out = [],
62944	            i = 0,
62945	            len,
62946	            e;
62947	        if (value != null) {
62948	            runAnimation(anim, this, -1, mmin(value, 1));
62949	            return this;
62950	        } else {
62951	            len = animationElements.length;
62952	            for (; i < len; i++) {
62953	                e = animationElements[i];
62954	                if (e.el.id == this.id && (!anim || e.anim == anim)) {
62955	                    if (anim) {
62956	                        return e.status;
62957	                    }
62958	                    out.push({
62959	                        anim: e.anim,
62960	                        status: e.status
62961	                    });
62962	                }
62963	            }
62964	            if (anim) {
62965	                return 0;
62966	            }
62967	            return out;
62968	        }
62969	    };
62970	    /*\
62971	     * Element.pause
62972	     [ method ]
62973	     **
62974	     * Stops animation of the element with ability to resume it later on.
62975	     **
62976	     > Parameters
62977	     **
62978	     - anim (object) #optional animation object
62979	     **
62980	     = (object) original element
62981	    \*/
62982	    elproto.pause = function (anim) {
62983	        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {
62984	            if (eve("raphael.anim.pause." + this.id, this, animationElements[i].anim) !== false) {
62985	                animationElements[i].paused = true;
62986	            }
62987	        }
62988	        return this;
62989	    };
62990	    /*\
62991	     * Element.resume
62992	     [ method ]
62993	     **
62994	     * Resumes animation if it was paused with @Element.pause method.
62995	     **
62996	     > Parameters
62997	     **
62998	     - anim (object) #optional animation object
62999	     **
63000	     = (object) original element
63001	    \*/
63002	    elproto.resume = function (anim) {
63003	        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {
63004	            var e = animationElements[i];
63005	            if (eve("raphael.anim.resume." + this.id, this, e.anim) !== false) {
63006	                delete e.paused;
63007	                this.status(e.anim, e.status);
63008	            }
63009	        }
63010	        return this;
63011	    };
63012	    /*\
63013	     * Element.stop
63014	     [ method ]
63015	     **
63016	     * Stops animation of the element.
63017	     **
63018	     > Parameters
63019	     **
63020	     - anim (object) #optional animation object
63021	     **
63022	     = (object) original element
63023	    \*/
63024	    elproto.stop = function (anim) {
63025	        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {
63026	            if (eve("raphael.anim.stop." + this.id, this, animationElements[i].anim) !== false) {
63027	                animationElements.splice(i--, 1);
63028	            }
63029	        }
63030	        return this;
63031	    };
63032	    function stopAnimation(paper) {
63033	        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.paper == paper) {
63034	            animationElements.splice(i--, 1);
63035	        }
63036	    }
63037	    eve.on("raphael.remove", stopAnimation);
63038	    eve.on("raphael.clear", stopAnimation);
63039	    elproto.toString = function () {
63040	        return "Rapha\xebl\u2019s object";
63041	    };
63042
63043	    // Set
63044	    var Set = function (items) {
63045	        this.items = [];
63046	        this.length = 0;
63047	        this.type = "set";
63048	        if (items) {
63049	            for (var i = 0, ii = items.length; i < ii; i++) {
63050	                if (items[i] && (items[i].constructor == elproto.constructor || items[i].constructor == Set)) {
63051	                    this[this.items.length] = this.items[this.items.length] = items[i];
63052	                    this.length++;
63053	                }
63054	            }
63055	        }
63056	    },
63057	    setproto = Set.prototype;
63058	    /*\
63059	     * Set.push
63060	     [ method ]
63061	     **
63062	     * Adds each argument to the current set.
63063	     = (object) original element
63064	    \*/
63065	    setproto.push = function () {
63066	        var item,
63067	            len;
63068	        for (var i = 0, ii = arguments.length; i < ii; i++) {
63069	            item = arguments[i];
63070	            if (item && (item.constructor == elproto.constructor || item.constructor == Set)) {
63071	                len = this.items.length;
63072	                this[len] = this.items[len] = item;
63073	                this.length++;
63074	            }
63075	        }
63076	        return this;
63077	    };
63078	    /*\
63079	     * Set.pop
63080	     [ method ]
63081	     **
63082	     * Removes last element and returns it.
63083	     = (object) element
63084	    \*/
63085	    setproto.pop = function () {
63086	        this.length && delete this[this.length--];
63087	        return this.items.pop();
63088	    };
63089	    /*\
63090	     * Set.forEach
63091	     [ method ]
63092	     **
63093	     * Executes given function for each element in the set.
63094	     *
63095	     * If function returns `false` it will stop loop running.
63096	     **
63097	     > Parameters
63098	     **
63099	     - callback (function) function to run
63100	     - thisArg (object) context object for the callback
63101	     = (object) Set object
63102	    \*/
63103	    setproto.forEach = function (callback, thisArg) {
63104	        for (var i = 0, ii = this.items.length; i < ii; i++) {
63105	            if (callback.call(thisArg, this.items[i], i) === false) {
63106	                return this;
63107	            }
63108	        }
63109	        return this;
63110	    };
63111	    for (var method in elproto) if (elproto[has](method)) {
63112	        setproto[method] = (function (methodname) {
63113	            return function () {
63114	                var arg = arguments;
63115	                return this.forEach(function (el) {
63116	                    el[methodname][apply](el, arg);
63117	                });
63118	            };
63119	        })(method);
63120	    }
63121	    setproto.attr = function (name, value) {
63122	        if (name && R.is(name, array) && R.is(name[0], "object")) {
63123	            for (var j = 0, jj = name.length; j < jj; j++) {
63124	                this.items[j].attr(name[j]);
63125	            }
63126	        } else {
63127	            for (var i = 0, ii = this.items.length; i < ii; i++) {
63128	                this.items[i].attr(name, value);
63129	            }
63130	        }
63131	        return this;
63132	    };
63133	    /*\
63134	     * Set.clear
63135	     [ method ]
63136	     **
63137	     * Removes all elements from the set
63138	    \*/
63139	    setproto.clear = function () {
63140	        while (this.length) {
63141	            this.pop();
63142	        }
63143	    };
63144	    /*\
63145	     * Set.splice
63146	     [ method ]
63147	     **
63148	     * Removes given element from the set
63149	     **
63150	     > Parameters
63151	     **
63152	     - index (number) position of the deletion
63153	     - count (number) number of element to remove
63154	     - insertion… (object) #optional elements to insert
63155	     = (object) set elements that were deleted
63156	    \*/
63157	    setproto.splice = function (index, count, insertion) {
63158	        index = index < 0 ? mmax(this.length + index, 0) : index;
63159	        count = mmax(0, mmin(this.length - index, count));
63160	        var tail = [],
63161	            todel = [],
63162	            args = [],
63163	            i;
63164	        for (i = 2; i < arguments.length; i++) {
63165	            args.push(arguments[i]);
63166	        }
63167	        for (i = 0; i < count; i++) {
63168	            todel.push(this[index + i]);
63169	        }
63170	        for (; i < this.length - index; i++) {
63171	            tail.push(this[index + i]);
63172	        }
63173	        var arglen = args.length;
63174	        for (i = 0; i < arglen + tail.length; i++) {
63175	            this.items[index + i] = this[index + i] = i < arglen ? args[i] : tail[i - arglen];
63176	        }
63177	        i = this.items.length = this.length -= count - arglen;
63178	        while (this[i]) {
63179	            delete this[i++];
63180	        }
63181	        return new Set(todel);
63182	    };
63183	    /*\
63184	     * Set.exclude
63185	     [ method ]
63186	     **
63187	     * Removes given element from the set
63188	     **
63189	     > Parameters
63190	     **
63191	     - element (object) element to remove
63192	     = (boolean) `true` if object was found & removed from the set
63193	    \*/
63194	    setproto.exclude = function (el) {
63195	        for (var i = 0, ii = this.length; i < ii; i++) if (this[i] == el) {
63196	            this.splice(i, 1);
63197	            return true;
63198	        }
63199	    };
63200	    setproto.animate = function (params, ms, easing, callback) {
63201	        (R.is(easing, "function") || !easing) && (callback = easing || null);
63202	        var len = this.items.length,
63203	            i = len,
63204	            item,
63205	            set = this,
63206	            collector;
63207	        if (!len) {
63208	            return this;
63209	        }
63210	        callback && (collector = function () {
63211	            !--len && callback.call(set);
63212	        });
63213	        easing = R.is(easing, string) ? easing : collector;
63214	        var anim = R.animation(params, ms, easing, collector);
63215	        item = this.items[--i].animate(anim);
63216	        while (i--) {
63217	            this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, anim, anim);
63218	            (this.items[i] && !this.items[i].removed) || len--;
63219	        }
63220	        return this;
63221	    };
63222	    setproto.insertAfter = function (el) {
63223	        var i = this.items.length;
63224	        while (i--) {
63225	            this.items[i].insertAfter(el);
63226	        }
63227	        return this;
63228	    };
63229	    setproto.getBBox = function () {
63230	        var x = [],
63231	            y = [],
63232	            x2 = [],
63233	            y2 = [];
63234	        for (var i = this.items.length; i--;) if (!this.items[i].removed) {
63235	            var box = this.items[i].getBBox();
63236	            x.push(box.x);
63237	            y.push(box.y);
63238	            x2.push(box.x + box.width);
63239	            y2.push(box.y + box.height);
63240	        }
63241	        x = mmin[apply](0, x);
63242	        y = mmin[apply](0, y);
63243	        x2 = mmax[apply](0, x2);
63244	        y2 = mmax[apply](0, y2);
63245	        return {
63246	            x: x,
63247	            y: y,
63248	            x2: x2,
63249	            y2: y2,
63250	            width: x2 - x,
63251	            height: y2 - y
63252	        };
63253	    };
63254	    setproto.clone = function (s) {
63255	        s = this.paper.set();
63256	        for (var i = 0, ii = this.items.length; i < ii; i++) {
63257	            s.push(this.items[i].clone());
63258	        }
63259	        return s;
63260	    };
63261	    setproto.toString = function () {
63262	        return "Rapha\xebl\u2018s set";
63263	    };
63264
63265	    setproto.glow = function(glowConfig) {
63266	        var ret = this.paper.set();
63267	        this.forEach(function(shape, index){
63268	            var g = shape.glow(glowConfig);
63269	            if(g != null){
63270	                g.forEach(function(shape2, index2){
63271	                    ret.push(shape2);
63272	                });
63273	            }
63274	        });
63275	        return ret;
63276	    };
63277
63278
63279	    /*\
63280	     * Set.isPointInside
63281	     [ method ]
63282	     **
63283	     * Determine if given point is inside this set’s elements
63284	     **
63285	     > Parameters
63286	     **
63287	     - x (number) x coordinate of the point
63288	     - y (number) y coordinate of the point
63289	     = (boolean) `true` if point is inside any of the set's elements
63290	     \*/
63291	    setproto.isPointInside = function (x, y) {
63292	        var isPointInside = false;
63293	        this.forEach(function (el) {
63294	            if (el.isPointInside(x, y)) {
63295	                isPointInside = true;
63296	                return false; // stop loop
63297	            }
63298	        });
63299	        return isPointInside;
63300	    };
63301
63302	    /*\
63303	     * Raphael.registerFont
63304	     [ method ]
63305	     **
63306	     * Adds given font to the registered set of fonts for Raphaël. Should be used as an internal call from within Cufón’s font file.
63307	     * Returns original parameter, so it could be used with chaining.
63308	     # <a href="http://wiki.github.com/sorccu/cufon/about">More about Cufón and how to convert your font form TTF, OTF, etc to JavaScript file.</a>
63309	     **
63310	     > Parameters
63311	     **
63312	     - font (object) the font to register
63313	     = (object) the font you passed in
63314	     > Usage
63315	     | Cufon.registerFont(Raphael.registerFont({…}));
63316	    \*/
63317	    R.registerFont = function (font) {
63318	        if (!font.face) {
63319	            return font;
63320	        }
63321	        this.fonts = this.fonts || {};
63322	        var fontcopy = {
63323	                w: font.w,
63324	                face: {},
63325	                glyphs: {}
63326	            },
63327	            family = font.face["font-family"];
63328	        for (var prop in font.face) if (font.face[has](prop)) {
63329	            fontcopy.face[prop] = font.face[prop];
63330	        }
63331	        if (this.fonts[family]) {
63332	            this.fonts[family].push(fontcopy);
63333	        } else {
63334	            this.fonts[family] = [fontcopy];
63335	        }
63336	        if (!font.svg) {
63337	            fontcopy.face["units-per-em"] = toInt(font.face["units-per-em"], 10);
63338	            for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) {
63339	                var path = font.glyphs[glyph];
63340	                fontcopy.glyphs[glyph] = {
63341	                    w: path.w,
63342	                    k: {},
63343	                    d: path.d && "M" + path.d.replace(/[mlcxtrv]/g, function (command) {
63344	                            return {l: "L", c: "C", x: "z", t: "m", r: "l", v: "c"}[command] || "M";
63345	                        }) + "z"
63346	                };
63347	                if (path.k) {
63348	                    for (var k in path.k) if (path[has](k)) {
63349	                        fontcopy.glyphs[glyph].k[k] = path.k[k];
63350	                    }
63351	                }
63352	            }
63353	        }
63354	        return font;
63355	    };
63356	    /*\
63357	     * Paper.getFont
63358	     [ method ]
63359	     **
63360	     * Finds font object in the registered fonts by given parameters. You could specify only one word from the font name, like “Myriad” for “Myriad Pro”.
63361	     **
63362	     > Parameters
63363	     **
63364	     - family (string) font family name or any word from it
63365	     - weight (string) #optional font weight
63366	     - style (string) #optional font style
63367	     - stretch (string) #optional font stretch
63368	     = (object) the font object
63369	     > Usage
63370	     | paper.print(100, 100, "Test string", paper.getFont("Times", 800), 30);
63371	    \*/
63372	    paperproto.getFont = function (family, weight, style, stretch) {
63373	        stretch = stretch || "normal";
63374	        style = style || "normal";
63375	        weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400;
63376	        if (!R.fonts) {
63377	            return;
63378	        }
63379	        var font = R.fonts[family];
63380	        if (!font) {
63381	            var name = new RegExp("(^|\\s)" + family.replace(/[^\w\d\s+!~.:_-]/g, E) + "(\\s|$)", "i");
63382	            for (var fontName in R.fonts) if (R.fonts[has](fontName)) {
63383	                if (name.test(fontName)) {
63384	                    font = R.fonts[fontName];
63385	                    break;
63386	                }
63387	            }
63388	        }
63389	        var thefont;
63390	        if (font) {
63391	            for (var i = 0, ii = font.length; i < ii; i++) {
63392	                thefont = font[i];
63393	                if (thefont.face["font-weight"] == weight && (thefont.face["font-style"] == style || !thefont.face["font-style"]) && thefont.face["font-stretch"] == stretch) {
63394	                    break;
63395	                }
63396	            }
63397	        }
63398	        return thefont;
63399	    };
63400	    /*\
63401	     * Paper.print
63402	     [ method ]
63403	     **
63404	     * Creates path that represent given text written using given font at given position with given size.
63405	     * Result of the method is path element that contains whole text as a separate path.
63406	     **
63407	     > Parameters
63408	     **
63409	     - x (number) x position of the text
63410	     - y (number) y position of the text
63411	     - string (string) text to print
63412	     - font (object) font object, see @Paper.getFont
63413	     - size (number) #optional size of the font, default is `16`
63414	     - origin (string) #optional could be `"baseline"` or `"middle"`, default is `"middle"`
63415	     - letter_spacing (number) #optional number in range `-1..1`, default is `0`
63416	     - line_spacing (number) #optional number in range `1..3`, default is `1`
63417	     = (object) resulting path element, which consist of all letters
63418	     > Usage
63419	     | var txt = r.print(10, 50, "print", r.getFont("Museo"), 30).attr({fill: "#fff"});
63420	    \*/
63421	    paperproto.print = function (x, y, string, font, size, origin, letter_spacing, line_spacing) {
63422	        origin = origin || "middle"; // baseline|middle
63423	        letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1);
63424	        line_spacing = mmax(mmin(line_spacing || 1, 3), 1);
63425	        var letters = Str(string)[split](E),
63426	            shift = 0,
63427	            notfirst = 0,
63428	            path = E,
63429	            scale;
63430	        R.is(font, "string") && (font = this.getFont(font));
63431	        if (font) {
63432	            scale = (size || 16) / font.face["units-per-em"];
63433	            var bb = font.face.bbox[split](separator),
63434	                top = +bb[0],
63435	                lineHeight = bb[3] - bb[1],
63436	                shifty = 0,
63437	                height = +bb[1] + (origin == "baseline" ? lineHeight + (+font.face.descent) : lineHeight / 2);
63438	            for (var i = 0, ii = letters.length; i < ii; i++) {
63439	                if (letters[i] == "\n") {
63440	                    shift = 0;
63441	                    curr = 0;
63442	                    notfirst = 0;
63443	                    shifty += lineHeight * line_spacing;
63444	                } else {
63445	                    var prev = notfirst && font.glyphs[letters[i - 1]] || {},
63446	                        curr = font.glyphs[letters[i]];
63447	                    shift += notfirst ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0;
63448	                    notfirst = 1;
63449	                }
63450	                if (curr && curr.d) {
63451	                    path += R.transformPath(curr.d, ["t", shift * scale, shifty * scale, "s", scale, scale, top, height, "t", (x - top) / scale, (y - height) / scale]);
63452	                }
63453	            }
63454	        }
63455	        return this.path(path).attr({
63456	            fill: "#000",
63457	            stroke: "none"
63458	        });
63459	    };
63460
63461	    /*\
63462	     * Paper.add
63463	     [ method ]
63464	     **
63465	     * Imports elements in JSON array in format `{type: type, <attributes>}`
63466	     **
63467	     > Parameters
63468	     **
63469	     - json (array)
63470	     = (object) resulting set of imported elements
63471	     > Usage
63472	     | paper.add([
63473	     |     {
63474	     |         type: "circle",
63475	     |         cx: 10,
63476	     |         cy: 10,
63477	     |         r: 5
63478	     |     },
63479	     |     {
63480	     |         type: "rect",
63481	     |         x: 10,
63482	     |         y: 10,
63483	     |         width: 10,
63484	     |         height: 10,
63485	     |         fill: "#fc0"
63486	     |     }
63487	     | ]);
63488	    \*/
63489	    paperproto.add = function (json) {
63490	        if (R.is(json, "array")) {
63491	            var res = this.set(),
63492	                i = 0,
63493	                ii = json.length,
63494	                j;
63495	            for (; i < ii; i++) {
63496	                j = json[i] || {};
63497	                elements[has](j.type) && res.push(this[j.type]().attr(j));
63498	            }
63499	        }
63500	        return res;
63501	    };
63502
63503	    /*\
63504	     * Raphael.format
63505	     [ method ]
63506	     **
63507	     * Simple format function. Replaces construction of type “`{<number>}`” to the corresponding argument.
63508	     **
63509	     > Parameters
63510	     **
63511	     - token (string) string to format
63512	     - … (string) rest of arguments will be treated as parameters for replacement
63513	     = (string) formated string
63514	     > Usage
63515	     | var x = 10,
63516	     |     y = 20,
63517	     |     width = 40,
63518	     |     height = 50;
63519	     | // this will draw a rectangular shape equivalent to "M10,20h40v50h-40z"
63520	     | paper.path(Raphael.format("M{0},{1}h{2}v{3}h{4}z", x, y, width, height, -width));
63521	    \*/
63522	    R.format = function (token, params) {
63523	        var args = R.is(params, array) ? [0][concat](params) : arguments;
63524	        token && R.is(token, string) && args.length - 1 && (token = token.replace(formatrg, function (str, i) {
63525	            return args[++i] == null ? E : args[i];
63526	        }));
63527	        return token || E;
63528	    };
63529	    /*\
63530	     * Raphael.fullfill
63531	     [ method ]
63532	     **
63533	     * A little bit more advanced format function than @Raphael.format. Replaces construction of type “`{<name>}
63533`” to the corresponding argument.
63534	     **
63535	     > Parameters
63536	     **
63537	     - token (string) string to format
63538	     - json (object) object which properties will be used as a replacement
63539	     = (string) formated string
63540	     > Usage
63541	     | // this will draw a rectangular shape equivalent to "M10,20h40v50h-40z"
63542	     | paper.path(Raphael.fullfill("M{x},{y}h{dim.width}v{dim.height}h{dim['negative width']}z", {
63543	     |     x: 10,
63544	     |     y: 20,
63545	     |     dim: {
63546	     |         width: 40,
63547	     |         height: 50,
63548	     |         "negative width": -40
63549	     |     }
63550	     | }));
63551	    \*/
63552	    R.fullfill = (function () {
63553	        var tokenRegex = /\{([^\}]+)\}/g,
63554	            objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g, // matches .xxxxx or ["xxxxx"] to run over object properties
63555	            replacer = function (all, key, obj) {
63556	                var res = obj;
63557	                key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) {
63558	                    name = name || quotedName;
63559	                    if (res) {
63560	                        if (name in res) {
63561	                            res = res[name];
63562	                        }
63563	                        typeof res == "function" && isFunc && (res = res());
63564	                    }
63565	                });
63566	                res = (res == null || res == obj ? all : res) + "";
63567	                return res;
63568	            };
63569	        return function (str, obj) {
63570	            return String(str).replace(tokenRegex, function (all, key) {
63571	                return replacer(all, key, obj);
63572	            });
63573	        };
63574	    })();
63575	    /*\
63576	     * Raphael.ninja
63577	     [ method ]
63578	     **
63579	     * If you want to leave no trace of Raphaël (Well, Raphaël creates only one global variable `Raphael`, but anyway.) You can use `ninja` method.
63580	     * Beware, that in this case plugins could stop working, because they are depending on global variable existence.
63581	     **
63582	     = (object) Raphael object
63583	     > Usage
63584	     | (function (local_raphael) {
63585	     |     var paper = local_raphael(10, 10, 320, 200);
63586	     |     …
63587	     | })(Raphael.ninja());
63588	    \*/
63589	    R.ninja = function () {
63590	        if (oldRaphael.was) {
63591	            g.win.Raphael = oldRaphael.is;
63592	        } else {
63593	            // IE8 raises an error when deleting window property
63594	            window.Raphael = undefined;
63595	            try {
63596	                delete window.Raphael;
63597	            } catch(e) {}
63598	        }
63599	        return R;
63600	    };
63601	    /*\
63602	     * Raphael.st
63603	     [ property (object) ]
63604	     **
63605	     * You can add your own method to elements and sets. It is wise to add a set method for each element method
63606	     * you added, so you will be able to call the same method on sets too.
63607	     **
63608	     * See also @Raphael.el.
63609	     > Usage
63610	     | Raphael.el.red = function () {
63611	     |     this.attr({fill: "#f00"});
63612	     | };
63613	     | Raphael.st.red = function () {
63614	     |     this.forEach(function (el) {
63615	     |         el.red();
63616	     |     });
63617	     | };
63618	     | // then use it
63619	     | paper.set(paper.circle(100, 100, 20), paper.circle(110, 100, 20)).red();
63620	    \*/
63621	    R.st = setproto;
63622
63623	    eve.on("raphael.DOMload", function () {
63624	        loaded = true;
63625	    });
63626
63627	    // Firefox <3.6 fix: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html
63628	    (function (doc, loaded, f) {
63629	        if (doc.readyState == null && doc.addEventListener){
63630	            doc.addEventListener(loaded, f = function () {
63631	                doc.removeEventListener(loaded, f, false);
63632	                doc.readyState = "complete";
63633	            }, false);
63634	            doc.readyState = "loading";
63635	        }
63636	        function isLoaded() {
63637	            (/in/).test(doc.readyState) ? setTimeout(isLoaded, 9) : R.eve("raphael.DOMload");
63638	        }
63639	        isLoaded();
63640	    })(document, "DOMContentLoaded");
63641
63642	    return R;
63643	}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
63644
63645
63646/***/ },
63647/* 2 */
63648/***/ function(module, exports, __webpack_require__) {
63649
63650	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
63651	// 
63652	// Licensed under the Apache License, Version 2.0 (the "License");
vendor: 14,957 bytes, lines 63653-64069
63653	// you may not use this file except in compliance with the License.
63654	// You may obtain a copy of the License at
63655	// 
63656	// http://www.apache.org/licenses/LICENSE-2.0
63657	// 
63658	// Unless required by applicable law or agreed to in writing, software
63659	// distributed under the License is distributed on an "AS IS" BASIS,
63660	// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
63661	// See the License for the specific language governing permissions and
63662	// limitations under the License.
63663	// ┌────────────────────────────────────────────────────────────┐ \\
63664	// │ Eve 0.5.0 - JavaScript Events Library                      │ \\
63665	// ├────────────────────────────────────────────────────────────┤ \\
63666	// │ Author Dmitry Baranovskiy (http://dmitry.baranovskiy.com/) │ \\
63667	// └────────────────────────────────────────────────────────────┘ \\
63668
63669	(function (glob) {
63670	    var version = "0.5.0",
63671	        has = "hasOwnProperty",
63672	        separator = /[\.\/]/,
63673	        comaseparator = /\s*,\s*/,
63674	        wildcard = "*",
63675	        fun = function () {},
63676	        numsort = function (a, b) {
63677	            return a - b;
63678	        },
63679	        current_event,
63680	        stop,
63681	        events = {n: {}},
63682	        firstDefined = function () {
63683	            for (var i = 0, ii = this.length; i < ii; i++) {
63684	                if (typeof this[i] != "undefined") {
63685	                    return this[i];
63686	                }
63687	            }
63688	        },
63689	        lastDefined = function () {
63690	            var i = this.length;
63691	            while (--i) {
63692	                if (typeof this[i] != "undefined") {
63693	                    return this[i];
63694	                }
63695	            }
63696	        },
63697	        objtos = Object.prototype.toString,
63698	        Str = String,
63699	        isArray = Array.isArray || function (ar) {
63700	            return ar instanceof Array || objtos.call(ar) == "[object Array]";
63701	        };
63702	    /*\
63703	     * eve
63704	     [ method ]
63705
63706	     * Fires event with given `name`, given scope and other parameters.
63707
63708	     > Arguments
63709
63710	     - name (string) name of the *event*, dot (`.`) or slash (`/`) separated
63711	     - scope (object) context for the event handlers
63712	     - varargs (...) the rest of arguments will be sent to event handlers
63713
63714	     = (object) array of returned values from the listeners. Array has two methods `.firstDefined()` and `.lastDefined()` to get first or last not `undefined` value.
63715	    \*/
63716	        eve = function (name, scope) {
63717	            var e = events,
63718	                oldstop = stop,
63719	                args = Array.prototype.slice.call(arguments, 2),
63720	                listeners = eve.listeners(name),
63721	                z = 0,
63722	                f = false,
63723	                l,
63724	                indexed = [],
63725	                queue = {},
63726	                out = [],
63727	                ce = current_event,
63728	                errors = [];
63729	            out.firstDefined = firstDefined;
63730	            out.lastDefined = lastDefined;
63731	            current_event = name;
63732	            stop = 0;
63733	            for (var i = 0, ii = listeners.length; i < ii; i++) if ("zIndex" in listeners[i]) {
63734	                indexed.push(listeners[i].zIndex);
63735	                if (listeners[i].zIndex < 0) {
63736	                    queue[listeners[i].zIndex] = listeners[i];
63737	                }
63738	            }
63739	            indexed.sort(numsort);
63740	            while (indexed[z] < 0) {
63741	                l = queue[indexed[z++]];
63742	                out.push(l.apply(scope, args));
63743	                if (stop) {
63744	                    stop = oldstop;
63745	                    return out;
63746	                }
63747	            }
63748	            for (i = 0; i < ii; i++) {
63749	                l = listeners[i];
63750	                if ("zIndex" in l) {
63751	                    if (l.zIndex == indexed[z]) {
63752	                        out.push(l.apply(scope, args));
63753	                        if (stop) {
63754	                            break;
63755	                        }
63756	                        do {
63757	                            z++;
63758	                            l = queue[indexed[z]];
63759	                            l && out.push(l.apply(scope, args));
63760	                            if (stop) {
63761	                                break;
63762	                            }
63763	                        } while (l)
63764	                    } else {
63765	                        queue[l.zIndex] = l;
63766	                    }
63767	                } else {
63768	                    out.push(l.apply(scope, args));
63769	                    if (stop) {
63770	                        break;
63771	                    }
63772	                }
63773	            }
63774	            stop = oldstop;
63775	            current_event = ce;
63776	            return out;
63777	        };
63778	        // Undocumented. Debug only.
63779	        eve._events = events;
63780	    /*\
63781	     * eve.listeners
63782	     [ method ]
63783
63784	     * Internal method which gives you array of all event handlers that will be triggered by the given `name`.
63785
63786	     > Arguments
63787
63788	     - name (string) name of the event, dot (`.`) or slash (`/`) separated
63789
63790	     = (array) array of event handlers
63791	    \*/
63792	    eve.listeners = function (name) {
63793	        var names = isArray(name) ? name : name.split(separator),
63794	            e = events,
63795	            item,
63796	            items,
63797	            k,
63798	            i,
63799	            ii,
63800	            j,
63801	            jj,
63802	            nes,
63803	            es = [e],
63804	            out = [];
63805	        for (i = 0, ii = names.length; i < ii; i++) {
63806	            nes = [];
63807	            for (j = 0, jj = es.length; j < jj; j++) {
63808	                e = es[j].n;
63809	                items = [e[names[i]], e[wildcard]];
63810	                k = 2;
63811	                while (k--) {
63812	                    item = items[k];
63813	                    if (item) {
63814	                        nes.push(item);
63815	                        out = out.concat(item.f || []);
63816	                    }
63817	                }
63818	            }
63819	            es = nes;
63820	        }
63821	        return out;
63822	    };
63823	    /*\
63824	     * eve.separator
63825	     [ method ]
63826
63827	     * If for some reasons you don’t like default separators (`.` or `/`) you can specify yours
63828	     * here. Be aware that if you pass a string longer than one character it will be treated as
63829	     * a list of characters.
63830
63831	     - separator (string) new separator. Empty string resets to default: `.` or `/`.
63832	    \*/
63833	    eve.separator = function (sep) {
63834	        if (sep) {
63835	            sep = Str(sep).replace(/(?=[\.\^\]\[\-])/g, "\\");
63836	            sep = "[" + sep + "]";
63837	            separator = new RegExp(sep);
63838	        } else {
63839	            separator = /[\.\/]/;
63840	        }
63841	    };
63842	    /*\
63843	     * eve.on
63844	     [ method ]
63845	     **
63846	     * Binds given event handler with a given name. You can use wildcards “`*`” for the names:
63847	     | eve.on("*.under.*", f);
63848	     | eve("mouse.under.floor"); // triggers f
63849	     * Use @eve to trigger the listener.
63850	     **
63851	     - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards
63852	     - f (function) event handler function
63853	     **
63854	     - name (array) if you don’t want to use separators, you can use array of strings
63855	     - f (function) event handler function
63856	     **
63857	     = (function) returned function accepts a single numeric parameter that represents z-index of the handler. It is an optional feature and only used when you need to ensure that some subset of handlers will be invoked in a given order, despite of the order of assignment. 
63858	     > Example:
63859	     | eve.on("mouse", eatIt)(2);
63860	     | eve.on("mouse", scream);
63861	     | eve.on("mouse", catchIt)(1);
63862	     * This will ensure that `catchIt` function will be called before `eatIt`.
63863	     *
63864	     * If you want to put your handler before non-indexed handlers, specify a negative value.
63865	     * Note: I assume most of the time you don’t need to worry about z-index, but it’s nice to have this feature “just in case”.
63866	    \*/
63867	    eve.on = function (name, f) {
63868	        if (typeof f != "function") {
63869	            return function () {};
63870	        }
63871	        var names = isArray(name) ? (isArray(name[0]) ? name : [name]) : Str(name).split(comaseparator);
63872	        for (var i = 0, ii = names.length; i < ii; i++) {
63873	            (function (name) {
63874	                var names = isArray(name) ? name : Str(name).split(separator),
63875	                    e = events,
63876	                    exist;
63877	                for (var i = 0, ii = names.length; i < ii; i++) {
63878	                    e = e.n;
63879	                    e = e.hasOwnProperty(names[i]) && e[names[i]] || (e[names[i]] = {n: {}});
63880	                }
63881	                e.f = e.f || [];
63882	                for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) {
63883	                    exist = true;
63884	                    break;
63885	                }
63886	                !exist && e.f.push(f);
63887	            }(names[i]));
63888	        }
63889	        return function (zIndex) {
63890	            if (+zIndex == +zIndex) {
63891	                f.zIndex = +zIndex;
63892	            }
63893	        };
63894	    };
63895	    /*\
63896	     * eve.f
63897	     [ method ]
63898	     **
63899	     * Returns function that will fire given event with optional arguments.
63900	     * Arguments that will be passed to the result function will be also
63901	     * concated to the list of final arguments.
63902	     | el.onclick = eve.f("click", 1, 2);
63903	     | eve.on("click", function (a, b, c) {
63904	     |     console.log(a, b, c); // 1, 2, [event object]
63905	     | });
63906	     > Arguments
63907	     - event (string) event name
63908	     - varargs (…) and any other arguments
63909	     = (function) possible event handler function
63910	    \*/
63911	    eve.f = function (event) {
63912	        var attrs = [].slice.call(arguments, 1);
63913	        return function () {
63914	            eve.apply(null, [event, null].concat(attrs).concat([].slice.call(arguments, 0)));
63915	        };
63916	    };
63917	    /*\
63918	     * eve.stop
63919	     [ method ]
63920	     **
63921	     * Is used inside an event handler to stop the event, preventing any subsequent listeners from firing.
63922	    \*/
63923	    eve.stop = function () {
63924	        stop = 1;
63925	    };
63926	    /*\
63927	     * eve.nt
63928	     [ method ]
63929	     **
63930	     * Could be used inside event handler to figure out actual name of the event.
63931	     **
63932	     > Arguments
63933	     **
63934	     - subname (string) #optional subname of the event
63935	     **
63936	     = (string) name of the event, if `subname` is not specified
63937	     * or
63938	     = (boolean) `true`, if current event’s name contains `subname`
63939	    \*/
63940	    eve.nt = function (subname) {
63941	        var cur = isArray(current_event) ? current_event.join(".") : current_event;
63942	        if (subname) {
63943	            return new RegExp("(?:\\.|\\/|^)" + subname + "(?:\\.|\\/|$)").test(cur);
63944	        }
63945	        return cur;
63946	    };
63947	    /*\
63948	     * eve.nts
63949	     [ method ]
63950	     **
63951	     * Could be used inside event handler to figure out actual name of the event.
63952	     **
63953	     **
63954	     = (array) names of the event
63955	    \*/
63956	    eve.nts = function () {
63957	        return isArray(current_event) ? current_event : current_event.split(separator);
63958	    };
63959	    /*\
63960	     * eve.off
63961	     [ method ]
63962	     **
63963	     * Removes given function from the list of event listeners assigned to given name.
63964	     * If no arguments specified all the events will be cleared.
63965	     **
63966	     > Arguments
63967	     **
63968	     - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards
63969	     - f (function) event handler function
63970	    \*/
63971	    /*\
63972	     * eve.unbind
63973	     [ method ]
63974	     **
63975	     * See @eve.off
63976	    \*/
63977	    eve.off = eve.unbind = function (name, f) {
63978	        if (!name) {
63979	            eve._events = events = {n: {}};
63980	            return;
63981	        }
63982	        var names = isArray(name) ? (isArray(name[0]) ? name : [name]) : Str(name).split(comaseparator);
63983	        if (names.length > 1) {
63984	            for (var i = 0, ii = names.length; i < ii; i++) {
63985	                eve.off(names[i], f);
63986	            }
63987	            return;
63988	        }
63989	        names = isArray(name) ? name : Str(name).split(separator);
63990	        var e,
63991	            key,
63992	            splice,
63993	            i, ii, j, jj,
63994	            cur = [events];
63995	        for (i = 0, ii = names.length; i < ii; i++) {
63996	            for (j = 0; j < cur.length; j += splice.length - 2) {
63997	                splice = [j, 1];
63998	                e = cur[j].n;
63999	                if (names[i] != wildcard) {
64000	                    if (e[names[i]]) {
64001	                        splice.push(e[names[i]]);
64002	                    }
64003	                } else {
64004	                    for (key in e) if (e[has](key)) {
64005	                        splice.push(e[key]);
64006	                    }
64007	                }
64008	                cur.splice.apply(cur, splice);
64009	            }
64010	        }
64011	        for (i = 0, ii = cur.length; i < ii; i++) {
64012	            e = cur[i];
64013	            while (e.n) {
64014	                if (f) {
64015	                    if (e.f) {
64016	                        for (j = 0, jj = e.f.length; j < jj; j++) if (e.f[j] == f) {
64017	                            e.f.splice(j, 1);
64018	                            break;
64019	                        }
64020	                        !e.f.length && delete e.f;
64021	                    }
64022	                    for (key in e.n) if (e.n[has](key) && e.n[key].f) {
64023	                        var funcs = e.n[key].f;
64024	                        for (j = 0, jj = funcs.length; j < jj; j++) if (funcs[j] == f) {
64025	                            funcs.splice(j, 1);
64026	                            break;
64027	                        }
64028	                        !funcs.length && delete e.n[key].f;
64029	                    }
64030	                } else {
64031	                    delete e.f;
64032	                    for (key in e.n) if (e.n[has](key) && e.n[key].f) {
64033	                        delete e.n[key].f;
64034	                    }
64035	                }
64036	                e = e.n;
64037	            }
64038	        }
64039	    };
64040	    /*\
64041	     * eve.once
64042	     [ method ]
64043	     **
64044	     * Binds given event handler with a given name to only run once then unbind itself.
64045	     | eve.once("login", f);
64046	     | eve("login"); // triggers f
64047	     | eve("login"); // no listeners
64048	     * Use @eve to trigger the listener.
64049	     **
64050	     > Arguments
64051	     **
64052	     - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards
64053	     - f (function) event handler function
64054	     **
64055	     = (function) same return function as @eve.on
64056	    \*/
64057	    eve.once = function (name, f) {
64058	        var f2 = function () {
64059	            eve.off(name, f2);
64060	            return f.apply(this, arguments);
64061	        };
64062	        return eve.on(name, f2);
64063	    };
64064	    /*\
64065	     * eve.version
64066	     [ property (string) ]
64067	     **
64068	     * Current version of the library.
64069	    \*/
64070	    eve.version = version;
64071	    eve.toString = function () {
64072	        return "You are running Eve " + version;
64073	    };
64074	    (typeof module != "undefined" && module.exports) ? (module.exports = eve) : ( true ? (!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function() { return eve; }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))) : (glob.eve = eve));
64075	})(this);
64076
64077
64078/***/ },
64079/* 3 */
64080/***/ function(module, exports, __webpack_require__) {
64081
64082	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1)], __WEBPACK_AMD_DEFINE_RESULT__ = function(R) {
64083	    if (R && !R.svg) {
64084	        return;
64085	    }
64086
64087	    var has = "hasOwnProperty",
64088	        Str = String,
64089	        toFloat = parseFloat,
64090	        toInt = parseInt,
64091	        math = Math,
64092	        mmax = math.max,
64093	        abs = math.abs,
64094	        pow = math.pow,
64095	        separator = /[, ]+/,
64096	        eve = R.eve,
64097	        E = "",
64098	        S = " ";
64099	    var xlink = "http://www.w3.org/1999/xlink",
64100	        markers = {
64101	            block: "M5,0 0,2.5 5,5z",
64102	            classic: "M5,0 0,2.5 5,5 3.5,3 3.5,2z",
64103	            diamond: "M2.5,0 5,2.5 2.5,5 0,2.5z",
64104	            open: "M6,1 1,3.5 6,6",
64105	            oval: "M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z"
64106	        },
64107	        markerCounter = {};
64108	    R.toString = function () {
64109	        return  "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version;
64110	    };
64111	    var $ = function (el, attr) {
64112	        if (attr) {
64113	            if (typeof el == "string") {
64114	                el = $(el);
64115	            }
64116	            for (var key in attr) if (attr[has](key)) {
64117	                if (key.substring(0, 6) == "xlink:") {
64118	                    el.setAttributeNS(xlink, key.substring(6), Str(attr[key]));
64119	                } else {
64120	                    el.setAttribute(key, Str(attr[key]));
64121	                }
64122	            }
64123	        } else {
64124	            el = R._g.doc.createElementNS("http://www.w3.org/2000/svg", el);
64125	            el.style && (el.style.webkitTapHighlightColor = "rgba(0,0,0,0)");
64126	        }
64127	        return el;
64128	    },
64129	    addGradientFill = function (element, gradient) {
64130	        var type = "linear",
64131	            id = element.id + gradient,
64132	            fx = .5, fy = .5,
64133	            o = element.node,
64134	            SVG = element.paper,
64135	            s = o.style,
64136	            el = R._g.doc.getElementById(id);
64137	        if (!el) {
64138	            gradient = Str(gradient).replace(R._radial_gradient, function (all, _fx, _fy) {
64139	                type = "radial";
64140	                if (_fx && _fy) {
64141	                    fx = toFloat(_fx);
64142	                    fy = toFloat(_fy);
64143	                    var dir = ((fy > .5) * 2 - 1);
64144	                    pow(fx - .5, 2) + pow(fy - .5, 2) > .25 &&
64145	                        (fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) &&
64146	                        fy != .5 &&
64147	                        (fy = fy.toFixed(5) - 1e-5 * dir);
64148	                }
64149	                return E;
64150	            });
64151	            gradient = gradient.split(/\s*\-\s*/);
64152	            if (type == "linear") {
64153	                var angle = gradient.shift();
64154	                angle = -toFloat(angle);
64155	                if (isNaN(angle)) {
64156	                    return null;
64157	                }
64158	                var vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))],
64159	                    max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1);
64160	                vector[2] *= max;
64161	                vector[3] *= max;
64162	                if (vector[2] < 0) {
64163	                    vector[0] = -vector[2];
64164	                    vector[2] = 0;
64165	                }
64166	                if (vector[3] < 0) {
64167	                    vector[1] = -vector[3];
64168	                    vector[3] = 0;
64169	                }
64170	            }
64171	            var dots = R._parseDots(gradient);
64172	            if (!dots) {
64173	                return null;
64174	            }
64175	            id = id.replace(/[\(\)\s,\xb0#]/g, "_");
64176
64177	            if (element.gradient && id != element.gradient.id) {
64178	                SVG.defs.removeChild(element.gradient);
64179	                delete element.gradient;
64180	            }
64181
64182	            if (!element.gradient) {
64183	                el = $(type + "Gradient", {id: id});
64184	                element.gradient = el;
64185	                $(el, type == "radial" ? {
64186	                    fx: fx,
64187	                    fy: fy
64188	                } : {
64189	                    x1: vector[0],
64190	                    y1: vector[1],
64191	                    x2: vector[2],
64192	                    y2: vector[3],
64193	                    gradientTransform: element.matrix.invert()
64194	                });
64195	                SVG.defs.appendChild(el);
64196	                for (var i = 0, ii = dots.length; i < ii; i++) {
64197	                    el.appendChild($("stop", {
64198	                        offset: dots[i].offset ? dots[i].offset : i ? "100%" : "0%",
64199	                        "stop-color": dots[i].color || "#fff",
64200	                        "stop-opacity": isFinite(dots[i].opacity) ? dots[i].opacity : 1
64201	                    }));
64202	                }
64203	            }
64204	        }
64205	        $(o, {
64206	            fill: fillurl(id),
64207	            opacity: 1,
64208	            "fill-opacity": 1
64209	        });
64210	        s.fill = E;
64211	        s.opacity = 1;
64212	        s.fillOpacity = 1;
64213	        return 1;
64214	    },
64215	    isIE9or10 = function () {
64216	      var mode = document.documentMode;
64217	      return mode && (mode === 9 || mode === 10);
64218	    },
64219	    fillurl = function (id) {
64220	      if (isIE9or10()) {
64221	          return "url('#" + id + "')";
64222	      }
64223	      var location = document.location;
64224	      var locationString = (
64225	          location.protocol + '//' +
64226	          location.host +
64227	          location.pathname +
64228	          location.search
64229	      );
64230	      return "url('" + locationString + "#" + id + "')";
64231	    },
64232	    updatePosition = function (o) {
64233	        var bbox = o.getBBox(1);
64234	        $(o.pattern, {patternTransform: o.matrix.invert() + " translate(" + bbox.x + "," + bbox.y + ")"});
64235	    },
64236	    addArrow = function (o, value, isEnd) {
64237	        if (o.type == "path") {
64238	            var values = Str(value).toLowerCase().split("-"),
64239	                p = o.paper,
64240	                se = isEnd ? "end" : "start",
64241	                node = o.node,
64242	                attrs = o.attrs,
64243	                stroke = attrs["stroke-width"],
64244	                i = values.length,
64245	                type = "classic",
64246	                from,
64247	                to,
64248	                dx,
64249	                refX,
64250	                attr,
64251	                w = 3,
64252	                h = 3,
64253	                t = 5;
64254	            while (i--) {
64255	                switch (values[i]) {
64256	                    case "block":
64257	                    case "classic":
64258	                    case "oval":
64259	                    case "diamond":
64260	                    case "open":
64261	                    case "none":
64262	                        type = values[i];
64263	                        break;
64264	                    case "wide": h = 5; break;
64265	                    case "narrow": h = 2; break;
64266	                    case "long": w = 5; break;
64267	                    case "short": w = 2; break;
64268	                }
64269	            }
64270	            if (type == "open") {
64271	                w += 2;
64272	                h += 2;
64273	                t += 2;
64274	                dx = 1;
64275	                refX = isEnd ? 4 : 1;
64276	                attr = {
64277	                    fill: "none",
64278	                    stroke: attrs.stroke
64279	                };
64280	            } else {
64281	                refX = dx = w / 2;
64282	                attr = {
64283	                    fill: attrs.stroke,
64284	                    stroke: "none"
64285	                };
64286	            }
64287	            if (o._.arrows) {
64288	                if (isEnd) {
64289	                    o._.arrows.endPath && markerCounter[o._.arrows.endPath]--;
64290	                    o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--;
64291	                } else {
64292	                    o._.arrows.startPath && markerCounter[o._.arrows.startPath]--;
64293	                    o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--;
64294	                }
64295	            } else {
64296	                o._.arrows = {};
64297	            }
64298	            if (type != "none") {
64299	                var pathId = "raphael-marker-" + type,
64300	                    markerId = "raphael-marker-" + se + type + w + h + "-obj" + o.id;
64301	                if (!R._g.doc.getElementById(pathId)) {
64302	                    p.defs.appendChild($($("path"), {
64303	                        "stroke-linecap": "round",
64304	                        d: markers[type],
64305	                        id: pathId
64306	                    }));
64307	                    markerCounter[pathId] = 1;
64308	                } else {
64309	                    markerCounter[pathId]++;
64310	                }
64311	                var marker = R._g.doc.getElementById(markerId),
64312	                    use;
64313	                if (!marker) {
64314	                    marker = $($("marker"), {
64315	                        id: markerId,
64316	                        markerHeight: h,
64317	                        markerWidth: w,
64318	                        orient: "auto",
64319	                        refX: refX,
64320	                        refY: h / 2
64321	                    });
64322	                    use = $($("use"), {
64323	                        "xlink:href": "#" + pathId,
64324	                        transform: (isEnd ? "rotate(180 " + w / 2 + " " + h / 2 + ") " : E) + "scale(" + w / t + "," + h / t + ")",
64325	                        "stroke-width": (1 / ((w / t + h / t) / 2)).toFixed(4)
64326	                    });
64327	                    marker.appendChild(use);
64328	                    p.defs.appendChild(marker);
64329	                    markerCounter[markerId] = 1;
64330	                } else {
64331	                    markerCounter[markerId]++;
64332	                    use = marker.getElementsByTagName("use")[0];
64333	                }
64334	                $(use, attr);
64335	                var delta = dx * (type != "diamond" && type != "oval");
64336	                if (isEnd) {
64337	                    from = o._.arrows.startdx * stroke || 0;
64338	                    to = R.getTotalLength(attrs.path) - delta * stroke;
64339	                } else {
64340	                    from = delta * stroke;
64341	                    to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);
64342	                }
64343	                attr = {};
64344	                attr["marker-" + se] = "url(#" + markerId + ")";
64345	                if (to || from) {
64346	                    attr.d = R.getSubpath(attrs.path, from, to);
64347	                }
64348	                $(node, attr);
64349	                o._.arrows[se + "Path"] = pathId;
64350	                o._.arrows[se + "Marker"] = markerId;
64351	                o._.arrows[se + "dx"] = delta;
64352	                o._.arrows[se + "Type"] = type;
64353	                o._.arrows[se + "String"] = value;
64354	            } else {
64355	                if (isEnd) {
64356	                    from = o._.arrows.startdx * stroke || 0;
64357	                    to = R.getTotalLength(attrs.path) - from;
64358	                } else {
64359	                    from = 0;
64360	                    to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);
64361	                }
64362	                o._.arrows[se + "Path"] && $(node, {d: R.getSubpath(attrs.path, from, to)});
64363	                delete o._.arrows[se + "Path"];
64364	                delete o._.arrows[se + "Marker"];
64365	                delete o._.arrows[se + "dx"];
64366	                delete o._.arrows[se + "Type"];
64367	                delete o._.arrows[se + "String"];
64368	            }
64369	            for (attr in markerCounter) if (markerCounter[has](attr) && !markerCounter[attr]) {
64370	                var item = R._g.doc.getElementById(attr);
64371	                item && item.parentNode.removeChild(item);
64372	            }
64373	        }
64374	    },
64375	    dasharray = {
64376	        "-": [3, 1],
64377	        ".": [1, 1],
64378	        "-.": [3, 1, 1, 1],
64379	        "-..": [3, 1, 1, 1, 1, 1],
64380	        ". ": [1, 3],
64381	        "- ": [4, 3],
64382	        "--": [8, 3],
64383	        "- .": [4, 3, 1, 3],
64384	        "--.": [8, 3, 1, 3],
64385	        "--..": [8, 3, 1, 3, 1, 3]
64386	    },
64387	    addDashes = function (o, value, params) {
64388	        value = dasharray[Str(value).toLowerCase()];
64389	        if (value) {
64390	            var width = o.attrs["stroke-width"] || "1",
64391	                butt = {round: width, square: width, butt: 0}[o.attrs["stroke-linecap"] || params["stroke-linecap"]] || 0,
64392	                dashes = [],
64393	                i = value.length;
64394	            while (i--) {
64395	                dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt;
64396	            }
64397	            $(o.node, {"stroke-dasharray": dashes.join(",")});
64398	        }
64399	        else {
64400	          $(o.node, {"stroke-dasharray": "none"});
64401	        }
64402	    },
64403	    setFillAndStroke = function (o, params) {
64404	        var node = o.node,
64405	            attrs = o.attrs,
64406	            vis = node.style.visibility;
64407	        node.style.visibility = "hidden";
64408	        for (var att in params) {
64409	            if (params[has](att)) {
64410	                if (!R._availableAttrs[has](att)) {
64411	                    continue;
64412	                }
64413	                var value = params[att];
64414	                attrs[att] = value;
64415	                switch (att) {
64416	                    case "blur":
64417	                        o.blur(value);
64418	                        break;
64419	                    case "title":
64420	                        var title = node.getElementsByTagName("title");
64421
64422	                        // Use the existing <title>.
64423	                        if (title.length && (title = title[0])) {
64424	                          title.firstChild.nodeValue = value;
64425	                        } else {
64426	                          title = $("title");
64427	                          var val = R._g.doc.createTextNode(value);
64428	                          title.appendChild(val);
64429	                          node.appendChild(title);
64430	                        }
64431	                        break;
64432	                    case "href":
64433	                    case "target":
64434	                        var pn = node.parentNode;
64435	                        if (pn.tagName.toLowerCase() != "a") {
64436	                            var hl = $("a");
64437	                            pn.insertBefore(hl, node);
64438	                            hl.appendChild(node);
64439	                            pn = hl;
64440	                        }
64441	                        if (att == "target") {
64442	                            pn.setAttributeNS(xlink, "show", value == "blank" ? "new" : value);
64443	                        } else {
64444	                            pn.setAttributeNS(xlink, att, value);
64445	                        }
64446	                        break;
64447	                    case "cursor":
64448	                        node.style.cursor = value;
64449	                        break;
64450	                    case "transform":
64451	                        o.transform(value);
64452	                        break;
64453	                    case "arrow-start":
64454	                        addArrow(o, value);
64455	                        break;
64456	                    case "arrow-end":
64457	                        addArrow(o, value, 1);
64458	                        break;
64459	                    case "clip-rect":
64460	                        var rect = Str(value).split(separator);
64461	                        if (rect.length == 4) {
64462	                            o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode);
64463	                            var el = $("clipPath"),
64464	                                rc = $("rect");
64465	                            el.id = R.createUUID();
64466	                            $(rc, {
64467	                                x: rect[0],
64468	                                y: rect[1],
64469	                                width: rect[2],
64470	                                height: rect[3]
64471	                            });
64472	                            el.appendChild(rc);
64473	                            o.paper.defs.appendChild(el);
64474	                            $(node, {"clip-path": "url(#" + el.id + ")"});
64475	                            o.clip = rc;
64476	                        }
64477	                        if (!value) {
64478	                            var path = node.getAttribute("clip-path");
64479	                            if (path) {
64480	                                var clip = R._g.doc.getElementById(path.replace(/(^url\(#|\)$)/g, E));
64481	                                clip && clip.parentNode.removeChild(clip);
64482	                                $(node, {"clip-path": E});
64483	                                delete o.clip;
64484	                            }
64485	                        }
64486	                    break;
64487	                    case "path":
64488	                        if (o.type == "path") {
64489	                            $(node, {d: value ? attrs.path = R._pathToAbsolute(value) : "M0,0"});
64490	                            o._.dirty = 1;
64491	                            if (o._.arrows) {
64492	                                "startString" in o._.arrows && addArrow(o, o._.arrows.startString);
64493	                                "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
64494	                            }
64495	                        }
64496	                        break;
64497	                    case "width":
64498	                        node.setAttribute(att, value);
64499	                        o._.dirty = 1;
64500	                        if (attrs.fx) {
64501	                            att = "x";
64502	                            value = attrs.x;
64503	                        } else {
64504	                            break;
64505	                        }
64506	                    case "x":
64507	                        if (attrs.fx) {
64508	                            value = -attrs.x - (attrs.width || 0);
64509	                        }
64510	                    case "rx":
64511	                        if (att == "rx" && o.type == "rect") {
64512	                            break;
64513	                        }
64514	                    case "cx":
64515	                        node.setAttribute(att, value);
64516	                        o.pattern && updatePosition(o);
64517	                        o._.dirty = 1;
64518	                        break;
64519	                    case "height":
64520	                        node.setAttribute(att, value);
64521	                        o._.dirty = 1;
64522	                        if (attrs.fy) {
64523	                            att = "y";
64524	                            value = attrs.y;
64525	                        } else {
64526	                            break;
64527	                        }
64528	                    case "y":
64529	                        if (attrs.fy) {
64530	                            value = -attrs.y - (attrs.height || 0
64530);
64531	                        }
64532	                    case "ry":
64533	                        if (att == "ry" && o.type == "rect") {
64534	                            break;
64535	                        }
64536	                    case "cy":
64537	                        node.setAttribute(att, value);
64538	                        o.pattern && updatePosition(o);
64539	                        o._.dirty = 1;
64540	                        break;
64541	                    case "r":
64542	                        if (o.type == "rect") {
64543	                            $(node, {rx: value, ry: value});
64544	                        } else {
64545	                            node.setAttribute(att, value);
64546	                        }
64547	                        o._.dirty = 1;
64548	                        break;
64549	                    case "src":
64550	                        if (o.type == "image") {
64551	                            node.setAttributeNS(xlink, "href", value);
64552	                        }
64553	                        break;
64554	                    case "stroke-width":
64555	                        if (o._.sx != 1 || o._.sy != 1) {
64556	                            value /= mmax(abs(o._.sx), abs(o._.sy)) || 1;
64557	                        }
64558	                        node.setAttribute(att, value);
64559	                        if (attrs["stroke-dasharray"]) {
64560	                            addDashes(o, attrs["stroke-dasharray"], params);
64561	                        }
64562	                        if (o._.arrows) {
64563	                            "startString" in o._.arrows && addArrow(o, o._.arrows.startString);
64564	                            "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
64565	                        }
64566	                        break;
64567	                    case "stroke-dasharray":
64568	                        addDashes(o, value, params);
64569	                        break;
64570	                    case "fill":
64571	                        var isURL = Str(value).match(R._ISURL);
64572	                        if (isURL) {
64573	                            el = $("pattern");
64574	                            var ig = $("image");
64575	                            el.id = R.createUUID();
64576	                            $(el, {x: 0, y: 0, patternUnits: "userSpaceOnUse", height: 1, width: 1});
64577	                            $(ig, {x: 0, y: 0, "xlink:href": isURL[1]});
64578	                            el.appendChild(ig);
64579
64580	                            (function (el) {
64581	                                R._preload(isURL[1], function () {
64582	                                    var w = this.offsetWidth,
64583	                                        h = this.offsetHeight;
64584	                                    $(el, {width: w, height: h});
64585	                                    $(ig, {width: w, height: h});
64586	                                });
64587	                            })(el);
64588	                            o.paper.defs.appendChild(el);
64589	                            $(node, {fill: "url(#" + el.id + ")"});
64590	                            o.pattern = el;
64591	                            o.pattern && updatePosition(o);
64592	                            break;
64593	                        }
64594	                        var clr = R.getRGB(value);
64595	                        if (!clr.error) {
64596	                            delete params.gradient;
64597	                            delete attrs.gradient;
64598	                            !R.is(attrs.opacity, "undefined") &&
64599	                                R.is(params.opacity, "undefined") &&
64600	                                $(node, {opacity: attrs.opacity});
64601	                            !R.is(attrs["fill-opacity"], "undefined") &&
64602	                                R.is(params["fill-opacity"], "undefined") &&
64603	                                $(node, {"fill-opacity": attrs["fill-opacity"]});
64604	                        } else if ((o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value)) {
64605	                            if ("opacity" in attrs || "fill-opacity" in attrs) {
64606	                                var gradient = R._g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E));
64607	                                if (gradient) {
64608	                                    var stops = gradient.getElementsByTagName("stop");
64609	                                    $(stops[stops.length - 1], {"stop-opacity": ("opacity" in attrs ? attrs.opacity : 1) * ("fill-opacity" in attrs ? attrs["fill-opacity"] : 1)});
64610	                                }
64611	                            }
64612	                            attrs.gradient = value;
64613	                            attrs.fill = "none";
64614	                            break;
64615	                        }
64616	                        clr[has]("opacity") && $(node, {"fill-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});
64617	                    case "stroke":
64618	                        clr = R.getRGB(value);
64619	                        node.setAttribute(att, clr.hex);
64620	                        att == "stroke" && clr[has]("opacity") && $(node, {"stroke-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});
64621	                        if (att == "stroke" && o._.arrows) {
64622	                            "startString" in o._.arrows && addArrow(o, o._.arrows.startString);
64623	                            "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
64624	                        }
64625	                        break;
64626	                    case "gradient":
64627	                        (o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value);
64628	                        break;
64629	                    case "opacity":
64630	                        if (attrs.gradient && !attrs[has]("stroke-opacity")) {
64631	                            $(node, {"stroke-opacity": value > 1 ? value / 100 : value});
64632	                        }
64633	                        // fall
64634	                    case "fill-opacity":
64635	                        if (attrs.gradient) {
64636	                            gradient = R._g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E));
64637	                            if (gradient) {
64638	                                stops = gradient.getElementsByTagName("stop");
64639	                                $(stops[stops.length - 1], {"stop-opacity": value});
64640	                            }
64641	                            break;
64642	                        }
64643	                    default:
64644	                        att == "font-size" && (value = toInt(value, 10) + "px");
64645	                        var cssrule = att.replace(/(\-.)/g, function (w) {
64646	                            return w.substring(1).toUpperCase();
64647	                        });
64648	                        node.style[cssrule] = value;
64649	                        o._.dirty = 1;
64650	                        node.setAttribute(att, value);
64651	                        break;
64652	                }
64653	            }
64654	        }
64655
64656	        tuneText(o, params);
64657	        node.style.visibility = vis;
64658	    },
64659	    leading = 1.2,
64660	    tuneText = function (el, params) {
64661	        if (el.type != "text" || !(params[has]("text") || params[has]("font") || params[has]("font-size") || params[has]("x") || params[has]("y"))) {
64662	            return;
64663	        }
64664	        var a = el.attrs,
64665	            node = el.node,
64666	            fontSize = node.firstChild ? toInt(R._g.doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue("font-size"), 10) : 10;
64667
64668	        if (params[has]("text")) {
64669	            a.text = params.text;
64670	            while (node.firstChild) {
64671	                node.removeChild(node.firstChild);
64672	            }
64673	            var texts = Str(params.text).split("\n"),
64674	                tspans = [],
64675	                tspan;
64676	            for (var i = 0, ii = texts.length; i < ii; i++) {
64677	                tspan = $("tspan");
64678	                i && $(tspan, {dy: fontSize * leading, x: a.x});
64679	                tspan.appendChild(R._g.doc.createTextNode(texts[i]));
64680	                node.appendChild(tspan);
64681	                tspans[i] = tspan;
64682	            }
64683	        } else {
64684	            tspans = node.getElementsByTagName("tspan");
64685	            for (i = 0, ii = tspans.length; i < ii; i++) if (i) {
64686	                $(tspans[i], {dy: fontSize * leading, x: a.x});
64687	            } else {
64688	                $(tspans[0], {dy: 0});
64689	            }
64690	        }
64691	        $(node, {x: a.x, y: a.y});
64692	        el._.dirty = 1;
64693	        var bb = el._getBBox(),
64694	            dif = a.y - (bb.y + bb.height / 2);
64695	        dif && R.is(dif, "finite") && $(tspans[0], {dy: dif});
64696	    },
64697	    getRealNode = function (node) {
64698	        if (node.parentNode && node.parentNode.tagName.toLowerCase() === "a") {
64699	            return node.parentNode;
64700	        } else {
64701	            return node;
64702	        }
64703	    },
64704	    Element = function (node, svg) {
64705	        var X = 0,
64706	            Y = 0;
64707	        /*\
64708	         * Element.node
64709	         [ property (object) ]
64710	         **
64711	         * Gives you a reference to the DOM object, so you can assign event handlers or just mess around.
64712	         **
64713	         * Note: Don’t mess with it.
64714	         > Usage
64715	         | // draw a circle at coordinate 10,10 with radius of 10
64716	         | var c = paper.circle(10, 10, 10);
64717	         | c.node.onclick = function () {
64718	         |     c.attr("fill", "red");
64719	         | };
64720	        \*/
64721	        this[0] = this.node = node;
64722	        /*\
64723	         * Element.raphael
64724	         [ property (object) ]
64725	         **
64726	         * Internal reference to @Raphael object. In case it is not available.
64727	         > Usage
64728	         | Raphael.el.red = function () {
64729	         |     var hsb = this.paper.raphael.rgb2hsb(this.attr("fill"));
64730	         |     hsb.h = 1;
64731	         |     this.attr({fill: this.paper.raphael.hsb2rgb(hsb).hex});
64732	         | }
64733	        \*/
64734	        node.raphael = true;
64735	        /*\
64736	         * Element.id
64737	         [ property (number) ]
64738	         **
64739	         * Unique id of the element. Especially useful when you want to listen to events of the element,
64740	         * because all events are fired in format `<module>.<action>.<id>`. Also useful for @Paper.getById method.
64741	        \*/
64742	        this.id = guid();
64743	        node.raphaelid = this.id;
64744
64745	        /**
64746	        * Method that returns a 5 letter/digit id, enough for 36^5 = 60466176 elements
64747	        * @returns {string} id
64748	        */
64749	        function guid() {
64750	            return ("0000" + (Math.random()*Math.pow(36,5) << 0).toString(36)).slice(-5);
64751	        }
64752
64753	        this.matrix = R.matrix();
64754	        this.realPath = null;
64755	        /*\
64756	         * Element.paper
64757	         [ property (object) ]
64758	         **
64759	         * Internal reference to “paper” where object drawn. Mainly for use in plugins and element extensions.
64760	         > Usage
64761	         | Raphael.el.cross = function () {
64762	         |     this.attr({fill: "red"});
64763	         |     this.paper.path("M10,10L50,50M50,10L10,50")
64764	         |         .attr({stroke: "red"});
64765	         | }
64766	        \*/
64767	        this.paper = svg;
64768	        this.attrs = this.attrs || {};
64769	        this._ = {
64770	            transform: [],
64771	            sx: 1,
64772	            sy: 1,
64773	            deg: 0,
64774	            dx: 0,
64775	            dy: 0,
64776	            dirty: 1
64777	        };
64778	        !svg.bottom && (svg.bottom = this);
64779	        /*\
64780	         * Element.prev
64781	         [ property (object) ]
64782	         **
64783	         * Reference to the previous element in the hierarchy.
64784	        \*/
64785	        this.prev = svg.top;
64786	        svg.top && (svg.top.next = this);
64787	        svg.top = this;
64788	        /*\
64789	         * Element.next
64790	         [ property (object) ]
64791	         **
64792	         * Reference to the next element in the hierarchy.
64793	        \*/
64794	        this.next = null;
64795	    },
64796	    elproto = R.el;
64797
64798	    Element.prototype = elproto;
64799	    elproto.constructor = Element;
64800
64801	    R._engine.path = function (pathString, SVG) {
64802	        var el = $("path");
64803	        SVG.canvas && SVG.canvas.appendChild(el);
64804	        var p = new Element(el, SVG);
64805	        p.type = "path";
64806	        setFillAndStroke(p, {
64807	            fill: "none",
64808	            stroke: "#000",
64809	            path: pathString
64810	        });
64811	        return p;
64812	    };
64813	    /*\
64814	     * Element.rotate
64815	     [ method ]
64816	     **
64817	     * Deprecated! Use @Element.transform instead.
64818	     * Adds rotation by given angle around given point to the list of
64819	     * transformations of the element.
64820	     > Parameters
64821	     - deg (number) angle in degrees
64822	     - cx (number) #optional x coordinate of the centre of rotation
64823	     - cy (number) #optional y coordinate of the centre of rotation
64824	     * If cx & cy aren’t specified centre of the shape is used as a point of rotation.
64825	     = (object) @Element
64826	    \*/
64827	    elproto.rotate = function (deg, cx, cy) {
64828	        if (this.removed) {
64829	            return this;
64830	        }
64831	        deg = Str(deg).split(separator);
64832	        if (deg.length - 1) {
64833	            cx = toFloat(deg[1]);
64834	            cy = toFloat(deg[2]);
64835	        }
64836	        deg = toFloat(deg[0]);
64837	        (cy == null) && (cx = cy);
64838	        if (cx == null || cy == null) {
64839	            var bbox = this.getBBox(1);
64840	            cx = bbox.x + bbox.width / 2;
64841	            cy = bbox.y + bbox.height / 2;
64842	        }
64843	        this.transform(this._.transform.concat([["r", deg, cx, cy]]));
64844	        return this;
64845	    };
64846	    /*\
64847	     * Element.scale
64848	     [ method ]
64849	     **
64850	     * Deprecated! Use @Element.transform instead.
64851	     * Adds scale by given amount relative to given point to the list of
64852	     * transformations of the element.
64853	     > Parameters
64854	     - sx (number) horisontal scale amount
64855	     - sy (number) vertical scale amount
64856	     - cx (number) #optional x coordinate of the centre of scale
64857	     - cy (number) #optional y coordinate of the centre of scale
64858	     * If cx & cy aren’t specified centre of the shape is used instead.
64859	     = (object) @Element
64860	    \*/
64861	    elproto.scale = function (sx, sy, cx, cy) {
64862	        if (this.removed) {
64863	            return this;
64864	        }
64865	        sx = Str(sx).split(separator);
64866	        if (sx.length - 1) {
64867	            sy = toFloat(sx[1]);
64868	            cx = toFloat(sx[2]);
64869	            cy = toFloat(sx[3]);
64870	        }
64871	        sx = toFloat(sx[0]);
64872	        (sy == null) && (sy = sx);
64873	        (cy == null) && (cx = cy);
64874	        if (cx == null || cy == null) {
64875	            var bbox = this.getBBox(1);
64876	        }
64877	        cx = cx == null ? bbox.x + bbox.width / 2 : cx;
64878	        cy = cy == null ? bbox.y + bbox.height / 2 : cy;
64879	        this.transform(this._.transform.concat([["s", sx, sy, cx, cy]]));
64880	        return this;
64881	    };
64882	    /*\
64883	     * Element.translate
64884	     [ method ]
64885	     **
64886	     * Deprecated! Use @Element.transform instead.
64887	     * Adds translation by given amount to the list of transformations of the element.
64888	     > Parameters
64889	     - dx (number) horisontal shift
64890	     - dy (number) vertical shift
64891	     = (object) @Element
64892	    \*/
64893	    elproto.translate = function (dx, dy) {
64894	        if (this.removed) {
64895	            return this;
64896	        }
64897	        dx = Str(dx).split(separator);
64898	        if (dx.length - 1) {
64899	            dy = toFloat(dx[1]);
64900	        }
64901	        dx = toFloat(dx[0]) || 0;
64902	        dy = +dy || 0;
64903	        this.transform(this._.transform.concat([["t", dx, dy]]));
64904	        return this;
64905	    };
64906	    /*\
64907	     * Element.transform
64908	     [ method ]
64909	     **
64910	     * Adds transformation to the element which is separate to other attributes,
64911	     * i.e. translation doesn’t change `x` or `y` of the rectange. The format
64912	     * of transformation string is similar to the path string syntax:
64913	     | "t100,100r30,100,100s2,2,100,100r45s1.5"
64914	     * Each letter is a command. There are four commands: `t` is for translate, `r` is for rotate, `s` is for
64915	     * scale and `m` is for matrix.
64916	     *
64917	     * There are also alternative “absolute” translation, rotation and scale: `T`, `R` and `S`. They will not take previous transformation into account. For example, `...T100,0` will always move element 100 px horisontally, while `...t100,0` could move it vertically if there is `r90` before. Just compare results of `r90t100,0` and `r90T100,0`.
64918	     *
64919	     * So, the example line above could be read like “translate by 100, 100; rotate 30° around 100, 100; scale twice around 100, 100;
64920	     * rotate 45° around centre; scale 1.5 times relative to centre”. As you can see rotate and scale commands have origin
64921	     * coordinates as optional parameters, the default is the centre point of the element.
64922	     * Matrix accepts six parameters.
64923	     > Usage
64924	     | var el = paper.rect(10, 20, 300, 200);
64925	     | // translate 100, 100, rotate 45°, translate -100, 0
64926	     | el.transform("t100,100r45t-100,0");
64927	     | // if you want you can append or prepend transformations
64928	     | el.transform("...t50,50");
64929	     | el.transform("s2...");
64930	     | // or even wrap
64931	     | el.transform("t50,50...t-50-50");
64932	     | // to reset transformation call method with empty string
64933	     | el.transform("");
64934	     | // to get current value call it without parameters
64935	     | console.log(el.transform());
64936	     > Parameters
64937	     - tstr (string) #optional transformation string
64938	     * If tstr isn’t specified
64939	     = (string) current transformation string
64940	     * else
64941	     = (object) @Element
64942	    \*/
64943	    elproto.transform = function (tstr) {
64944	        var _ = this._;
64945	        if (tstr == null) {
64946	            return _.transform;
64947	        }
64948	        R._extractTransform(this, tstr);
64949
64950	        this.clip && $(this.clip, {transform: this.matrix.invert()});
64951	        this.pattern && updatePosition(this);
64952	        this.node && $(this.node, {transform: this.matrix});
64953
64954	        if (_.sx != 1 || _.sy != 1) {
64955	            var sw = this.attrs[has]("stroke-width") ? this.attrs["stroke-width"] : 1;
64956	            this.attr({"stroke-width": sw});
64957	        }
64958
64959	        return this;
64960	    };
64961	    /*\
64962	     * Element.hide
64963	     [ method ]
64964	     **
64965	     * Makes element invisible. See @Element.show.
64966	     = (object) @Element
64967	    \*/
64968	    elproto.hide = function () {
64969	        if(!this.removed) this.node.style.display = "none";
64970	        return this;
64971	    };
64972	    /*\
64973	     * Element.show
64974	     [ method ]
64975	     **
64976	     * Makes element visible. See @Element.hide.
64977	     = (object) @Element
64978	    \*/
64979	    elproto.show = function () {
64980	        if(!this.removed) this.node.style.display = "";
64981	        return this;
64982	    };
64983	    /*\
64984	     * Element.remove
64985	     [ method ]
64986	     **
64987	     * Removes element from the paper.
64988	    \*/
64989	    elproto.remove = function () {
64990	        var node = getRealNode(this.node);
64991	        if (this.removed || !node.parentNode) {
64992	            return;
64993	        }
64994	        var paper = this.paper;
64995	        paper.__set__ && paper.__set__.exclude(this);
64996	        eve.unbind("raphael.*.*." + this.id);
64997	        if (this.gradient) {
64998	            paper.defs.removeChild(this.gradient);
64999	        }
65000	        R._tear(this, paper);
65001
65002	        node.parentNode.removeChild(node);
65003
65004	        // Remove custom data for element
65005	        this.removeData();
65006
65007	        for (var i in this) {
65008	            this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null;
65009	        }
65010	        this.removed = true;
65011	    };
65012	    elproto._getBBox = function () {
65013	        if (this.node.style.display == "none") {
65014	            this.show();
65015	            var hide = true;
65016	        }
65017	        var canvasHidden = false,
65018	            containerStyle;
65019	        if (this.paper.canvas.parentElement) {
65020	          containerStyle = this.paper.canvas.parentElement.style;
65021	        } //IE10+ can't find parentElement
65022	        else if (this.paper.canvas.parentNode) {
65023	          containerStyle = this.paper.canvas.parentNode.style;
65024	        }
65025
65026	        if(containerStyle && containerStyle.display == "none") {
65027	          canvasHidden = true;
65028	          containerStyle.display = "";
65029	        }
65030	        var bbox = {};
65031	        try {
65032	            bbox = this.node.getBBox();
65033	        } catch(e) {
65034	            // Firefox 3.0.x, 25.0.1 (probably more versions affected) play badly here - possible fix
65035	            bbox = {
65036	                x: this.node.clientLeft,
65037	                y: this.node.clientTop,
65038	                width: this.node.clientWidth,
65039	                height: this.node.clientHeight
65040	            }
65041	        } finally {
65042	            bbox = bbox || {};
65043	            if(canvasHidden){
65044	              containerStyle.display = "none";
65045	            }
65046	        }
65047	        hide && this.hide();
65048	        return bbox;
65049	    };
65050	    /*\
65051	     * Element.attr
65052	     [ method ]
65053	     **
65054	     * Sets the attributes of the element.
65055	     > Parameters
65056	     - attrName (string) attribute’s name
65057	     - value (string) value
65058	     * or
65059	     - params (object) object of name/value pairs
65060	     * or
65061	     - attrName (string) attribute’s name
65062	     * or
65063	     - attrNames (array) in this case method returns array of current values for given attribute names
65064	     = (object) @Element if attrsName & value or params are passed in.
65065	     = (...) value of the attribute if only attrsName is passed in.
65066	     = (array) array of values of the attribute if attrsNames is passed in.
65067	     = (object) object of attributes if nothing is passed in.
65068	     > Possible parameters
65069	     # <p>Please refer to the <a href="http://www.w3.org/TR/SVG/" title="The W3C Recommendation for the SVG language describes these properties in detail.">SVG specification</a> for an explanation of these parameters.</p>
65070	     o arrow-end (string) arrowhead on the end of the path. The format for string is `<type>[-<width>[-<length>]]`. Possible types: `classic`, `block`, `open`, `oval`, `diamond`, `none`, width: `wide`, `narrow`, `medium`, length: `long`, `short`, `midium`.
65071	     o clip-rect (string) comma or space separated values: x, y, width and height
65072	     o cursor (string) CSS type of the cursor
65073	     o cx (number) the x-axis coordinate of the center of the circle, or ellipse
65074	     o cy (number) the y-axis coordinate of the center of the circle, or ellipse
65075	     o fill (string) colour, gradient or image
65076	     o fill-opacity (number)
65077	     o font (string)
65078	     o font-family (string)
65079	     o font-size (number) font size in pixels
65080	     o font-weight (string)
65081	     o height (number)
65082	     o href (string) URL, if specified element behaves as hyperlink
65083	     o opacity (number)
65084	     o path (string) SVG path string format
65085	     o r (number) radius of the circle, ellipse or rounded corner on the rect
65086	     o rx (number) horisontal radius of the ellipse
65087	     o ry (number) vertical radius of the ellipse
65088	     o src (string) image URL, only works for @Element.image element
65089	     o stroke (string) stroke colour
65090	     o stroke-dasharray (string) [“”, “none”, “`-`”, “`.`”, “`-.`”, “`-..`”, “`. `”, “`- `”, “`--`”, “`- .`”, “`--.`”, “`--..`”]
65091	     o stroke-linecap (string) [“`butt`”, “`square`”, “`round`”]
65092	     o stroke-linejoin (string) [“`bevel`”, “`round`”, “`miter`”]
65093	     o stroke-miterlimit (number)
65094	     o stroke-opacity (number)
65095	     o stroke-width (number) stroke width in pixels, default is '1'
65096	     o target (string) used with href
65097	     o text (string) contents of the text element. Use `\n` for multiline text
65098	     o text-anchor (string) [“`start`”, “`middle`”, “`end`”], default is “`middle`”
65099	     o title (string) will create tooltip with a given text
65100	     o transform (string) see @Element.transform
65101	     o width (number)
65102	     o x (number)
65103	     o y (number)
65104	     > Gradients
65105	     * Linear gradient format: “`‹angle›-‹colour›[-‹colour›[:‹offset›]]*-‹colour›`”, example: “`90-#fff-#000`” – 90°
65106	     * gradient from white to black or “`0-#fff-#f00:20-#000`” – 0° gradient from white via red (at 20%) to black.
65107	     *
65108	     * radial gradient: “`r[(‹fx›, ‹fy›)]‹colour›[-‹colour›[:‹offset›]]*-‹colour›`”, example: “`r#fff-#000`” –
65109	     * gradient from white to black or “`r(0.25, 0.75)#fff-#000`” – gradient from white to black with focus point
65110	     * at 0.25, 0.75. Focus point coordinates are in 0..1 range. Radial gradients can only be applied to circles and ellipses.
65111	     > Path String
65112	     # <p>Please refer to <a href="http://www.w3.org/TR/SVG/paths.html#PathData" title="Details of a path’s data attribute’s format are described in the SVG specification.">SVG documentation regarding path string</a>. Raphaël fully supports it.</p>
65113	     > Colour Parsing
65114	     # <ul>
65115	     #     <li>Colour name (“<code>red</code>”, “<code>green</code>”, “<code>cornflowerblue</code>”, etc)</li>
65116	     #     <li>#••• — shortened HTML colour: (“<code>#000</code>”, “<code>#fc0</code>”, etc)</li>
65117	     #     <li>#•••••• — full length HTML colour: (“<code>#000000</code>”, “<code>#bd2300</code>”)</li>
65118	     #     <li>rgb(•••, •••, •••) — red, green and blue channels’ values: (“<code>rgb(200,&nbsp;100,&nbsp;0)</code>”)</li>
65119	     #     <li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<code>rgb(100%,&nbsp;175%,&nbsp;0%)</code>”)</li>
65120	     #     <li>rgba(•••, •••, •••, •••) — red, green and blue channels’ values: (“<code>rgba(200,&nbsp;100,&nbsp;0, .5)</code>”)</li>
65121	     #     <li>rgba(•••%, •••%, •••%, •••%) — same as above, but in %: (“<code>rgba(100%,&nbsp;175%,&nbsp;0%, 50%)</code>”)</li>
65122	     #     <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<code>hsb(0.5,&nbsp;0.25,&nbsp;1)</code>”)</li>
65123	     #     <li>hsb(•••%, •••%, •••%) — same as above, but in %</li>
65124	     #     <li>hsba(•••, •••, •••, •••) — same as above, but with opacity</li>
65125	     #     <li>hsl(•••, •••, •••) — almost the same as hsb, see <a href="http://en.wikipedia.org/wiki/HSL_and_HSV" title="HSL and HSV - Wikipedia, the free encyclopedia">Wikipedia page</a></li>
65126	     #     <li>hsl(•••%, •••%, •••%) — same as above, but in %</li>
65127	     #     <li>hsla(•••, •••, •••, •••) — same as above, but with opacity</li>
65128	     #     <li>Optionally for hsb and hsl you could specify hue as a degree: “<code>hsl(240deg,&nbsp;1,&nbsp;.5)</code>” or, if you want to go fancy, “<code>hsl(240°,&nbsp;1,&nbsp;.5)</code>”</li>
65129	     # </ul>
65130	    \*/
65131	    elproto.attr = function (name, value) {
65132	        if (this.removed) {
65133	            return this;
65134	        }
65135	        if (name == null) {
65136	            var res = {};
65137	            for (var a in this.attrs) if (this.attrs[has](a)) {
65138	                res[a] = this.attrs[a];
65139	            }
65140	            res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
65141	            res.transform = this._.transform;
65142	            return res;
65143	        }
65144	        if (value == null && R.is(name, "string")) {
65145	            if (name == "fill" && this.attrs.fill == "none" && this.attrs.gradient) {
65146	                return this.attrs.gradient;
65147	            }
65148	            if (name == "transform") {
65149	                return this._.transform;
65150	            }
65151	            var names = name.split(separator),
65152	                out = {};
65153	            for (var i = 0, ii = names.length; i < ii; i++) {
65154	                name = names[i];
65155	                if (name in this.attrs) {
65156	                    out[name] = this.attrs[name];
65157	                } else if (R.is(this.paper.customAttributes[name], "function")) {
65158	                    out[name] = this.paper.customAttributes[name].def;
65159	                } else {
65160	                    out[name] = R._availableAttrs[name];
65161	                }
65162	            }
65163	            return ii - 1 ? out : out[names[0]];
65164	        }
65165	        if (value == null && R.is(name, "array")) {
65166	            out = {};
65167	            for (i = 0, ii = name.length; i < ii; i++) {
65168	                out[name[i]] = this.attr(name[i]);
65169	            }
65170	            return out;
65171	        }
65172	        if (value != null) {
65173	            var params = {};
65174	            params[name] = value;
65175	        } else if (name != null && R.is(name, "object")) {
65176	            params = name;
65177	        }
65178	        for (var key in params) {
65179	            eve("raphael.attr." + key + "." + this.id, this, params[key]);
65180	        }
65181	        for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) {
65182	            var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));
65183	            this.attrs[key] = params[key];
65184	            for (var subkey in par) if (par[has](subkey)) {
65185	                params[subkey] = par[subkey];
65186	            }
65187	        }
65188	        setFillAndStroke(this, params);
65189	        return this;
65190	    };
65191	    /*\
65192	     * Element.toFront
65193	     [ method ]
65194	     **
65195	     * Moves the element so it is the closest to the viewer’s eyes, on top of other elements.
65196	     = (object) @Element
65197	    \*/
65198	    elproto.toFront = function () {
65199	        if (this.removed) {
65200	            return this;
65201	        }
65202	        var node = getRealNode(this.node);
65203	        node.parentNode.appendChild(node);
65204	        var svg = this.paper;
65205	        svg.top != this && R._tofront(this, svg);
65206	        return this;
65207	    };
65208	    /*\
65209	     * Element.toBack
65210	     [ method ]
65211	     **
65212	     * Moves the element so it is the furthest from the viewer’s eyes, behind other elements.
65213	     = (object) @Element
65214	    \*/
65215	    elproto.toBack = function () {
65216	        if (this.removed) {
65217	            return this;
65218	        }
65219	        var node = getRealNode(this.node);
65220	        var parentNode = node.parentNode;
65221	        parentNode.insertBefore(node, parentNode.firstChild);
65222	        R._toback(this, this.paper);
65223	        var svg = this.paper;
65224	        return this;
65225	    };
65226	    /*\
65227	     * Element.insertAfter
65228	     [ method ]
65229	     **
65230	     * Inserts current object after the given one.
65231	     = (object) @Element
65232	    \*/
65233	    elproto.insertAfter = function (element) {
65234	        if (this.removed || !element) {
65235	            return this;
65236	        }
65237
65238	        var node = getRealNode(this.node);
65239	        var afterNode = getRealNode(element.node || element[element.length - 1].node);
65240	        if (afterNode.nextSibling) {
65241	            afterNode.parentNode.insertBefore(node, afterNode.nextSibling);
65242	        } else {
65243	            afterNode.parentNode.appendChild(node);
65244	        }
65245	        R._insertafter(this, element, this.paper);
65246	        return this;
65247	    };
65248	    /*\
65249	     * Element.insertBefore
65250	     [ method ]
65251	     **
65252	     * Inserts current object before the given one.
65253	     = (object) @Element
65254	    \*/
65255	    elproto.insertBefore = function (element) {
65256	        if (this.removed || !element) {
65257	            return this;
65258	        }
65259
65260	        var node = getRealNode(this.node);
65261	        var beforeNode = getRealNode(element.node || element[0].node);
65262	        beforeNode.parentNode.insertBefore(node, beforeNode);
65263	        R._insertbefore(this, element, this.paper);
65264	        return this;
65265	    };
65266	    elproto.blur = function (size) {
65267	        // Experimental. No Safari support. Use it on your own risk.
65268	        var t = this;
65269	        if (+size !== 0) {
65270	            var fltr = $("filter"),
65271	                blur = $("feGaussianBlur");
65272	            t.attrs.blur = size;
65273	            fltr.id = R.createUUID();
65274	            $(blur, {stdDeviation: +size || 1.5});
65275	            fltr.appendChild(blur);
65276	            t.paper.defs.appendChild(fltr);
65277	            t._blur = fltr;
65278	            $(t.node, {filter: "url(#" + fltr.id + ")"});
65279	        } else {
65280	            if (t._blur) {
65281	                t._blur.parentNode.removeChild(t._blur);
65282	                delete t._blur;
65283	                delete t.attrs.blur;
65284	            }
65285	            t.node.removeAttribute("filter");
65286	        }
65287	        return t;
65288	    };
65289	    R._engine.circle = function (svg, x, y, r) {
65290	        var el = $("circle");
65291	        svg.canvas && svg.canvas.appendChild(el);
65292	        var res = new Element(el, svg);
65293	        res.attrs = {cx: x, cy: y, r: r, fill: "none", stroke: "#000"};
65294	        res.type = "circle";
65295	        $(el, res.attrs);
65296	        return res;
65297	    };
65298	    R._engine.rect = function (svg, x, y, w, h, r) {
65299	        var el = $("rect");
65300	        svg.canvas && svg.canvas.appendChild(el);
65301	        var res = new Element(el, svg);
65302	        res.attrs = {x: x, y: y, width: w, height: h, rx: r || 0, ry: r || 0, fill: "none", stroke: "#000"};
65303	        res.type = "rect";
65304	        $(el, res.attrs);
65305	        return res;
65306	    };
65307	    R._engine.ellipse = function (svg, x, y, rx, ry) {
65308	        var el = $("ellipse");
65309	        svg.canvas && svg.canvas.appendChild(el);
65310	        var res = new Element(el, svg);
65311	        res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: "none", stroke: "#000"};
65312	        res.type = "ellipse";
65313	        $(el, res.attrs);
65314	        return res;
65315	    };
65316	    R._engine.image = function (svg, src, x, y, w, h) {
65317	        var el = $("image");
65318	        $(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: "none"});
65319	        el.setAttributeNS(xlink, "href", src);
65320	        svg.canvas && svg.canvas.appendChild(el);
65321	        var res = new Element(el, svg);
65322	        res.attrs = {x: x, y: y, width: w, height: h, src: src};
65323	        res.type = "image";
65324	        return res;
65325	    };
65326	    R._engine.text = function (svg, x, y, text) {
65327	        var el = $("text");
65328	        svg.canvas && svg.canvas.appendChild(el);
65329	        var res = new Element(el, svg);
65330	        res.attrs = {
65331	            x: x,
65332	            y: y,
65333	            "text-anchor": "middle",
65334	            text: text,
65335	            "font-family": R._availableAttrs["font-family"],
65336	            "font-size": R._availableAttrs["font-size"],
65337	            stroke: "none",
65338	            fill: "#000"
65339	        };
65340	        res.type = "text";
65341	        setFillAndStroke(res, res.attrs);
65342	        return res;
65343	    };
65344	    R._engine.setSize = function (width, height) {
65345	        this.width = width || this.width;
65346	        this.height = height || this.height;
65347	        this.canvas.setAttribute("width", this.width);
65348	        this.canvas.setAttribute("height", this.height);
65349	        if (this._viewBox) {
65350	            this.setViewBox.apply(this, this._viewBox);
65351	        }
65352	        return this;
65353	    };
65354	    R._engine.create = function () {
65355	        var con = R._getContainer.apply(0, arguments),
65356	            container = con && con.container,
65357	            x = con.x,
65358	            y = con.y,
65359	            width = con.width,
65360	            height = con.height;
65361	        if (!container) {
65362	            throw new Error("SVG container not found.");
65363	        }
65364	        var cnvs = $("svg"),
65365	            css = "overflow:hidden;",
65366	            isFloating;
65367	        x = x || 0;
65368	        y = y || 0;
65369	        width = width || 512;
65370	        height = height || 342;
65371	        $(cnvs, {
65372	            height: height,
65373	            version: 1.1,
65374	            width: width,
65375	            xmlns: "http://www.w3.org/2000/svg",
65376	            "xmlns:xlink": "http://www.w3.org/1999/xlink"
65377	        });
65378	        if (container == 1) {
65379	            cnvs.style.cssText = css + "position:absolute;left:" + x + "px;top:" + y + "px";
65380	            R._g.doc.body.appendChild(cnvs);
65381	            isFloating = 1;
65382	        } else {
65383	            cnvs.style.cssText = css + "position:relative";
65384	            if (container.firstChild) {
65385	                container.insertBefore(cnvs, container.firstChild);
65386	            } else {
65387	                container.appendChild(cnvs);
65388	            }
65389	        }
65390	        container = new R._Paper;
65391	        container.width = width;
65392	        container.height = height;
65393	        container.canvas = cnvs;
65394	        container.clear();
65395	        container._left = container._top = 0;
65396	        isFloating && (container.renderfix = function () {});
65397	        container.renderfix();
65398	        return container;
65399	    };
65400	    R._engine.setViewBox = function (x, y, w, h, fit) {
65401	        eve("raphael.setViewBox", this, this._viewBox, [x, y, w, h, fit]);
65402	        var paperSize = this.getSize(),
65403	            size = mmax(w / paperSize.width, h / paperSize.height),
65404	            top = this.top,
65405	            aspectRatio = fit ? "xMidYMid meet" : "xMinYMin",
65406	            vb,
65407	            sw;
65408	        if (x == null) {
65409	            if (this._vbSize) {
65410	                size = 1;
65411	            }
65412	            delete this._vbSize;
65413	            vb = "0 0 " + this.width + S + this.height;
65414	        } else {
65415	            this._vbSize = size;
65416	            vb = x + S + y + S + w + S + h;
65417	        }
65418	        $(this.canvas, {
65419	            viewBox: vb,
65420	            preserveAspectRatio: aspectRatio
65421	        });
65422	        while (size && top) {
65423	            sw = "stroke-width" in top.attrs ? top.attrs["stroke-width"] : 1;
65424	            top.attr({"stroke-width": sw});
65425	            top._.dirty = 1;
65426	            top._.dirtyT = 1;
65427	            top = top.prev;
65428	        }
65429	        this._viewBox = [x, y, w, h, !!fit];
65430	        return this;
65431	    };
65432	    /*\
65433	     * Paper.renderfix
65434	     [ method ]
65435	     **
65436	     * Fixes the issue of Firefox and IE9 regarding subpixel rendering. If paper is dependent
65437	     * on other elements after reflow it could shift half pixel which cause for lines to lost their crispness.
65438	     * This method fixes the issue.
65439	     **
65440	       Special thanks to Mariusz Nowak (http://www.medikoo.com/) for this method.
65441	    \*/
65442	    R.prototype.renderfix = function () {
65443	        var cnvs = this.canvas,
65444	            s = cnvs.style,
65445	            pos;
65446	        try {
65447	            pos = cnvs.getScreenCTM() || cnvs.createSVGMatrix();
65448	        } catch (e) {
65449	            pos = cnvs.createSVGMatrix();
65450	        }
65451	        var left = -pos.e % 1,
65452	            top = -pos.f % 1;
65453	        if (left || top) {
65454	            if (left) {
65455	                this._left = (this._left + left) % 1;
65456	                s.left = this._left + "px";
65457	            }
65458	            if (top) {
65459	                this._top = (this._top + top) % 1;
65460	                s.top = this._top + "px";
65461	            }
65462	        }
65463	    };
65464	    /*\
65465	     * Paper.clear
65466	     [ method ]
65467	     **
65468	     * Clears the paper, i.e. removes all the elements.
65469	    \*/
65470	    R.prototype.clear = function () {
65471	        R.eve("raphael.clear", this);
65472	        var c = this.canvas;
65473	        while (c.firstChild) {
65474	            c.removeChild(c.firstChild);
65475	        }
65476	        this.bottom = this.top = null;
65477	        (this.desc = $("desc")).appendChild(R._g.doc.createTextNode("Created with Rapha\xebl " + R.version));
65478	        c.appendChild(this.desc);
65479	        c.appendChild(this.defs = $("defs"));
65480	    };
65481	    /*\
65482	     * Paper.remove
65483	     [ method ]
65484	     **
65485	     * Removes the paper from the DOM.
65486	    \*/
65487	    R.prototype.remove = function () {
65488	        eve("raphael.remove", this);
65489	        this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);
65490	        for (var i in this) {
65491	            this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null;
65492	        }
65493	    };
65494	    var setproto = R.st;
65495	    for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {
65496	        setproto[method] = (function (methodname) {
65497	            return function () {
65498	                var arg = arguments;
65499	                return this.forEach(function (el) {
65500	                    el[methodname].apply(el, arg);
65501	                });
65502	            };
65503	        })(method);
65504	    }
65505	}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
65506
65507
65508/***/ },
65509/* 4 */
65510/***/ function(module, exports, __webpack_require__) {
65511
65512	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1)], __WEBPACK_AMD_DEFINE_RESULT__ = function(R) {
65513	    if (R && !R.vml) {
65514	        return;
65515	    }
65516
65517	    var has = "hasOwnProperty",
65518	        Str = String,
65519	        toFloat = parseFloat,
65520	        math = Math,
65521	        round = math.round,
65522	        mmax = math.max,
65523	        mmin = math.min,
65524	        abs = math.abs,
65525	        fillString = "fill",
65526	        separator = /[, ]+/,
65527	        eve = R.eve,
65528	        ms = " progid:DXImageTransform.Microsoft",
65529	        S = " ",
65530	        E = "",
65531	        map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"},
65532	        bites = /([clmz]),?([^clmz]*)/gi,
65533	        blurregexp = / progid:\S+Blur\([^\)]+\)/g,
65534	        val = /-?[^,\s-]+/g,
65535	        cssDot = "position:absolute;left:0;top:0;width:1px;height:1px;behavior:url(#default#VML)",
65536	        zoom = 21600,
65537	        pathTypes = {path: 1, rect: 1, image: 1},
65538	        ovalTypes = {circle: 1, ellipse: 1},
65539	        path2vml = function (path) {
65540	            var total =  /[ahqstv]/ig,
65541	                command = R._pathToAbsolute;
65542	            Str(path).match(total) && (command = R._path2curve);
65543	            total = /[clmz]/g;
65544	            if (command == R._pathToAbsolute && !Str(path).match(total)) {
65545	                var res = Str(path).replace(bites, function (all, command, args) {
65546	                    var vals = [],
65547	                        isMove = command.toLowerCase() == "m",
65548	                        res = map[command];
65549	                    args.replace(val, function (value) {
65550	                        if (isMove && vals.length == 2) {
65551	                            res += vals + map[command == "m" ? "l" : "L"];
65552	                            vals = [];
65553	                        }
65554	                        vals.push(round(value * zoom));
65555	                    });
65556	                    return res + vals;
65557	                });
65558	                return res;
65559	            }
65560	            var pa = command(path), p, r;
65561	            res = [];
65562	            for (var i = 0, ii = pa.length; i < ii; i++) {
65563	                p = pa[i];
65564	                r = pa[i][0].toLowerCase();
65565	                r == "z" && (r = "x");
65566	                for (var j = 1, jj = p.length; j < jj; j++) {
65567	                    r += round(p[j] * zoom) + (j != jj - 1 ? "," : E);
65568	                }
65569	                res.push(r);
65570	            }
65571	            return res.join(S);
65572	        },
65573	        compensation = function (deg, dx, dy) {
65574	            var m = R.matrix();
65575	            m.rotate(-deg, .5, .5);
65576	            return {
65577	                dx: m.x(dx, dy),
65578	                dy: m.y(dx, dy)
65579	            };
65580	        },
65581	        setCoords = function (p, sx, sy, dx, dy, deg) {
65582	            var _ = p._,
65583	                m = p.matrix,
65584	                fillpos = _.fillpos,
65585	                o = p.node,
65586	                s = o.style,
65587	                y = 1,
65588	                flip = "",
65589	                dxdy,
65590	                kx = zoom / sx,
65591	                ky = zoom / sy;
65592	            s.visibility = "hidden";
65593	            if (!sx || !sy) {
65594	                return;
65595	            }
65596	            o.coordsize = abs(kx) + S + abs(ky);
65597	            s.rotation = deg * (sx * sy < 0 ? -1 : 1);
65598	            if (deg) {
65599	                var c = compensation(deg, dx, dy);
65600	                dx = c.dx;
65601	                dy = c.dy;
65602	            }
65603	            sx < 0 && (flip += "x");
65604	            sy < 0 && (flip += " y") && (y = -1);
65605	            s.flip = flip;
65606	            o.coordorigin = (dx * -kx) + S + (dy * -ky);
65607	            if (fillpos || _.fillsize) {
65608	                var fill = o.getElementsByTagName(fillString);
65609	                fill = fill && fill[0];
65610	                o.removeChild(fill);
65611	                if (fillpos) {
65612	                    c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1]));
65613	                    fill.position = c.dx * y + S + c.dy * y;
65614	                }
65615	                if (_.fillsize) {
65616	                    fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy);
65617	                }
65618	                o.appendChild(fill);
65619	            }
65620	            s.visibility = "visible";
65621	        };
65622	    R.toString = function () {
65623	        return  "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version;
65624	    };
65625	    var addArrow = function (o, value, isEnd) {
65626	        var values = Str(value).toLowerCase().split("-"),
65627	            se = isEnd ? "end" : "start",
65628	            i = values.length,
65629	            type = "classic",
65630	            w = "medium",
65631	            h = "medium";
65632	        while (i--) {
65633	            switch (values[i]) {
65634	                case "block":
65635	                case "classic":
65636	                case "oval":
65637	                case "diamond":
65638	                case "open":
65639	                case "none":
65640	                    type = values[i];
65641	                    break;
65642	                case "wide":
65643	                case "narrow": h = values[i]; break;
65644	                case "long":
65645	                case "short": w = values[i]; break;
65646	            }
65647	        }
65648	        var stroke = o.node.getElementsByTagName("stroke")[0];
65649	        stroke[se + "arrow"] = type;
65650	        stroke[se + "arrowlength"] = w;
65651	        stroke[se + "arrowwidth"] = h;
65652	    },
65653	    setFillAndStroke = function (o, params) {
65654	        // o.paper.canvas.style.display = "none";
65655	        o.attrs = o.attrs || {};
65656	        var node = o.node,
65657	            a = o.attrs,
65658	            s = node.style,
65659	            xy,
65660	            newpath = pathTypes[o.type] && (params.x != a.x || params.y != a.y || params.width != a.width || params.height != a.height || params.cx != a.cx || params.cy != a.cy || params.rx != a.rx || params.ry != a.ry || params.r != a.r),
65661	            isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry),
65662	            res = o;
65663
65664
65665	        for (var par in params) if (params[has](par)) {
65666	            a[par] = params[par];
65667	        }
65668	        if (newpath) {
65669	            a.path = R._getPath[o.type](o);
65670	            o._.dirty = 1;
65671	        }
65672	        params.href && (node.href = params.href);
65673	        params.title && (node.title = params.title);
65674	        params.target && (node.target = params.target);
65675	        params.cursor && (s.cursor = params.cursor);
65676	        "blur" in params && o.blur(params.blur);
65677	        if (params.path && o.type == "path" || newpath) {
65678	            node.path = path2vml(~Str(a.path).toLowerCase().indexOf("r") ? R._pathToAbsolute(a.path) : a.path);
65679	            o._.dirty = 1;
65680	            if (o.type == "image") {
65681	                o._.fillpos = [a.x, a.y];
65682	                o._.fillsize = [a.width, a.height];
65683	                setCoords(o, 1, 1, 0, 0, 0);
65684	            }
65685	        }
65686	        "transform" in params && o.transform(params.transform);
65687	        if (isOval) {
65688	            var cx = +a.cx,
65689	                cy = +a.cy,
65690	                rx = +a.rx || +a.r || 0,
65691	                ry = +a.ry || +a.r || 0;
65692	            node.path = R.format("ar{0},{1},{2},{3},{4},{1},{4},{1}x", round((cx - rx) * zoom), round((cy - ry) * zoom), round((cx + rx) * zoom), round((cy + ry) * zoom), round(cx * zoom));
65693	            o._.dirty = 1;
65694	        }
65695	        if ("clip-rect" in params) {
65696	            var rect = Str(params["clip-rect"]).split(separator);
65697	            if (rect.length == 4) {
65698	                rect[2] = +rect[2] + (+rect[0]);
65699	                rect[3] = +rect[3] + (+rect[1]);
65700	                var div = node.clipRect || R._g.doc.createElement("div"),
65701	                    dstyle = div.style;
65702	                dstyle.clip = R.format("rect({1}px {2}px {3}px {0}px)", rect);
65703	                if (!node.clipRect) {
65704	                    dstyle.position = "absolute";
65705	                    dstyle.top = 0;
65706	                    dstyle.left = 0;
65707	                    dstyle.width = o.paper.width + "px";
65708	                    dstyle.height = o.paper.height + "px";
65709	                    node.parentNode.insertBefore(div, node);
65710	                    div.appendChild(node);
65711	                    node.clipRect = div;
65712	                }
65713	            }
65714	            if (!params["clip-rect"]) {
65715	                node.clipRect && (node.clipRect.style.clip = "auto");
65716	            }
65717	        }
65718	        if (o.textpath) {
65719	            var textpathStyle = o.textpath.style;
65720	            params.font && (textpathStyle.font = params.font);
65721	            params["font-family"] && (textpathStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g, E) + '"');
65722	            params["font-size"] && (textpathStyle.fontSize = params["font-size"]);
65723	            params["font-weight"] && (textpathStyle.fontWeight = params["font-weight"]);
65724	            params["font-style"] && (textpathStyle.fontStyle = params["font-style"]);
65725	        }
65726	        if ("arrow-start" in params) {
65727	            addArrow(res, params["arrow-start"]);
65728	        }
65729	        if ("arrow-end" in params) {
65730	            addArrow(res, params["arrow-end"], 1);
65731	        }
65732	        if (params.opacity != null ||
65733	            params.fill != null ||
65734	            params.src != null ||
65735	            params.stroke != null ||
65736	            params["stroke-width"] != null ||
65737	            params["stroke-opacity"] != null ||
65738	            params["fill-opacity"] != null ||
65739	            params["stroke-dasharray"] != null ||
65740	            params["stroke-miterlimit"] != null ||
65741	            params["stroke-linejoin"] != null ||
65742	            params["stroke-linecap"] != null) {
65743	            var fill = node.getElementsByTagName(fillString),
65744	                newfill = false;
65745	            fill = fill && fill[0];
65746	            !fill && (newfill = fill = createNode(fillString));
65747	            if (o.type == "image" && params.src) {
65748	                fill.src = params.src;
65749	            }
65750	            params.fill && (fill.on = true);
65751	            if (fill.on == null || params.fill == "none" || params.fill === null) {
65752	                fill.on = false;
65753	            }
65754	            if (fill.on && params.fill) {
65755	                var isURL = Str(params.fill).match(R._ISURL);
65756	                if (isURL) {
65757	                    fill.parentNode == node && node.removeChild(fill);
65758	                    fill.rotate = true;
65759	                    fill.src = isURL[1];
65760	                    fill.type = "tile";
65761	                    var bbox = o.getBBox(1);
65762	                    fill.position = bbox.x + S + bbox.y;
65763	                    o._.fillpos = [bbox.x, bbox.y];
65764
65765	                    R._preload(isURL[1], function () {
65766	                        o._.fillsize = [this.offsetWidth, this.offsetHeight];
65767	                    });
65768	                } else {
65769	                    fill.color = R.getRGB(params.fill).hex;
65770	                    fill.src = E;
65771	                    fill.type = "solid";
65772	                    if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != "r") && addGradientFill(res, params.fill, fill)) {
65773	                        a.fill = "none";
65774	                        a.gradient = params.fill;
65775	                        fill.rotate = false;
65776	                    }
65777	                }
65778	            }
65779	            if ("fill-opacity" in params || "opacity" in params) {
65780	                var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1);
65781	                opacity = mmin(mmax(opacity, 0), 1);
65782	                fill.opacity = opacity;
65783	                if (fill.src) {
65784	                    fill.color = "none";
65785	                }
65786	            }
65787	            node.appendChild(fill);
65788	            var stroke = (node.getElementsByTagName("stroke") && node.getElementsByTagName("stroke")[0]),
65789	            newstroke = false;
65790	            !stroke && (newstroke = stroke = createNode("stroke"));
65791	            if ((params.stroke && params.stroke != "none") ||
65792	                params["stroke-width"] ||
65793	                params["stroke-opacity"] != null ||
65794	                params["stroke-dasharray"] ||
65795	                params["stroke-miterlimit"] ||
65796	                params["stroke-linejoin"] ||
65797	                params["stroke-linecap"]) {
65798	                stroke.on = true;
65799	            }
65800	            (params.stroke == "none" || params.stroke === null || stroke.on == null || params.stroke == 0 || params["stroke-width"] == 0) && (stroke.on = false);
65801	            var strokeColor = R.getRGB(params.stroke);
65802	            stroke.on && params.stroke && (stroke.color = strokeColor.hex);
65803	            opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1);
65804	            var width = (toFloat(params["stroke-width"]) || 1) * .75;
65805	            opacity = mmin(mmax(opacity, 0), 1);
65806	            params["stroke-width"] == null && (width = a["stroke-width"]);
65807	            params["stroke-width"] && (stroke.weight = width);
65808	            width && width < 1 && (opacity *= width) && (stroke.weight = 1);
65809	            stroke.opacity = opacity;
65810
65811	            params["stroke-linejoin"] && (stroke.joinstyle = params["stroke-linejoin"] || "miter");
65812	            stroke.miterlimit = params["stroke-miterlimit"] || 8;
65813	            params["stroke-linecap"] && (stroke.endcap = params["stroke-linecap"] == "butt" ? "flat" : params["stroke-linecap"] == "square" ? "square" : "round");
65814	            if ("stroke-dasharray" in params) {
65815	                var dasharray = {
65816	                    "-": "shortdash",
65817	                    ".": "shortdot",
65818	                    "-.": "shortdashdot",
65819	                    "-..": "shortdashdotdot",
65820	                    ". ": "dot",
65821	                    "- ": "dash",
65822	                    "--": "longdash",
65823	                    "- .": "dashdot",
65824	                    "--.": "longdashdot",
65825	                    "--..": "longdashdotdot"
65826	                };
65827	                stroke.dashstyle = dasharray[has](params["stroke-dasharray"]) ? dasharray[params["stroke-dasharray"]] : E;
65828	            }
65829	            newstroke && node.appendChild(stroke);
65830	        }
65831	        if (res.type == "text") {
65832	            res.paper.canvas.style.display = E;
65833	            var span = res.paper.span,
65834	                m = 100,
65835	                fontSize = a.font && a.font.match(/\d+(?:\.\d*)?(?=px)/);
65836	            s = span.style;
65837	            a.font && (s.font = a.font);
65838	            a["font-family"] && (s.fontFamily = a["font-family"]);
65839	            a["font-weight"] && (s.fontWeight = a["font-weight"]);
65840	            a["font-style"] && (s.fontStyle = a["font-style"]);
65841	            fontSize = toFloat(a["font-size"] || fontSize && fontSize[0]) || 10;
65842	            s.fontSize = fontSize * m + "px";
65843	            res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/</g, "&#60;").replace(/&/g, "&#38;").replace(/\n/g, "<br>"));
65844	            var brect = span.getBoundingClientRect();
65845	            res.W = a.w = (brect.right - brect.left) / m;
65846	            res.H = a.h = (brect.bottom - brect.top) / m;
65847	            // res.paper.canvas.style.display = "none";
65848	            res.X = a.x;
65849	            res.Y = a.y + res.H / 2;
65850
65851	            ("x" in params || "y" in params) && (res.path.v = R.format("m{0},{1}l{2},{1}
65851", round(a.x * zoom), round(a.y * zoom), round(a.x * zoom) + 1));
65852	            var dirtyattrs = ["x", "y", "text", "font", "font-family", "font-weight", "font-style", "font-size"];
65853	            for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) {
65854	                res._.dirty = 1;
65855	                break;
65856	            }
65857
65858	            // text-anchor emulation
65859	            switch (a["text-anchor"]) {
65860	                case "start":
65861	                    res.textpath.style["v-text-align"] = "left";
65862	                    res.bbx = res.W / 2;
65863	                break;
65864	                case "end":
65865	                    res.textpath.style["v-text-align"] = "right";
65866	                    res.bbx = -res.W / 2;
65867	                break;
65868	                default:
65869	                    res.textpath.style["v-text-align"] = "center";
65870	                    res.bbx = 0;
65871	                break;
65872	            }
65873	            res.textpath.style["v-text-kern"] = true;
65874	        }
65875	        // res.paper.canvas.style.display = E;
65876	    },
65877	    addGradientFill = function (o, gradient, fill) {
65878	        o.attrs = o.attrs || {};
65879	        var attrs = o.attrs,
65880	            pow = Math.pow,
65881	            opacity,
65882	            oindex,
65883	            type = "linear",
65884	            fxfy = ".5 .5";
65885	        o.attrs.gradient = gradient;
65886	        gradient = Str(gradient).replace(R._radial_gradient, function (all, fx, fy) {
65887	            type = "radial";
65888	            if (fx && fy) {
65889	                fx = toFloat(fx);
65890	                fy = toFloat(fy);
65891	                pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5);
65892	                fxfy = fx + S + fy;
65893	            }
65894	            return E;
65895	        });
65896	        gradient = gradient.split(/\s*\-\s*/);
65897	        if (type == "linear") {
65898	            var angle = gradient.shift();
65899	            angle = -toFloat(angle);
65900	            if (isNaN(angle)) {
65901	                return null;
65902	            }
65903	        }
65904	        var dots = R._parseDots(gradient);
65905	        if (!dots) {
65906	            return null;
65907	        }
65908	        o = o.shape || o.node;
65909	        if (dots.length) {
65910	            o.removeChild(fill);
65911	            fill.on = true;
65912	            fill.method = "none";
65913	            fill.color = dots[0].color;
65914	            fill.color2 = dots[dots.length - 1].color;
65915	            var clrs = [];
65916	            for (var i = 0, ii = dots.length; i < ii; i++) {
65917	                dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color);
65918	            }
65919	            fill.colors = clrs.length ? clrs.join() : "0% " + fill.color;
65920	            if (type == "radial") {
65921	                fill.type = "gradientTitle";
65922	                fill.focus = "100%";
65923	                fill.focussize = "0 0";
65924	                fill.focusposition = fxfy;
65925	                fill.angle = 0;
65926	            } else {
65927	                // fill.rotate= true;
65928	                fill.type = "gradient";
65929	                fill.angle = (270 - angle) % 360;
65930	            }
65931	            o.appendChild(fill);
65932	        }
65933	        return 1;
65934	    },
65935	    Element = function (node, vml) {
65936	        this[0] = this.node = node;
65937	        node.raphael = true;
65938	        this.id = R._oid++;
65939	        node.raphaelid = this.id;
65940	        this.X = 0;
65941	        this.Y = 0;
65942	        this.attrs = {};
65943	        this.paper = vml;
65944	        this.matrix = R.matrix();
65945	        this._ = {
65946	            transform: [],
65947	            sx: 1,
65948	            sy: 1,
65949	            dx: 0,
65950	            dy: 0,
65951	            deg: 0,
65952	            dirty: 1,
65953	            dirtyT: 1
65954	        };
65955	        !vml.bottom && (vml.bottom = this);
65956	        this.prev = vml.top;
65957	        vml.top && (vml.top.next = this);
65958	        vml.top = this;
65959	        this.next = null;
65960	    };
65961	    var elproto = R.el;
65962
65963	    Element.prototype = elproto;
65964	    elproto.constructor = Element;
65965	    elproto.transform = function (tstr) {
65966	        if (tstr == null) {
65967	            return this._.transform;
65968	        }
65969	        var vbs = this.paper._viewBoxShift,
65970	            vbt = vbs ? "s" + [vbs.scale, vbs.scale] + "-1-1t" + [vbs.dx, vbs.dy] : E,
65971	            oldt;
65972	        if (vbs) {
65973	            oldt = tstr = Str(tstr).replace(/\.{3}|\u2026/g, this._.transform || E);
65974	        }
65975	        R._extractTransform(this, vbt + tstr);
65976	        var matrix = this.matrix.clone(),
65977	            skew = this.skew,
65978	            o = this.node,
65979	            split,
65980	            isGrad = ~Str(this.attrs.fill).indexOf("-"),
65981	            isPatt = !Str(this.attrs.fill).indexOf("url(");
65982	        matrix.translate(1, 1);
65983	        if (isPatt || isGrad || this.type == "image") {
65984	            skew.matrix = "1 0 0 1";
65985	            skew.offset = "0 0";
65986	            split = matrix.split();
65987	            if ((isGrad && split.noRotation) || !split.isSimple) {
65988	                o.style.filter = matrix.toFilter();
65989	                var bb = this.getBBox(),
65990	                    bbt = this.getBBox(1),
65991	                    dx = bb.x - bbt.x,
65992	                    dy = bb.y - bbt.y;
65993	                o.coordorigin = (dx * -zoom) + S + (dy * -zoom);
65994	                setCoords(this, 1, 1, dx, dy, 0);
65995	            } else {
65996	                o.style.filter = E;
65997	                setCoords(this, split.scalex, split.scaley, split.dx, split.dy, split.rotate);
65998	            }
65999	        } else {
66000	            o.style.filter = E;
66001	            skew.matrix = Str(matrix);
66002	            skew.offset = matrix.offset();
66003	        }
66004	        if (oldt !== null) { // empty string value is true as well
66005	            this._.transform = oldt;
66006	            R._extractTransform(this, oldt);
66007	        }
66008	        return this;
66009	    };
66010	    elproto.rotate = function (deg, cx, cy) {
66011	        if (this.removed) {
66012	            return this;
66013	        }
66014	        if (deg == null) {
66015	            return;
66016	        }
66017	        deg = Str(deg).split(separator);
66018	        if (deg.length - 1) {
66019	            cx = toFloat(deg[1]);
66020	            cy = toFloat(deg[2]);
66021	        }
66022	        deg = toFloat(deg[0]);
66023	        (cy == null) && (cx = cy);
66024	        if (cx == null || cy == null) {
66025	            var bbox = this.getBBox(1);
66026	            cx = bbox.x + bbox.width / 2;
66027	            cy = bbox.y + bbox.height / 2;
66028	        }
66029	        this._.dirtyT = 1;
66030	        this.transform(this._.transform.concat([["r", deg, cx, cy]]));
66031	        return this;
66032	    };
66033	    elproto.translate = function (dx, dy) {
66034	        if (this.removed) {
66035	            return this;
66036	        }
66037	        dx = Str(dx).split(separator);
66038	        if (dx.length - 1) {
66039	            dy = toFloat(dx[1]);
66040	        }
66041	        dx = toFloat(dx[0]) || 0;
66042	        dy = +dy || 0;
66043	        if (this._.bbox) {
66044	            this._.bbox.x += dx;
66045	            this._.bbox.y += dy;
66046	        }
66047	        this.transform(this._.transform.concat([["t", dx, dy]]));
66048	        return this;
66049	    };
66050	    elproto.scale = function (sx, sy, cx, cy) {
66051	        if (this.removed) {
66052	            return this;
66053	        }
66054	        sx = Str(sx).split(separator);
66055	        if (sx.length - 1) {
66056	            sy = toFloat(sx[1]);
66057	            cx = toFloat(sx[2]);
66058	            cy = toFloat(sx[3]);
66059	            isNaN(cx) && (cx = null);
66060	            isNaN(cy) && (cy = null);
66061	        }
66062	        sx = toFloat(sx[0]);
66063	        (sy == null) && (sy = sx);
66064	        (cy == null) && (cx = cy);
66065	        if (cx == null || cy == null) {
66066	            var bbox = this.getBBox(1);
66067	        }
66068	        cx = cx == null ? bbox.x + bbox.width / 2 : cx;
66069	        cy = cy == null ? bbox.y + bbox.height / 2 : cy;
66070
66071	        this.transform(this._.transform.concat([["s", sx, sy, cx, cy]]));
66072	        this._.dirtyT = 1;
66073	        return this;
66074	    };
66075	    elproto.hide = function () {
66076	        !this.removed && (this.node.style.display = "none");
66077	        return this;
66078	    };
66079	    elproto.show = function () {
66080	        !this.removed && (this.node.style.display = E);
66081	        return this;
66082	    };
66083	    // Needed to fix the vml setViewBox issues
66084	    elproto.auxGetBBox = R.el.getBBox;
66085	    elproto.getBBox = function(){
66086	      var b = this.auxGetBBox();
66087	      if (this.paper && this.paper._viewBoxShift)
66088	      {
66089	        var c = {};
66090	        var z = 1/this.paper._viewBoxShift.scale;
66091	        c.x = b.x - this.paper._viewBoxShift.dx;
66092	        c.x *= z;
66093	        c.y = b.y - this.paper._viewBoxShift.dy;
66094	        c.y *= z;
66095	        c.width  = b.width  * z;
66096	        c.height = b.height * z;
66097	        c.x2 = c.x + c.width;
66098	        c.y2 = c.y + c.height;
66099	        return c;
66100	      }
66101	      return b;
66102	    };
66103	    elproto._getBBox = function () {
66104	        if (this.removed) {
66105	            return {};
66106	        }
66107	        return {
66108	            x: this.X + (this.bbx || 0) - this.W / 2,
66109	            y: this.Y - this.H,
66110	            width: this.W,
66111	            height: this.H
66112	        };
66113	    };
66114	    elproto.remove = function () {
66115	        if (this.removed || !this.node.parentNode) {
66116	            return;
66117	        }
66118	        this.paper.__set__ && this.paper.__set__.exclude(this);
66119	        R.eve.unbind("raphael.*.*." + this.id);
66120	        R._tear(this, this.paper);
66121	        this.node.parentNode.removeChild(this.node);
66122	        this.shape && this.shape.parentNode.removeChild(this.shape);
66123	        for (var i in this) {
66124	            this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null;
66125	        }
66126	        this.removed = true;
66127	    };
66128	    elproto.attr = function (name, value) {
66129	        if (this.removed) {
66130	            return this;
66131	        }
66132	        if (name == null) {
66133	            var res = {};
66134	            for (var a in this.attrs) if (this.attrs[has](a)) {
66135	                res[a] = this.attrs[a];
66136	            }
66137	            res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
66138	            res.transform = this._.transform;
66139	            return res;
66140	        }
66141	        if (value == null && R.is(name, "string")) {
66142	            if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) {
66143	                return this.attrs.gradient;
66144	            }
66145	            var names = name.split(separator),
66146	                out = {};
66147	            for (var i = 0, ii = names.length; i < ii; i++) {
66148	                name = names[i];
66149	                if (name in this.attrs) {
66150	                    out[name] = this.attrs[name];
66151	                } else if (R.is(this.paper.customAttributes[name], "function")) {
66152	                    out[name] = this.paper.customAttributes[name].def;
66153	                } else {
66154	                    out[name] = R._availableAttrs[name];
66155	                }
66156	            }
66157	            return ii - 1 ? out : out[names[0]];
66158	        }
66159	        if (this.attrs && value == null && R.is(name, "array")) {
66160	            out = {};
66161	            for (i = 0, ii = name.length; i < ii; i++) {
66162	                out[name[i]] = this.attr(name[i]);
66163	            }
66164	            return out;
66165	        }
66166	        var params;
66167	        if (value != null) {
66168	            params = {};
66169	            params[name] = value;
66170	        }
66171	        value == null && R.is(name, "object") && (params = name);
66172	        for (var key in params) {
66173	            eve("raphael.attr." + key + "." + this.id, this, params[key]);
66174	        }
66175	        if (params) {
66176	            for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) {
66177	                var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));
66178	                this.attrs[key] = params[key];
66179	                for (var subkey in par) if (par[has](subkey)) {
66180	                    params[subkey] = par[subkey];
66181	                }
66182	            }
66183	            // this.paper.canvas.style.display = "none";
66184	            if (params.text && this.type == "text") {
66185	                this.textpath.string = params.text;
66186	            }
66187	            setFillAndStroke(this, params);
66188	            // this.paper.canvas.style.display = E;
66189	        }
66190	        return this;
66191	    };
66192	    elproto.toFront = function () {
66193	        !this.removed && this.node.parentNode.appendChild(this.node);
66194	        this.paper && this.paper.top != this && R._tofront(this, this.paper);
66195	        return this;
66196	    };
66197	    elproto.toBack = function () {
66198	        if (this.removed) {
66199	            return this;
66200	        }
66201	        if (this.node.parentNode.firstChild != this.node) {
66202	            this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild);
66203	            R._toback(this, this.paper);
66204	        }
66205	        return this;
66206	    };
66207	    elproto.insertAfter = function (element) {
66208	        if (this.removed) {
66209	            return this;
66210	        }
66211	        if (element.constructor == R.st.constructor) {
66212	            element = element[element.length - 1];
66213	        }
66214	        if (element.node.nextSibling) {
66215	            element.node.parentNode.insertBefore(this.node, element.node.nextSibling);
66216	        } else {
66217	            element.node.parentNode.appendChild(this.node);
66218	        }
66219	        R._insertafter(this, element, this.paper);
66220	        return this;
66221	    };
66222	    elproto.insertBefore = function (element) {
66223	        if (this.removed) {
66224	            return this;
66225	        }
66226	        if (element.constructor == R.st.constructor) {
66227	            element = element[0];
66228	        }
66229	        element.node.parentNode.insertBefore(this.node, element.node);
66230	        R._insertbefore(this, element, this.paper);
66231	        return this;
66232	    };
66233	    elproto.blur = function (size) {
66234	        var s = this.node.runtimeStyle,
66235	            f = s.filter;
66236	        f = f.replace(blurregexp, E);
66237	        if (+size !== 0) {
66238	            this.attrs.blur = size;
66239	            s.filter = f + S + ms + ".Blur(pixelradius=" + (+size || 1.5) + ")";
66240	            s.margin = R.format("-{0}px 0 0 -{0}px", round(+size || 1.5));
66241	        } else {
66242	            s.filter = f;
66243	            s.margin = 0;
66244	            delete this.attrs.blur;
66245	        }
66246	        return this;
66247	    };
66248
66249	    R._engine.path = function (pathString, vml) {
66250	        var el = createNode("shape");
66251	        el.style.cssText = cssDot;
66252	        el.coordsize = zoom + S + zoom;
66253	        el.coordorigin = vml.coordorigin;
66254	        var p = new Element(el, vml),
66255	            attr = {fill: "none", stroke: "#000"};
66256	        pathString && (attr.path = pathString);
66257	        p.type = "path";
66258	        p.path = [];
66259	        p.Path = E;
66260	        setFillAndStroke(p, attr);
66261	        vml.canvas && vml.canvas.appendChild(el);
66262	        var skew = createNode("skew");
66263	        skew.on = true;
66264	        el.appendChild(skew);
66265	        p.skew = skew;
66266	        p.transform(E);
66267	        return p;
66268	    };
66269	    R._engine.rect = function (vml, x, y, w, h, r) {
66270	        var path = R._rectPath(x, y, w, h, r),
66271	            res = vml.path(path),
66272	            a = res.attrs;
66273	        res.X = a.x = x;
66274	        res.Y = a.y = y;
66275	        res.W = a.width = w;
66276	        res.H = a.height = h;
66277	        a.r = r;
66278	        a.path = path;
66279	        res.type = "rect";
66280	        return res;
66281	    };
66282	    R._engine.ellipse = function (vml, x, y, rx, ry) {
66283	        var res = vml.path(),
66284	            a = res.attrs;
66285	        res.X = x - rx;
66286	        res.Y = y - ry;
66287	        res.W = rx * 2;
66288	        res.H = ry * 2;
66289	        res.type = "ellipse";
66290	        setFillAndStroke(res, {
66291	            cx: x,
66292	            cy: y,
66293	            rx: rx,
66294	            ry: ry
66295	        });
66296	        return res;
66297	    };
66298	    R._engine.circle = function (vml, x, y, r) {
66299	        var res = vml.path(),
66300	            a = res.attrs;
66301	        res.X = x - r;
66302	        res.Y = y - r;
66303	        res.W = res.H = r * 2;
66304	        res.type = "circle";
66305	        setFillAndStroke(res, {
66306	            cx: x,
66307	            cy: y,
66308	            r: r
66309	        });
66310	        return res;
66311	    };
66312	    R._engine.image = function (vml, src, x, y, w, h) {
66313	        var path = R._rectPath(x, y, w, h),
66314	            res = vml.path(path).attr({stroke: "none"}),
66315	            a = res.attrs,
66316	            node = res.node,
66317	            fill = node.getElementsByTagName(fillString)[0];
66318	        a.src = src;
66319	        res.X = a.x = x;
66320	        res.Y = a.y = y;
66321	        res.W = a.width = w;
66322	        res.H = a.height = h;
66323	        a.path = path;
66324	        res.type = "image";
66325	        fill.parentNode == node && node.removeChild(fill);
66326	        fill.rotate = true;
66327	        fill.src = src;
66328	        fill.type = "tile";
66329	        res._.fillpos = [x, y];
66330	        res._.fillsize = [w, h];
66331	        node.appendChild(fill);
66332	        setCoords(res, 1, 1, 0, 0, 0);
66333	        return res;
66334	    };
66335	    R._engine.text = function (vml, x, y, text) {
66336	        var el = createNode("shape"),
66337	            path = createNode("path"),
66338	            o = createNode("textpath");
66339	        x = x || 0;
66340	        y = y || 0;
66341	        text = text || "";
66342	        path.v = R.format("m{0},{1}l{2},{1}", round(x * zoom), round(y * zoom), round(x * zoom) + 1);
66343	        path.textpathok = true;
66344	        o.string = Str(text);
66345	        o.on = true;
66346	        el.style.cssText = cssDot;
66347	        el.coordsize = zoom + S + zoom;
66348	        el.coordorigin = "0 0";
66349	        var p = new Element(el, vml),
66350	            attr = {
66351	                fill: "#000",
66352	                stroke: "none",
66353	                font: R._availableAttrs.font,
66354	                text: text
66355	            };
66356	        p.shape = el;
66357	        p.path = path;
66358	        p.textpath = o;
66359	        p.type = "text";
66360	        p.attrs.text = Str(text);
66361	        p.attrs.x = x;
66362	        p.attrs.y = y;
66363	        p.attrs.w = 1;
66364	        p.attrs.h = 1;
66365	        setFillAndStroke(p, attr);
66366	        el.appendChild(o);
66367	        el.appendChild(path);
66368	        vml.canvas.appendChild(el);
66369	        var skew = createNode("skew");
66370	        skew.on = true;
66371	        el.appendChild(skew);
66372	        p.skew = skew;
66373	        p.transform(E);
66374	        return p;
66375	    };
66376	    R._engine.setSize = function (width, height) {
66377	        var cs = this.canvas.style;
66378	        this.width = width;
66379	        this.height = height;
66380	        width == +width && (width += "px");
66381	        height == +height && (height += "px");
66382	        cs.width = width;
66383	        cs.height = height;
66384	        cs.clip = "rect(0 " + width + " " + height + " 0)";
66385	        if (this._viewBox) {
66386	            R._engine.setViewBox.apply(this, this._viewBox);
66387	        }
66388	        return this;
66389	    };
66390	    R._engine.setViewBox = function (x, y, w, h, fit) {
66391	        R.eve("raphael.setViewBox", this, this._viewBox, [x, y, w, h, fit]);
66392	        var paperSize = this.getSize(),
66393	            width = paperSize.width,
66394	            height = paperSize.height,
66395	            H, W;
66396	        if (fit) {
66397	            H = height / h;
66398	            W = width / w;
66399	            if (w * H < width) {
66400	                x -= (width - w * H) / 2 / H;
66401	            }
66402	            if (h * W < height) {
66403	                y -= (height - h * W) / 2 / W;
66404	            }
66405	        }
66406	        this._viewBox = [x, y, w, h, !!fit];
66407	        this._viewBoxShift = {
66408	            dx: -x,
66409	            dy: -y,
66410	            scale: paperSize
66411	        };
66412	        this.forEach(function (el) {
66413	            el.transform("...");
66414	        });
66415	        return this;
66416	    };
66417	    var createNode;
66418	    R._engine.initWin = function (win) {
66419	            var doc = win.document;
66420	            if (doc.styleSheets.length < 31) {
66421	                doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
66422	            } else {
66423	                // no more room, add to the existing one
66424	                // http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx
66425	                doc.styleSheets[0].addRule(".rvml", "behavior:url(#default#VML)");
66426	            }
66427	            try {
66428	                !doc.namespaces.rvml && doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
66429	                createNode = function (tagName) {
66430	                    return doc.createElement('<rvml:' + tagName + ' class="rvml">');
66431	                };
66432	            } catch (e) {
66433	                createNode = function (tagName) {
66434	                    return doc.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
66435	                };
66436	            }
66437	        };
66438	    R._engine.initWin(R._g.win);
66439	    R._engine.create = function () {
66440	        var con = R._getContainer.apply(0, arguments),
66441	            container = con.container,
66442	            height = con.height,
66443	            s,
66444	            width = con.width,
66445	            x = con.x,
66446	            y = con.y;
66447	        if (!container) {
66448	            throw new Error("VML container not found.");
66449	        }
66450	        var res = new R._Paper,
66451	            c = res.canvas = R._g.doc.createElement("div"),
66452	            cs = c.style;
66453	        x = x || 0;
66454	        y = y || 0;
66455	        width = width || 512;
66456	        height = height || 342;
66457	        res.width = width;
66458	        res.height = height;
66459	        width == +width && (width += "px");
66460	        height == +height && (height += "px");
66461	        res.coordsize = zoom * 1e3 + S + zoom * 1e3;
66462	        res.coordorigin = "0 0";
66463	        res.span = R._g.doc.createElement("span");
66464	        res.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;";
66465	        c.appendChild(res.span);
66466	        cs.cssText = R.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden", width, height);
66467	        if (container == 1) {
66468	            R._g.doc.body.appendChild(c);
66469	            cs.left = x + "px";
66470	            cs.top = y + "px";
66471	            cs.position = "absolute";
66472	        } else {
66473	            if (container.firstChild) {
66474	                container.insertBefore(c, container.firstChild);
66475	            } else {
66476	                container.appendChild(c);
66477	            }
66478	        }
66479	        res.renderfix = function () {};
66480	        return res;
66481	    };
66482	    R.prototype.clear = function () {
66483	        R.eve("raphael.clear", this);
66484	        this.canvas.innerHTML = E;
66485	        this.span = R._g.doc.createElement("span");
66486	        this.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";
66487	        this.canvas.appendChild(this.span);
66488	        this.bottom = this.top = null;
66489	    };
66490	    R.prototype.remove = function () {
66491	        R.eve("raphael.remove", this);
66492	        this.canvas.parentNode.removeChild(this.canvas);
66493	        for (var i in this) {
66494	            this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null;
66495	        }
66496	        return true;
66497	    };
66498
66499	    var setproto = R.st;
66500	    for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {
66501	        setproto[method] = (function (methodname) {
66502	            return function () {
66503	                var arg = arguments;
66504	                return this.forEach(function (el) {
66505	                    el[methodname].apply(el, arg);
66506	                });
66507	            };
66508	        })(method);
66509	    }
66510	}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
66511
66512
66513/***/ }
66514/******/ ])
66515});
66516;
66517/* @license
66518morris.js v0.5.0
66519Copyright 2014 Olly Smith All rights reserved.
66520Licensed under the BSD-2-Clause License.
66521*/
66522
66523
66524(function() {
66525  var $, Morris, minutesSpecHelper, secondsSpecHelper,
66526    __slice = [].slice,
66527    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
66528    __hasProp = {}.hasOwnProperty,
66529    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
66530    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
66531
66532  Morris = window.Morris = {};
66533
66534  $ = jQuery;
66535
66536  Morris.EventEmitter = (function() {
66537    function EventEmitter() {}
66538
66539    EventEmitter.prototype.on = function(name, handler) {
66540      if (this.handlers == null) {
66541        this.handlers = {};
66542      }
66543      if (this.handlers[name] == null) {
66544        this.handlers[name] = [];
66545      }
66546      this.handlers[name].push(handler);
66547      return this;
66548    };
66549
66550    EventEmitter.prototype.fire = function() {
66551      var args, handler, name, _i, _len, _ref, _results;
66552      name = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
66553      if ((this.handlers != null) && (this.handlers[name] != null)) {
66554        _ref = this.handlers[name];
66555        _results = [];
66556        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
66557          handler = _ref[_i];
66558          _results.push(handler.apply(null, args));
66559        }
66560        return _results;
66561      }
66562    };
66563
66564    return EventEmitter;
66565
66566  })();
66567
66568  Morris.commas = function(num) {
66569    var absnum, intnum, ret, strabsnum;
66570    if (num != null) {
66571      ret = num < 0 ? "-" : "";
66572      absnum = Math.abs(num);
66573      intnum = Math.floor(absnum).toFixed(0);
66574      ret += intnum.replace(/(?=(?:\d{3})+$)(?!^)/g, ',');
66575      strabsnum = absnum.toString();
66576      if (strabsnum.length > intnum.length) {
66577        ret += strabsnum.slice(intnum.length);
66578      }
66579      return ret;
66580    } else {
66581      return '-';
66582    }
66583  };
66584
66585  Morris.pad2 = function(number) {
66586    return (number < 10 ? '0' : '') + number;
66587  };
66588
66589  Morris.Grid = (function(_super) {
66590    __extends(Grid, _super);
66591
66592    function Grid(options) {
66593      this.resizeHandler = __bind(this.resizeHandler, this);
66594      var _this = this;
66595      if (typeof options.element === 'string') {
66596        this.el = $(document.getElementById(options.element));
66597      } else {
66598        this.el = $(options.element);
66599      }
66600      if ((this.el == null) || this.el.length === 0) {
66601        throw new Error("Graph container element not found");
66602      }
66603      if (this.el.css('position') === 'static') {
66604        this.el.css('position', 'relative');
66605      }
66606      this.options = $.extend({}, this.gridDefaults, this.defaults || {}, options);
66607      if (typeof this.options.units === 'string') {
66608        this.options.postUnits = options.units;
66609      }
66610      this.raphael = new Raphael(this.el[0]);
66611      this.elementWidth = null;
66612      this.elementHeight = null;
66613      this.dirty = false;
66614      this.selectFrom = null;
66615      if (this.init) {
66616        this.init();
66617      }
66618      this.setData(this.options.data);
66619      this.el.bind('mousemove', function(evt) {
66620        var left, offset, right, width, x;
66621        offset = _this.el.offset();
66622        x = evt.pageX - offset.left;
66623        if (_this.selectFrom) {
66624          left = _this.data[_this.hitTest(Math.min(x, _this.selectFrom))]._x;
66625          right = _this.data[_this.hitTest(Math.max(x, _this.selectFrom))]._x;
66626          width = right - left;
66627          return _this.selectionRect.attr({
66628            x: left,
66629            width: width
66630          });
66631        } else {
66632          return _this.fire('hovermove', x, evt.pageY - offset.top);
66633        }
66634      });
66635      this.el.bind('mouseleave', function(evt) {
66636        if (_this.selectFrom) {
66637          _this.selectionRect.hide();
66638          _this.selectFrom = null;
66639        }
66640        return _this.fire('hoverout');
66641      });
66642      this.el.bind('touchstart touchmove touchend', function(evt) {
66643        var offset, touch;
66644        touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0];
66645        offset = _this.el.offset();
66646        return _this.fire('hovermove', touch.pageX - offset.left, touch.pageY - offset.top);
66647      });
66648      this.el.bind('click', function(evt) {
66649        var offset;
66650        offset = _this.el.offset();
66651        return _this.fire('gridclick', evt.pageX - offset.left, evt.pageY - offset.top);
66652      });
66653      if (this.options.rangeSelect) {
66654        this.selectionRect = this.raphael.rect(0, 0, 0, this.el.innerHeight()).attr({
66655          fill: this.options.rangeSelectColor,
66656          stroke: false
66657        }).toBack().hide();
66658        this.el.bind('mousedown', function(evt) {
66659          var offset;
66660          offset = _this.el.offset();
66661          return _this.startRange(evt.pageX - offset.left);
66662        });
66663        this.el.bind('mouseup', function(evt) {
66664          var offset;
66665          offset = _this.el.offset();
66666          _this.endRange(evt.pageX - offset.left);
66667          return _this.fire('hovermove', evt.pageX - offset.left, evt.pageY - offset.top);
66668        });
66669      }
66670      if (this.options.resize) {
66671        $(window).bind('resize', function(evt) {
66672          if (_this.timeoutId != null) {
66673            window.clearTimeout(_this.timeoutId);
66674          }
66675          return _this.timeoutId = window.setTimeout(_this.resizeHandler, 100);
66676        });
66677      }
66678      this.el.css('-webkit-tap-highlight-color', 'rgba(0,0,0,0)');
66679      if (this.postInit) {
66680        this.postInit();
66681      }
66682    }
66683
66684    Grid.prototype.gridDefaults = {
66685      dateFormat: null,
66686      axes: true,
66687      grid: true,
66688      gridLineColor: '#aaa',
66689      gridStrokeWidth: 0.5,
66690      gridTextColor: '#888',
66691      gridTextSize: 12,
66692      gridTextFamily: 'sans-serif',
66693      gridTextWeight: 'normal',
66694      hideHover: false,
66695      yLabelFormat: null,
66696      xLabelAngle: 0,
66697      numLines: 5,
66698      padding: 25,
66699      parseTime: true,
66700      postUnits: '',
66701      preUnits: '',
66702      ymax: 'auto',
66703      ymin: 'auto 0',
66704      goals: [],
66705      goalStrokeWidth: 1.0,
66706      goalLineColors: ['#666633', '#999966', '#cc6666', '#663333'],
66707      events: [],
66708      eventStrokeWidth: 1.0,
66709      eventLineColors: ['#005a04', '#ccffbb', '#3a5f0b', '#005502'],
66710      rangeSelect: null,
66711      rangeSelectColor: '#eef',
66712      resize: false
66713    };
66714
66715    Grid.prototype.setData = function(data, redraw) {
66716      var e, idx, index, maxGoal, minGoal, ret, row, step, total, y, ykey, ymax, ymin, yval, _ref;
66717      if (redraw == null) {
66718        redraw = true;
66719      }
66720      this.options.data = data;
66721      if ((data == null) || data.length === 0) {
66722        this.data = [];
66723        this.raphael.clear();
66724        if (this.hover != null) {
66725          this.hover.hide();
66726        }
66727        return;
66728      }
66729      ymax = this.cumulative ? 0 : null;
66730      ymin = this.cumulative ? 0 : null;
66731      if (this.options.goals.length > 0) {
66732        minGoal = Math.min.apply(Math, this.options.goals);
66733        maxGoal = Math.max.apply(Math, this.options.goals);
66734        ymin = ymin != null ? Math.min(ymin, minGoal) : minGoal;
66735        ymax = ymax != null ? Math.max(ymax, maxGoal) : maxGoal;
66736      }
66737      this.data = (function() {
66738        var _i, _len, _results;
66739        _results = [];
66740        for (index = _i = 0, _len = data.length; _i < _len; index = ++_i) {
66741          row = data[index];
66742          ret = {
66743            src: row
66744          };
66745          ret.label = row[this.options.xkey];
66746          if (this.options.parseTime) {
66747            ret.x = Morris.parseDate(ret.label);
66748            if (this.options.dateFormat) {
66749              ret.label = this.options.dateFormat(ret.x);
66750            } else if (typeof ret.label === 'number') {
66751              ret.label = new Date(ret.label).toString();
66752            }
66753          } else {
66754            ret.x = index;
66755            if (this.options.xLabelFormat) {
66756              ret.label = this.options.xLabelFormat(ret);
66757            }
66758          }
66759          total = 0;
66760          ret.y = (function() {
66761            var _j, _len1, _ref, _results1;
66762            _ref = this.options.ykeys;
66763            _results1 = [];
66764            for (idx = _j = 0, _len1 = _ref.length; _j < _len1; idx = ++_j) {
66765              ykey = _ref[idx];
66766              yval = row[ykey];
66767              if (typeof yval === 'string') {
66768                yval = parseFloat(yval);
66769              }
66770              if ((yval != null) && typeof yval !== 'number') {
66771                yval = null;
66772              }
66773              if (yval != null) {
66774                if (this.cumulative) {
66775                  total += yval;
66776                } else {
66777                  if (ymax != null) {
66778                    ymax = Math.max(yval, ymax);
66779                    ymin = Math.min(yval, ymin);
66780                  } else {
66781                    ymax = ymin = yval;
66782                  }
66783                }
66784              }
66785              if (this.cumulative && (total != null)) {
66786                ymax = Math.max(total, ymax);
66787                ymin = Math.min(total, ymin);
66788              }
66789              _results1.push(yval);
66790            }
66791            return _results1;
66792          }).call(this);
66793          _results.push(ret);
66794        }
66795        return _results;
66796      }).call(this);
66797      if (this.options.parseTime) {
66798        this.data = this.data.sort(function(a, b) {
66799          return (a.x > b.x) - (b.x > a.x);
66800        });
66801      }
66802      this.xmin = this.data[0].x;
66803      this.xmax = this.data[this.data.length - 1].x;
66804      this.events = [];
66805      if (this.options.events.length > 0) {
66806        if (this.options.parseTime) {
66807          this.events = (function() {
66808            var _i, _len, _ref, _results;
66809            _ref = this.options.events;
66810            _results = [];
66811            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
66812              e = _ref[_i];
66813              _results.push(Morris.parseDate(e));
66814            }
66815            return _results;
66816          }).call(this);
66817        } else {
66818          this.events = this.options.events;
66819        }
66820        this.xmax = Math.max(this.xmax, Math.max.apply(Math, this.events));
66821        this.xmin = Math.min(this.xmin, Math.min.apply(Math, this.events));
66822      }
66823      if (this.xmin === this.xmax) {
66824        this.xmin -= 1;
66825        this.xmax += 1;
66826      }
66827      this.ymin = this.yboundary('min', ymin);
66828      this.ymax = this.yboundary('max', ymax);
66829      if (this.ymin === this.ymax) {
66830        if (ymin) {
66831          this.ymin -= 1;
66832        }
66833        this.ymax += 1;
66834      }
66835      if (((_ref = this.options.axes) === true || _ref === 'both' || _ref === 'y') || this.options.grid === true) {
66836        if (this.options.ymax === this.gridDefaults.ymax && this.options.ymin === this.gridDefaults.ymin) {
66837          this.grid = this.autoGridLines(this.ymin, this.ymax, this.options.numLines);
66838          this.ymin = Math.min(this.ymin, this.grid[0]);
66839          this.ymax = Math.max(this.ymax, this.grid[this.grid.length - 1]);
66840        } else {
66841          step = (this.ymax - this.ymin) / (this.options.numLines - 1);
66842          this.grid = (function() {
66843            var _i, _ref1, _ref2, _results;
66844            _results = [];
66845            for (y = _i = _ref1 = this.ymin, _ref2 = this.ymax; step > 0 ? _i <= _ref2 : _i >= _ref2; y = _i += step) {
66846              _results.push(y);
66847            }
66848            return _results;
66849          }).call(this);
66850        }
66851      }
66852      this.dirty = true;
66853      if (redraw) {
66854        return this.redraw();
66855      }
66856    };
66857
66858    Grid.prototype.yboundary = function(boundaryType, currentValue) {
66859      var boundaryOption, suggestedValue;
66860      boundaryOption = this.options["y" + boundaryType];
66861      if (typeof boundaryOption === 'string') {
66862        if (boundaryOption.slice(0, 4) === 'auto') {
66863          if (boundaryOption.length > 5) {
66864            suggestedValue = parseInt(boundaryOption.slice(5), 10);
66865            if (currentValue == null) {
66866              return suggestedValue;
66867            }
66868            return Math[boundaryType](currentValue, suggestedValue);
66869          } else {
66870            if (currentValue != null) {
66871              return currentValue;
66872            } else {
66873              return 0;
66874            }
66875          }
66876        } else {
66877          return parseInt(boundaryOption, 10);
66878        }
66879      } else {
66880        return boundaryOption;
66881      }
66882    };
66883
66884    Grid.prototype.autoGridLines = function(ymin, ymax, nlines) {
66885      var gmax, gmin, grid, smag, span, step, unit, y, ymag;
66886      span = ymax - ymin;
66887      ymag = Math.floor(Math.log(span) / Math.log(10));
66888      unit = Math.pow(10, ymag);
66889      gmin = Math.floor(ymin / unit) * unit;
66890      gmax = Math.ceil(ymax / unit) * unit;
66891      step = (gmax - gmin) / (nlines - 1);
66892      if (unit === 1 && step > 1 && Math.ceil(step) !== step) {
66893        step = Math.ceil(step);
66894        gmax = gmin + step * (nlines - 1);
66895      }
66896      if (gmin < 0 && gmax > 0) {
66897        gmin = Math.floor(ymin / step) * step;
66898        gmax = Math.ceil(ymax / step) * step;
66899      }
66900      if (step < 1) {
66901        smag = Math.floor(Math.log(step) / Math.log(10));
66902        grid = (function() {
66903          var _i, _results;
66904          _results = [];
66905          for (y = _i = gmin; step > 0 ? _i <= gmax : _i >= gmax; y = _i += step) {
66906            _results.push(parseFloat(y.toFixed(1 - smag)));
66907          }
66908          return _results;
66909        })();
66910      } else {
66911        grid = (function() {
66912          var _i, _results;
66913          _results = [];
66914          for (y = _i = gmin; step > 0 ? _i <= gmax : _i >= gmax; y = _i += step) {
66915            _results.push(y);
66916          }
66917          return _results;
66918        })();
66919      }
66920      return grid;
66921    };
66922
66923    Grid.prototype._calc = function() {
66924      var bottomOffsets, gridLine, h, i, w, yLabelWidths, _ref, _ref1;
66925      w = this.el.width();
66926      h = this.el.height();
66927      if (this.elementWidth !== w || this.elementHeight !== h || this.dirty) {
66928        this.elementWidth = w;
66929        this.elementHeight = h;
66930        this.dirty = false;
66931        this.left = this.options.padding;
66932        this.right = this.elementWidth - this.options.padding;
66933        this.top = this.options.padding;
66934        this.bottom = this.elementHeight - this.options.padding;
66935        if ((_ref = this.options.axes) === true || _ref === 'both' || _ref === 'y') {
66936          yLabelWidths = (function() {
66937            var _i, _len, _ref1, _results;
66938            _ref1 = this.grid;
66939            _results = [];
66940            for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
66941              gridLine = _ref1[_i];
66942              _results.push(this.measureText(this.yAxisFormat(gridLine)).width);
66943            }
66944            return _results;
66945          }).call(this);
66946          this.left += Math.max.apply(Math, yLabelWidths);
66947        }
66948        if ((_ref1 = this.options.axes) === true || _ref1 === 'both' || _ref1 === 'x') {
66949          bottomOffsets = (function() {
66950            var _i, _ref2, _results;
66951            _results = [];
66952            for (i = _i = 0, _ref2 = this.data.length; 0 <= _ref2 ? _i < _ref2 : _i > _ref2; i = 0 <= _ref2 ? ++_i : --_i) {
66953              _results.push(this.measureText(this.data[i].text, -this.options.xLabelAngle).height);
66954            }
66955            return _results;
66956          }).call(this);
66957          this.bottom -= Math.max.apply(Math, bottomOffsets);
66958        }
66959        this.width = Math.max(1, this.right - this.left);
66960        this.height = Math.max(1, this.bottom - this.top);
66961        this.dx = this.width / (this.xmax - this.xmin);
66962        this.dy = this.height / (this.ymax - this.ymin);
66963        if (this.calc) {
66964          return this.calc();
66965        }
66966      }
66967    };
66968
66969    Grid.prototype.transY = function(y) {
66970      return this.bottom - (y - this.ymin) * this.dy;
66971    };
66972
66973    Grid.prototype.transX = function(x) {
66974      if (this.data.length === 1) {
66975        return (this.left + this.right) / 2;
66976      } else {
66977        return this.left + (x - this.xmin) * this.dx;
66978      }
66979    };
66980
66981    Grid.prototype.redraw = function() {
66982      this.raphael.clear();
66983      this._calc();
66984      this.drawGrid();
66985      this.drawGoals();
66986      this.drawEvents();
66987      if (this.draw) {
66988        return this.draw();
66989      }
66990    };
66991
66992    Grid.prototype.measureText = function(text, angle) {
66993      var ret, tt;
66994      if (angle == null) {
66995        angle = 0;
66996      }
66997      tt = this.raphael.text(100, 100, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).rotate(angle);
66998      ret = tt.getBBox();
66999      tt.remove();
67000      return ret;
67001    };
67002
67003    Grid.prototype.yAxisFormat = function(label) {
67004      return this.yLabelFormat(label);
67005    };
67006
67007    Grid.prototype.yLabelFormat = function(label) {
67008      if (typeof this.options.yLabelFormat === 'function') {
67009        return this.options.yLabelFormat(label);
67010      } else {
67011        return "" + this.options.preUnits + (Morris.commas(label)) + this.options.postUnits;
67012      }
67013    };
67014
67015    Grid.prototype.drawGrid = function() {
67016      var lineY, y, _i, _len, _ref, _ref1, _ref2, _results;
67017      if (this.options.grid === false && ((_ref = this.options.axes) !== true && _ref !== 'both' && _ref !== 'y')) {
67018        return;
67019      }
67020      _ref1 = this.grid;
67021      _results = [];
67022      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
67023        lineY = _ref1[_i];
67024        y = this.transY(lineY);
67025        if ((_ref2 = this.options.axes) === true || _ref2 === 'both' || _ref2 === 'y') {
67026          this.drawYAxisLabel(this.left - this.options.padding / 2, y, this.yAxisFormat(lineY));
67027        }
67028        if (this.options.grid) {
67029          _results.push(this.drawGridLine("M" + this.left + "," + y + "H" + (this.left + this.width)));
67030        } else {
67031          _results.push(void 0);
67032        }
67033      }
67034      return _results;
67035    };
67036
67037    Grid.prototype.drawGoals = function() {
67038      var color, goal, i, _i, _len, _ref, _results;
67039      _ref = this.options.goals;
67040      _results = [];
67041      for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
67042        goal = _ref[i];
67043        color = this.options.goalLineColors[i % this.options.goalLineColors.length];
67044        _results.push(this.drawGoal(goal, color));
67045      }
67046      return _results;
67047    };
67048
67049    Grid.prototype.drawEvents = function() {
67050      var color, event, i, _i, _len, _ref, _results;
67051      _ref = this.events;
67052      _results = [];
67053      for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
67054        event = _ref[i];
67055        color = this.options.eventLineColors[i % this.options.eventLineColors.length];
67056        _results.push(this.drawEvent(event, color));
67057      }
67058      return _results;
67059    };
67060
67061    Grid.prototype.drawGoal = function(goal, color) {
67062      return this.raphael.path("M" + this.left + "," + (this.transY(goal)) + "H" + this.right).attr('stroke', color).attr('stroke-width', this.options.goalStrokeWidth);
67063    };
67064
67065    Grid.prototype.drawEvent = function(event, color) {
67066      return this.raphael.path("M" + (this.transX(event)) + "," + this.bottom + "V" + this.top).attr('stroke', color).attr('stroke-width', this.options.eventStrokeWidth);
67067    };
67068
67069    Grid.prototype.drawYAxisLabel = function(xPos, yPos, text) {
67070      return this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor).attr('text-anchor', 'end');
67071    };
67072
67073    Grid.prototype.drawGridLine = function(path) {
67074      return this.raphael.path(path).attr('stroke', this.options.gridLineColor).attr('stroke-width', this.options.gridStrokeWidth);
67075    };
67076
67077    Grid.prototype.startRange = function(x) {
67078      this.hover.hide();
67079      this.selectFrom = x;
67080      return this.selectionRect.attr({
67081        x: x,
67082        width: 0
67083      }).show();
67084    };
67085
67086    Grid.prototype.endRange = function(x) {
67087      var end, start;
67088      if (this.selectFrom) {
67089        start = Math.min(this.selectFrom, x);
67090        end = Math.max(this.selectFrom, x);
67091        this.options.rangeSelect.call(this.el, {
67092          start: this.data[this.hitTest(start)].x,
67093          end: this.data[this.hitTest(end)].x
67094        });
67095        return this.selectFrom = null;
67096      }
67097    };
67098
67099    Grid.prototype.resizeHandler = function() {
67100      this.timeoutId = null;
67101      this.raphael.setSize(this.el.width(), this.el.height());
67102      return this.redraw();
67103    };
67104
67105    return Grid;
67106
67107  })(Morris.EventEmitter);
67108
67109  Morris.parseDate = function(date) {
67110    var isecs, m, msecs, n, o, offsetmins, p, q, r, ret, secs;
67111    if (typeof date === 'number') {
67112      return date;
67113    }
67114    m = date.match(/^(\d+) Q(\d)$/);
67115    n = date.match(/^(\d+)-(\d+)$/);
67116    o = date.match(/^(\d+)-(\d+)-(\d+)$/);
67117    p = date.match(/^(\d+) W(\d+)$/);
67118    q = date.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+)(Z|([+-])(\d\d):?(\d\d))?$/);
67119    r = date.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+):(\d+(\.\d+)?)(Z|([+-])(\d\d):?(\d\d))?$/);
67120    if (m) {
67121      return new Date(parseInt(m[1], 10), parseInt(m[2], 10) * 3 - 1, 1).getTime();
67122    } else if (n) {
67123      return new Date(parseInt(n[1], 10), parseInt(n[2], 10) - 1, 1).getTime();
67124    } else if (o) {
67125      return new Date(parseInt(o[1], 10), parseInt(o[2], 10) - 1, parseInt(o[3], 10)).getTime();
67126    } else if (p) {
67127      ret = new Date(parseInt(p[1], 10), 0, 1);
67128      if (ret.getDay() !== 4) {
67129        ret.setMonth(0, 1 + ((4 - ret.getDay()) + 7) % 7);
67130      }
67131      return ret.getTime() + parseInt(p[2], 10) * 604800000;
67132    } else if (q) {
67133      if (!q[6]) {
67134        return new Date(parseInt(q[1], 10), parseInt(q[2], 10) - 1, parseInt(q[3], 10), parseInt(q[4], 10), parseInt(q[5], 10)).getTime();
67135      } else {
67136        offsetmins = 0;
67137        if (q[6] !== 'Z') {
67138          offsetmins = parseInt(q[8], 10) * 60 + parseInt(q[9], 10);
67139          if (q[7] === '+') {
67140            offsetmins = 0 - offsetmins;
67141          }
67142        }
67143        return Date.UTC(parseInt(q[1], 10), parseInt(q[2], 10) - 1, parseInt(q[3], 10), parseInt(q[4], 10), parseInt(q[5], 10) + offsetmins);
67144      }
67145    } else if (r) {
67146      secs = parseFloat(r[6]);
67147      isecs = Math.floor(secs);
67148      msecs = Math.round((secs - isecs) * 1000);
67149      if (!r[8]) {
67150        return new Date(parseInt(r[1], 10), parseInt(r[2], 10) - 1, parseInt(r[3], 10), parseInt(r[4], 10), parseInt(r[5], 10), isecs, msecs).getTime();
67151      } else {
67152        offsetmins = 0;
67153        if (r[8] !== 'Z') {
67154          offsetmins = parseInt(r[10], 10) * 60 + parseInt(r[11], 10);
67155          if (r[9] === '+') {
67156            offsetmins = 0 - offsetmins;
67157          }
67158        }
67159        return Date.UTC(parseInt(r[1], 10), parseInt(r[2], 10) - 1, parseInt(r[3], 10), parseInt(r[4], 10), parseInt(r[5], 10) + offsetmins, isecs, msecs);
67160      }
67161    } else {
67162      return new Date(parseInt(date, 10), 0, 1).getTime();
67163    }
67164  };
67165
67166  Morris.Hover = (function() {
67167    Hover.defaults = {
67168      "class": 'morris-hover morris-default-style'
67169    };
67170
67171    function Hover(options) {
67172      if (options == null) {
67173        options = {};
67174      }
67175      this.options = $.extend({}, Morris.Hover.defaults, options);
67176      this.el = $("<div class='" + this.options["class"] + "'></div>");
67177      this.el.hide();
67178      this.options.parent.append(this.el);
67179    }
67180
67181    Hover.prototype.update = function(html, x, y) {
67182      if (!html) {
67183        return this.hide();
67184      } else {
67185        this.html(html);
67186        this.show();
67187        return this.moveTo(x, y);
67188      }
67189    };
67190
67191    Hover.prototype.html = function(content) {
67192      return this.el.html(content);
67193    };
67194
67195    Hover.prototype.moveTo = function(x, y) {
67196      var hoverHeight, hoverWidth, left, parentHeight, parentWidth, top;
67197      parentWidth = this.options.parent.innerWidth();
67198      parentHeight = this.options.parent.innerHeight();
67199      hoverWidth = this.el.outerWidth();
67200      hoverHeight = this.el.outerHeight();
67201      left = Math.min(Math.max(0, x - hoverWidth / 2), parentWidth - hoverWidth);
67202      if (y != null) {
67203        top = y - hoverHeight - 10;
67204        if (top < 0) {
67205          top = y + 10;
67206          if (top + hoverHeight > parentHeight) {
67207            top = parentHeight / 2 - hoverHeight / 2;
67208          }
67209        }
67210      } else {
67211        top = parentHeight / 2 - hoverHeight / 2;
67212      }
67213      return this.el.css({
67214        left: left + "px",
67215        top: parseInt(top) + "px"
67216      });
67217    };
67218
67219    Hover.prototype.show = function() {
67220      return this.el.show();
67221    };
67222
67223    Hover.prototype.hide = function() {
67224      return this.el.hide();
67225    };
67226
67227    return Hover;
67228
67229  })();
67230
67231  Morris.Line = (function(_super) {
67232    __extends(Line, _super);
67233
67234    function Line(options) {
67235      this.hilight = __bind(this.hilight, this);
67236      this.onHoverOut = __bind(this.onHoverOut, this);
67237      this.onHoverMove = __bind(this.onHoverMove, this);
67238      this.onGridClick = __bind(this.onGridClick, this);
67239      if (!(this instanceof Morris.Line)) {
67240        return new Morris.Line(options);
67241      }
67242      Line.__super__.constructor.call(this, options);
67243    }
67244
67245    Line.prototype.init = function() {
67246      if (this.options.hideHover !== 'always') {
67247        this.hover = new Morris.Hover({
67248          parent: this.el
67249        });
67250        this.on('hovermove', this.onHoverMove);
67251        this.on('hoverout', this.onHoverOut);
67252        return this.on('gridclick', this.onGridClick);
67253      }
67254    };
67255
67256    Line.prototype.defaults = {
67257      lineWidth: 3,
67258      pointSize: 4,
67259      lineColors: ['#0b62a4', '#7A92A3', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'],
67260      pointStrokeWidths: [1],
67261      pointStrokeColors: ['#ffffff'],
67262      pointFillColors: [],
67263      smooth: true,
67264      xLabels: 'auto',
67265      xLabelFormat: null,
67266      xLabelMargin: 24,
67267      hideHover: false
67268    };
67269
67270    Line.prototype.calc = function() {
67271      this.calcPoints();
67272      return this.generatePaths();
67273    };
67274
67275    Line.prototype.calcPoints = function() {
67276      var row, y, _i, _len, _ref, _results;
67277      _ref = this.data;
67278      _results = [];
67279      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
67280        row = _ref[_i];
67281        row._x = this.transX(row.x);
67282        row._y = (function() {
67283          var _j, _len1, _ref1, _results1;
67284          _ref1 = row.y;
67285          _results1 = [];
67286          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
67287            y = _ref1[_j];
67288            if (y != null) {
67289              _results1.push(this.transY(y));
67290            } else {
67291              _results1.push(y);
67292            }
67293          }
67294          return _results1;
67295        }).call(this);
67296        _results.push(row._ymax = Math.min.apply(Math, [this.bottom].concat((function() {
67297          var _j, _len1, _ref1, _results1;
67298          _ref1 = row._y;
67299          _results1 = [];
67300          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
67301            y = _ref1[_j];
67302            if (y != null) {
67303              _results1.push(y);
67304            }
67305          }
67306          return _results1;
67307        })())));
67308      }
67309      return _results;
67310    };
67311
67312    Line.prototype.hitTest = function(x) {
67313      var index, r, _i, _len, _ref;
67314      if (this.data.length === 0) {
67315        return null;
67316      }
67317      _ref = this.data.slice(1);
67318      for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
67319        r = _ref[index];
67320        if (x < (r._x + this.data[index]._x) / 2) {
67321          break;
67322        }
67323      }
67324      return index;
67325    };
67326
67327    Line.prototype.onGridClick = function(x, y) {
67328      var index;
67329      index = this.hitTest(x);
67330      return this.fire('click', index, this.data[index].src, x, y);
67331    };
67332
67333    Line.prototype.onHoverMove = function(x, y) {
67334      var index;
67335      index = this.hitTest(x);
67336      return this.displayHoverForRow(index);
67337    };
67338
67339    Line.prototype.onHoverOut = function() {
67340      if (this.options.hideHover !== false) {
67341        return this.displayHoverForRow(null);
67342      }
67343    };
67344
67345    Line.prototype.displayHoverForRow = function(index) {
67346      var _ref;
67347      if (index != null) {
67348        (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(index));
67349        return this.hilight(index);
67350      } else {
67351        this.hover.hide();
67352        return this.hilight();
67353      }
67354    };
67355
67356    Line.prototype.hoverContentForRow = function(index) {
67357      var content, j, row, y, _i, _len, _ref;
67358      row = this.data[index];
67359      content = "<div class='morris-hover-row-label'>" + row.label + "</div>";
67360      _ref = row.y;
67361      for (j = _i = 0, _len = _ref.length; _i < _len; j = ++_i) {
67362        y = _ref[j];
67363        content += "<div class='morris-hover-point' style='color: " + (this.colorFor(row, j, 'label')) + "'>\n  " + this.options.labels[j] + ":\n  " + (this.yLabelFormat(y)) + "\n</div>";
67364      }
67365      if (typeof this.options.hoverCallback === 'function') {
67366        content = this.options.hoverCallback(index, this.options, content, row.src
67366);
67367      }
67368      return [content, row._x, row._ymax];
67369    };
67370
67371    Line.prototype.generatePaths = function() {
67372      var coords, i, r, smooth;
67373      return this.paths = (function() {
67374        var _i, _ref, _ref1, _results;
67375        _results = [];
67376        for (i = _i = 0, _ref = this.options.ykeys.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
67377          smooth = typeof this.options.smooth === "boolean" ? this.options.smooth : (_ref1 = this.options.ykeys[i], __indexOf.call(this.options.smooth, _ref1) >= 0);
67378          coords = (function() {
67379            var _j, _len, _ref2, _results1;
67380            _ref2 = this.data;
67381            _results1 = [];
67382            for (_j = 0, _len = _ref2.length; _j < _len; _j++) {
67383              r = _ref2[_j];
67384              if (r._y[i] !== void 0) {
67385                _results1.push({
67386                  x: r._x,
67387                  y: r._y[i]
67388                });
67389              }
67390            }
67391            return _results1;
67392          }).call(this);
67393          if (coords.length > 1) {
67394            _results.push(Morris.Line.createPath(coords, smooth, this.bottom));
67395          } else {
67396            _results.push(null);
67397          }
67398        }
67399        return _results;
67400      }).call(this);
67401    };
67402
67403    Line.prototype.draw = function() {
67404      var _ref;
67405      if ((_ref = this.options.axes) === true || _ref === 'both' || _ref === 'x') {
67406        this.drawXAxis();
67407      }
67408      this.drawSeries();
67409      if (this.options.hideHover === false) {
67410        return this.displayHoverForRow(this.data.length - 1);
67411      }
67412    };
67413
67414    Line.prototype.drawXAxis = function() {
67415      var drawLabel, l, labels, prevAngleMargin, prevLabelMargin, row, ypos, _i, _len, _results,
67416        _this = this;
67417      ypos = this.bottom + this.options.padding / 2;
67418      prevLabelMargin = null;
67419      prevAngleMargin = null;
67420      drawLabel = function(labelText, xpos) {
67421        var label, labelBox, margin, offset, textBox;
67422        label = _this.drawXAxisLabel(_this.transX(xpos), ypos, labelText);
67423        textBox = label.getBBox();
67424        label.transform("r" + (-_this.options.xLabelAngle));
67425        labelBox = label.getBBox();
67426        label.transform("t0," + (labelBox.height / 2) + "...");
67427        if (_this.options.xLabelAngle !== 0) {
67428          offset = -0.5 * textBox.width * Math.cos(_this.options.xLabelAngle * Math.PI / 180.0);
67429          label.transform("t" + offset + ",0...");
67430        }
67431        labelBox = label.getBBox();
67432        if (((prevLabelMargin == null) || prevLabelMargin >= labelBox.x + labelBox.width || (prevAngleMargin != null) && prevAngleMargin >= labelBox.x) && labelBox.x >= 0 && (labelBox.x + labelBox.width) < _this.el.width()) {
67433          if (_this.options.xLabelAngle !== 0) {
67434            margin = 1.25 * _this.options.gridTextSize / Math.sin(_this.options.xLabelAngle * Math.PI / 180.0);
67435            prevAngleMargin = labelBox.x - margin;
67436          }
67437          return prevLabelMargin = labelBox.x - _this.options.xLabelMargin;
67438        } else {
67439          return label.remove();
67440        }
67441      };
67442      if (this.options.parseTime) {
67443        if (this.data.length === 1 && this.options.xLabels === 'auto') {
67444          labels = [[this.data[0].label, this.data[0].x]];
67445        } else {
67446          labels = Morris.labelSeries(this.xmin, this.xmax, this.width, this.options.xLabels, this.options.xLabelFormat);
67447        }
67448      } else {
67449        labels = (function() {
67450          var _i, _len, _ref, _results;
67451          _ref = this.data;
67452          _results = [];
67453          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
67454            row = _ref[_i];
67455            _results.push([row.label, row.x]);
67456          }
67457          return _results;
67458        }).call(this);
67459      }
67460      labels.reverse();
67461      _results = [];
67462      for (_i = 0, _len = labels.length; _i < _len; _i++) {
67463        l = labels[_i];
67464        _results.push(drawLabel(l[0], l[1]));
67465      }
67466      return _results;
67467    };
67468
67469    Line.prototype.drawSeries = function() {
67470      var i, _i, _j, _ref, _ref1, _results;
67471      this.seriesPoints = [];
67472      for (i = _i = _ref = this.options.ykeys.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) {
67473        this._drawLineFor(i);
67474      }
67475      _results = [];
67476      for (i = _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; i = _ref1 <= 0 ? ++_j : --_j) {
67477        _results.push(this._drawPointFor(i));
67478      }
67479      return _results;
67480    };
67481
67482    Line.prototype._drawPointFor = function(index) {
67483      var circle, row, _i, _len, _ref, _results;
67484      this.seriesPoints[index] = [];
67485      _ref = this.data;
67486      _results = [];
67487      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
67488        row = _ref[_i];
67489        circle = null;
67490        if (row._y[index] != null) {
67491          circle = this.drawLinePoint(row._x, row._y[index], this.colorFor(row, index, 'point'), index);
67492        }
67493        _results.push(this.seriesPoints[index].push(circle));
67494      }
67495      return _results;
67496    };
67497
67498    Line.prototype._drawLineFor = function(index) {
67499      var path;
67500      path = this.paths[index];
67501      if (path !== null) {
67502        return this.drawLinePath(path, this.colorFor(null, index, 'line'), index);
67503      }
67504    };
67505
67506    Line.createPath = function(coords, smooth, bottom) {
67507      var coord, g, grads, i, ix, lg, path, prevCoord, x1, x2, y1, y2, _i, _len;
67508      path = "";
67509      if (smooth) {
67510        grads = Morris.Line.gradients(coords);
67511      }
67512      prevCoord = {
67513        y: null
67514      };
67515      for (i = _i = 0, _len = coords.length; _i < _len; i = ++_i) {
67516        coord = coords[i];
67517        if (coord.y != null) {
67518          if (prevCoord.y != null) {
67519            if (smooth) {
67520              g = grads[i];
67521              lg = grads[i - 1];
67522              ix = (coord.x - prevCoord.x) / 4;
67523              x1 = prevCoord.x + ix;
67524              y1 = Math.min(bottom, prevCoord.y + ix * lg);
67525              x2 = coord.x - ix;
67526              y2 = Math.min(bottom, coord.y - ix * g);
67527              path += "C" + x1 + "," + y1 + "," + x2 + "," + y2 + "," + coord.x + "," + coord.y;
67528            } else {
67529              path += "L" + coord.x + "," + coord.y;
67530            }
67531          } else {
67532            if (!smooth || (grads[i] != null)) {
67533              path += "M" + coord.x + "," + coord.y;
67534            }
67535          }
67536        }
67537        prevCoord = coord;
67538      }
67539      return path;
67540    };
67541
67542    Line.gradients = function(coords) {
67543      var coord, grad, i, nextCoord, prevCoord, _i, _len, _results;
67544      grad = function(a, b) {
67545        return (a.y - b.y) / (a.x - b.x);
67546      };
67547      _results = [];
67548      for (i = _i = 0, _len = coords.length; _i < _len; i = ++_i) {
67549        coord = coords[i];
67550        if (coord.y != null) {
67551          nextCoord = coords[i + 1] || {
67552            y: null
67553          };
67554          prevCoord = coords[i - 1] || {
67555            y: null
67556          };
67557          if ((prevCoord.y != null) && (nextCoord.y != null)) {
67558            _results.push(grad(prevCoord, nextCoord));
67559          } else if (prevCoord.y != null) {
67560            _results.push(grad(prevCoord, coord));
67561          } else if (nextCoord.y != null) {
67562            _results.push(grad(coord, nextCoord));
67563          } else {
67564            _results.push(null);
67565          }
67566        } else {
67567          _results.push(null);
67568        }
67569      }
67570      return _results;
67571    };
67572
67573    Line.prototype.hilight = function(index) {
67574      var i, _i, _j, _ref, _ref1;
67575      if (this.prevHilight !== null && this.prevHilight !== index) {
67576        for (i = _i = 0, _ref = this.seriesPoints.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) {
67577          if (this.seriesPoints[i][this.prevHilight]) {
67578            this.seriesPoints[i][this.prevHilight].animate(this.pointShrinkSeries(i));
67579          }
67580        }
67581      }
67582      if (index !== null && this.prevHilight !== index) {
67583        for (i = _j = 0, _ref1 = this.seriesPoints.length - 1; 0 <= _ref1 ? _j <= _ref1 : _j >= _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
67584          if (this.seriesPoints[i][index]) {
67585            this.seriesPoints[i][index].animate(this.pointGrowSeries(i));
67586          }
67587        }
67588      }
67589      return this.prevHilight = index;
67590    };
67591
67592    Line.prototype.colorFor = function(row, sidx, type) {
67593      if (typeof this.options.lineColors === 'function') {
67594        return this.options.lineColors.call(this, row, sidx, type);
67595      } else if (type === 'point') {
67596        return this.options.pointFillColors[sidx % this.options.pointFillColors.length] || this.options.lineColors[sidx % this.options.lineColors.length];
67597      } else {
67598        return this.options.lineColors[sidx % this.options.lineColors.length];
67599      }
67600    };
67601
67602    Line.prototype.drawXAxisLabel = function(xPos, yPos, text) {
67603      return this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor);
67604    };
67605
67606    Line.prototype.drawLinePath = function(path, lineColor, lineIndex) {
67607      return this.raphael.path(path).attr('stroke', lineColor).attr('stroke-width', this.lineWidthForSeries(lineIndex));
67608    };
67609
67610    Line.prototype.drawLinePoint = function(xPos, yPos, pointColor, lineIndex) {
67611      return this.raphael.circle(xPos, yPos, this.pointSizeForSeries(lineIndex)).attr('fill', pointColor).attr('stroke-width', this.pointStrokeWidthForSeries(lineIndex)).attr('stroke', this.pointStrokeColorForSeries(lineIndex));
67612    };
67613
67614    Line.prototype.pointStrokeWidthForSeries = function(index) {
67615      return this.options.pointStrokeWidths[index % this.options.pointStrokeWidths.length];
67616    };
67617
67618    Line.prototype.pointStrokeColorForSeries = function(index) {
67619      return this.options.pointStrokeColors[index % this.options.pointStrokeColors.length];
67620    };
67621
67622    Line.prototype.lineWidthForSeries = function(index) {
67623      if (this.options.lineWidth instanceof Array) {
67624        return this.options.lineWidth[index % this.options.lineWidth.length];
67625      } else {
67626        return this.options.lineWidth;
67627      }
67628    };
67629
67630    Line.prototype.pointSizeForSeries = function(index) {
67631      if (this.options.pointSize instanceof Array) {
67632        return this.options.pointSize[index % this.options.pointSize.length];
67633      } else {
67634        return this.options.pointSize;
67635      }
67636    };
67637
67638    Line.prototype.pointGrowSeries = function(index) {
67639      return Raphael.animation({
67640        r: this.pointSizeForSeries(index) + 3
67641      }, 25, 'linear');
67642    };
67643
67644    Line.prototype.pointShrinkSeries = function(index) {
67645      return Raphael.animation({
67646        r: this.pointSizeForSeries(index)
67647      }, 25, 'linear');
67648    };
67649
67650    return Line;
67651
67652  })(Morris.Grid);
67653
67654  Morris.labelSeries = function(dmin, dmax, pxwidth, specName, xLabelFormat) {
67655    var d, d0, ddensity, name, ret, s, spec, t, _i, _len, _ref;
67656    ddensity = 200 * (dmax - dmin) / pxwidth;
67657    d0 = new Date(dmin);
67658    spec = Morris.LABEL_SPECS[specName];
67659    if (spec === void 0) {
67660      _ref = Morris.AUTO_LABEL_ORDER;
67661      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
67662        name = _ref[_i];
67663        s = Morris.LABEL_SPECS[name];
67664        if (ddensity >= s.span) {
67665          spec = s;
67666          break;
67667        }
67668      }
67669    }
67670    if (spec === void 0) {
67671      spec = Morris.LABEL_SPECS["second"];
67672    }
67673    if (xLabelFormat) {
67674      spec = $.extend({}, spec, {
67675        fmt: xLabelFormat
67676      });
67677    }
67678    d = spec.start(d0);
67679    ret = [];
67680    while ((t = d.getTime()) <= dmax) {
67681      if (t >= dmin) {
67682        ret.push([spec.fmt(d), t]);
67683      }
67684      spec.incr(d);
67685    }
67686    return ret;
67687  };
67688
67689  minutesSpecHelper = function(interval) {
67690    return {
67691      span: interval * 60 * 1000,
67692      start: function(d) {
67693        return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours());
67694      },
67695      fmt: function(d) {
67696        return "" + (Morris.pad2(d.getHours())) + ":" + (Morris.pad2(d.getMinutes()));
67697      },
67698      incr: function(d) {
67699        return d.setUTCMinutes(d.getUTCMinutes() + interval);
67700      }
67701    };
67702  };
67703
67704  secondsSpecHelper = function(interval) {
67705    return {
67706      span: interval * 1000,
67707      start: function(d) {
67708        return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes());
67709      },
67710      fmt: function(d) {
67711        return "" + (Morris.pad2(d.getHours())) + ":" + (Morris.pad2(d.getMinutes())) + ":" + (Morris.pad2(d.getSeconds()));
67712      },
67713      incr: function(d) {
67714        return d.setUTCSeconds(d.getUTCSeconds() + interval);
67715      }
67716    };
67717  };
67718
67719  Morris.LABEL_SPECS = {
67720    "decade": {
67721      span: 172800000000,
67722      start: function(d) {
67723        return new Date(d.getFullYear() - d.getFullYear() % 10, 0, 1);
67724      },
67725      fmt: function(d) {
67726        return "" + (d.getFullYear());
67727      },
67728      incr: function(d) {
67729        return d.setFullYear(d.getFullYear() + 10);
67730      }
67731    },
67732    "year": {
67733      span: 17280000000,
67734      start: function(d) {
67735        return new Date(d.getFullYear(), 0, 1);
67736      },
67737      fmt: function(d) {
67738        return "" + (d.getFullYear());
67739      },
67740      incr: function(d) {
67741        return d.setFullYear(d.getFullYear() + 1);
67742      }
67743    },
67744    "month": {
67745      span: 2419200000,
67746      start: function(d) {
67747        return new Date(d.getFullYear(), d.getMonth(), 1);
67748      },
67749      fmt: function(d) {
67750        return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1));
67751      },
67752      incr: function(d) {
67753        return d.setMonth(d.getMonth() + 1);
67754      }
67755    },
67756    "week": {
67757      span: 604800000,
67758      start: function(d) {
67759        return new Date(d.getFullYear(), d.getMonth(), d.getDate());
67760      },
67761      fmt: function(d) {
67762        return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1)) + "-" + (Morris.pad2(d.getDate()));
67763      },
67764      incr: function(d) {
67765        return d.setDate(d.getDate() + 7);
67766      }
67767    },
67768    "day": {
67769      span: 86400000,
67770      start: function(d) {
67771        return new Date(d.getFullYear(), d.getMonth(), d.getDate());
67772      },
67773      fmt: function(d) {
67774        return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1)) + "-" + (Morris.pad2(d.getDate()));
67775      },
67776      incr: function(d) {
67777        return d.setDate(d.getDate() + 1);
67778      }
67779    },
67780    "hour": minutesSpecHelper(60),
67781    "30min": minutesSpecHelper(30),
67782    "15min": minutesSpecHelper(15),
67783    "10min": minutesSpecHelper(10),
67784    "5min": minutesSpecHelper(5),
67785    "minute": minutesSpecHelper(1),
67786    "30sec": secondsSpecHelper(30),
67787    "15sec": secondsSpecHelper(15),
67788    "10sec": secondsSpecHelper(10),
67789    "5sec": secondsSpecHelper(5),
67790    "second": secondsSpecHelper(1)
67791  };
67792
67793  Morris.AUTO_LABEL_ORDER = ["decade", "year", "month", "week", "day", "hour", "30min", "15min", "10min", "5min", "minute", "30sec", "15sec", "10sec", "5sec", "second"];
67794
67795  Morris.Area = (function(_super) {
67796    var areaDefaults;
67797
67798    __extends(Area, _super);
67799
67800    areaDefaults = {
67801      fillOpacity: 'auto',
67802      behaveLikeLine: false
67803    };
67804
67805    function Area(options) {
67806      var areaOptions;
67807      if (!(this instanceof Morris.Area)) {
67808        return new Morris.Area(options);
67809      }
67810      areaOptions = $.extend({}, areaDefaults, options);
67811      this.cumulative = !areaOptions.behaveLikeLine;
67812      if (areaOptions.fillOpacity === 'auto') {
67813        areaOptions.fillOpacity = areaOptions.behaveLikeLine ? .8 : 1;
67814      }
67815      Area.__super__.constructor.call(this, areaOptions);
67816    }
67817
67818    Area.prototype.calcPoints = function() {
67819      var row, total, y, _i, _len, _ref, _results;
67820      _ref = this.data;
67821      _results = [];
67822      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
67823        row = _ref[_i];
67824        row._x = this.transX(row.x);
67825        total = 0;
67826        row._y = (function() {
67827          var _j, _len1, _ref1, _results1;
67828          _ref1 = row.y;
67829          _results1 = [];
67830          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
67831            y = _ref1[_j];
67832            if (this.options.behaveLikeLine) {
67833              _results1.push(this.transY(y));
67834            } else {
67835              total += y || 0;
67836              _results1.push(this.transY(total));
67837            }
67838          }
67839          return _results1;
67840        }).call(this);
67841        _results.push(row._ymax = Math.max.apply(Math, row._y));
67842      }
67843      return _results;
67844    };
67845
67846    Area.prototype.drawSeries = function() {
67847      var i, range, _i, _j, _k, _len, _ref, _ref1, _results, _results1, _results2;
67848      this.seriesPoints = [];
67849      if (this.options.behaveLikeLine) {
67850        range = (function() {
67851          _results = [];
67852          for (var _i = 0, _ref = this.options.ykeys.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); }
67853          return _results;
67854        }).apply(this);
67855      } else {
67856        range = (function() {
67857          _results1 = [];
67858          for (var _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; _ref1 <= 0 ? _j++ : _j--){ _results1.push(_j); }
67859          return _results1;
67860        }).apply(this);
67861      }
67862      _results2 = [];
67863      for (_k = 0, _len = range.length; _k < _len; _k++) {
67864        i = range[_k];
67865        this._drawFillFor(i);
67866        this._drawLineFor(i);
67867        _results2.push(this._drawPointFor(i));
67868      }
67869      return _results2;
67870    };
67871
67872    Area.prototype._drawFillFor = function(index) {
67873      var path;
67874      path = this.paths[index];
67875      if (path !== null) {
67876        path = path + ("L" + (this.transX(this.xmax)) + "," + this.bottom + "L" + (this.transX(this.xmin)) + "," + this.bottom + "Z");
67877        return this.drawFilledPath(path, this.fillForSeries(index));
67878      }
67879    };
67880
67881    Area.prototype.fillForSeries = function(i) {
67882      var color;
67883      color = Raphael.rgb2hsl(this.colorFor(this.data[i], i, 'line'));
67884      return Raphael.hsl(color.h, this.options.behaveLikeLine ? color.s * 0.9 : color.s * 0.75, Math.min(0.98, this.options.behaveLikeLine ? color.l * 1.2 : color.l * 1.25));
67885    };
67886
67887    Area.prototype.drawFilledPath = function(path, fill) {
67888      return this.raphael.path(path).attr('fill', fill).attr('fill-opacity', this.options.fillOpacity).attr('stroke', 'none');
67889    };
67890
67891    return Area;
67892
67893  })(Morris.Line);
67894
67895  Morris.Bar = (function(_super) {
67896    __extends(Bar, _super);
67897
67898    function Bar(options) {
67899      this.onHoverOut = __bind(this.onHoverOut, this);
67900      this.onHoverMove = __bind(this.onHoverMove, this);
67901      this.onGridClick = __bind(this.onGridClick, this);
67902      if (!(this instanceof Morris.Bar)) {
67903        return new Morris.Bar(options);
67904      }
67905      Bar.__super__.constructor.call(this, $.extend({}, options, {
67906        parseTime: false
67907      }));
67908    }
67909
67910    Bar.prototype.init = function() {
67911      this.cumulative = this.options.stacked;
67912      if (this.options.hideHover !== 'always') {
67913        this.hover = new Morris.Hover({
67914          parent: this.el
67915        });
67916        this.on('hovermove', this.onHoverMove);
67917        this.on('hoverout', this.onHoverOut);
67918        return this.on('gridclick', this.onGridClick);
67919      }
67920    };
67921
67922    Bar.prototype.defaults = {
67923      barSizeRatio: 0.75,
67924      barGap: 3,
67925      barColors: ['#0b62a4', '#7a92a3', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'],
67926      barOpacity: 1.0,
67927      barRadius: [0, 0, 0, 0],
67928      xLabelMargin: 50
67929    };
67930
67931    Bar.prototype.calc = function() {
67932      var _ref;
67933      this.calcBars();
67934      if (this.options.hideHover === false) {
67935        return (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(this.data.length - 1));
67936      }
67937    };
67938
67939    Bar.prototype.calcBars = function() {
67940      var idx, row, y, _i, _len, _ref, _results;
67941      _ref = this.data;
67942      _results = [];
67943      for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {
67944        row = _ref[idx];
67945        row._x = this.left + this.width * (idx + 0.5) / this.data.length;
67946        _results.push(row._y = (function() {
67947          var _j, _len1, _ref1, _results1;
67948          _ref1 = row.y;
67949          _results1 = [];
67950          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
67951            y = _ref1[_j];
67952            if (y != null) {
67953              _results1.push(this.transY(y));
67954            } else {
67955              _results1.push(null);
67956            }
67957          }
67958          return _results1;
67959        }).call(this));
67960      }
67961      return _results;
67962    };
67963
67964    Bar.prototype.draw = function() {
67965      var _ref;
67966      if ((_ref = this.options.axes) === true || _ref === 'both' || _ref === 'x') {
67967        this.drawXAxis();
67968      }
67969      return this.drawSeries();
67970    };
67971
67972    Bar.prototype.drawXAxis = function() {
67973      var i, label, labelBox, margin, offset, prevAngleMargin, prevLabelMargin, row, textBox, ypos, _i, _ref, _results;
67974      ypos = this.bottom + (this.options.xAxisLabelTopPadding || this.options.padding / 2);
67975      prevLabelMargin = null;
67976      prevAngleMargin = null;
67977      _results = [];
67978      for (i = _i = 0, _ref = this.data.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
67979        row = this.data[this.data.length - 1 - i];
67980        label = this.drawXAxisLabel(row._x, ypos, row.label);
67981        textBox = label.getBBox();
67982        label.transform("r" + (-this.options.xLabelAngle));
67983        labelBox = label.getBBox();
67984        label.transform("t0," + (labelBox.height / 2) + "...");
67985        if (this.options.xLabelAngle !== 0) {
67986          offset = -0.5 * textBox.width * Math.cos(this.options.xLabelAngle * Math.PI / 180.0);
67987          label.transform("t" + offset + ",0...");
67988        }
67989        if (((prevLabelMargin == null) || prevLabelMargin >= labelBox.x + labelBox.width || (prevAngleMargin != null) && prevAngleMargin >= labelBox.x) && labelBox.x >= 0 && (labelBox.x + labelBox.width) < this.el.width()) {
67990          if (this.options.xLabelAngle !== 0) {
67991            margin = 1.25 * this.options.gridTextSize / Math.sin(this.options.xLabelAngle * Math.PI / 180.0);
67992            prevAngleMargin = labelBox.x - margin;
67993          }
67994          _results.push(prevLabelMargin = labelBox.x - this.options.xLabelMargin);
67995        } else {
67996          _results.push(label.remove());
67997        }
67998      }
67999      return _results;
68000    };
68001
68002    Bar.prototype.drawSeries = function() {
68003      var barWidth, bottom, groupWidth, idx, lastTop, left, leftPadding, numBars, row, sidx, size, space
68003Left, top, ypos, zeroPos;
68004      groupWidth = this.width / this.options.data.length;
68005      numBars = this.options.stacked ? 1 : this.options.ykeys.length;
68006      barWidth = (groupWidth * this.options.barSizeRatio - this.options.barGap * (numBars - 1)) / numBars;
68007      if (this.options.barSize) {
68008        barWidth = Math.min(barWidth, this.options.barSize);
68009      }
68010      spaceLeft = groupWidth - barWidth * numBars - this.options.barGap * (numBars - 1);
68011      leftPadding = spaceLeft / 2;
68012      zeroPos = this.ymin <= 0 && this.ymax >= 0 ? this.transY(0) : null;
68013      return this.bars = (function() {
68014        var _i, _len, _ref, _results;
68015        _ref = this.data;
68016        _results = [];
68017        for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {
68018          row = _ref[idx];
68019          lastTop = 0;
68020          _results.push((function() {
68021            var _j, _len1, _ref1, _results1;
68022            _ref1 = row._y;
68023            _results1 = [];
68024            for (sidx = _j = 0, _len1 = _ref1.length; _j < _len1; sidx = ++_j) {
68025              ypos = _ref1[sidx];
68026              if (ypos !== null) {
68027                if (zeroPos) {
68028                  top = Math.min(ypos, zeroPos);
68029                  bottom = Math.max(ypos, zeroPos);
68030                } else {
68031                  top = ypos;
68032                  bottom = this.bottom;
68033                }
68034                left = this.left + idx * groupWidth + leftPadding;
68035                if (!this.options.stacked) {
68036                  left += sidx * (barWidth + this.options.barGap);
68037                }
68038                size = bottom - top;
68039                if (this.options.verticalGridCondition && this.options.verticalGridCondition(row.x)) {
68040                  this.drawBar(this.left + idx * groupWidth, this.top, groupWidth, Math.abs(this.top - this.bottom), this.options.verticalGridColor, this.options.verticalGridOpacity, this.options.barRadius);
68041                }
68042                if (this.options.stacked) {
68043                  top -= lastTop;
68044                }
68045                this.drawBar(left, top, barWidth, size, this.colorFor(row, sidx, 'bar'), this.options.barOpacity, this.options.barRadius);
68046                _results1.push(lastTop += size);
68047              } else {
68048                _results1.push(null);
68049              }
68050            }
68051            return _results1;
68052          }).call(this));
68053        }
68054        return _results;
68055      }).call(this);
68056    };
68057
68058    Bar.prototype.colorFor = function(row, sidx, type) {
68059      var r, s;
68060      if (typeof this.options.barColors === 'function') {
68061        r = {
68062          x: row.x,
68063          y: row.y[sidx],
68064          label: row.label
68065        };
68066        s = {
68067          index: sidx,
68068          key: this.options.ykeys[sidx],
68069          label: this.options.labels[sidx]
68070        };
68071        return this.options.barColors.call(this, r, s, type);
68072      } else {
68073        return this.options.barColors[sidx % this.options.barColors.length];
68074      }
68075    };
68076
68077    Bar.prototype.hitTest = function(x) {
68078      if (this.data.length === 0) {
68079        return null;
68080      }
68081      x = Math.max(Math.min(x, this.right), this.left);
68082      return Math.min(this.data.length - 1, Math.floor((x - this.left) / (this.width / this.data.length)));
68083    };
68084
68085    Bar.prototype.onGridClick = function(x, y) {
68086      var index;
68087      index = this.hitTest(x);
68088      return this.fire('click', index, this.data[index].src, x, y);
68089    };
68090
68091    Bar.prototype.onHoverMove = function(x, y) {
68092      var index, _ref;
68093      index = this.hitTest(x);
68094      return (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(index));
68095    };
68096
68097    Bar.prototype.onHoverOut = function() {
68098      if (this.options.hideHover !== false) {
68099        return this.hover.hide();
68100      }
68101    };
68102
68103    Bar.prototype.hoverContentForRow = function(index) {
68104      var content, j, row, x, y, _i, _len, _ref;
68105      row = this.data[index];
68106      content = "<div class='morris-hover-row-label'>" + row.label + "</div>";
68107      _ref = row.y;
68108      for (j = _i = 0, _len = _ref.length; _i < _len; j = ++_i) {
68109        y = _ref[j];
68110        content += "<div class='morris-hover-point' style='color: " + (this.colorFor(row, j, 'label')) + "'>\n  " + this.options.labels[j] + ":\n  " + (this.yLabelFormat(y)) + "\n</div>";
68111      }
68112      if (typeof this.options.hoverCallback === 'function') {
68113        content = this.options.hoverCallback(index, this.options, content, row.src
68113);
68114      }
68115      x = this.left + (index + 0.5) * this.width / this.data.length;
68116      return [content, x];
68117    };
68118
68119    Bar.prototype.drawXAxisLabel = function(xPos, yPos, text) {
68120      var label;
68121      return label = this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor);
68122    };
68123
68124    Bar.prototype.drawBar = function(xPos, yPos, width, height, barColor, opacity, radiusArray) {
68125      var maxRadius, path;
68126      maxRadius = Math.max.apply(Math, radiusArray);
68127      if (maxRadius === 0 || maxRadius > height) {
68128        path = this.raphael.rect(xPos, yPos, width, height);
68129      } else {
68130        path = this.raphael.path(this.roundedRect(xPos, yPos, width, height, radiusArray));
68131      }
68132      return path.attr('fill', barColor).attr('fill-opacity', opacity).attr('stroke', 'none');
68133    };
68134
68135    Bar.prototype.roundedRect = function(x, y, w, h, r) {
68136      if (r == null) {
68137        r = [0, 0, 0, 0];
68138      }
68139      return ["M", x, r[0] + y, "Q", x, y, x + r[0], y, "L", x + w - r[1], y, "Q", x + w, y, x + w, y + r[1], "L", x + w, y + h - r[2], "Q", x + w, y + h, x + w - r[2], y + h, "L", x + r[3], y + h, "Q", x, y + h, x, y + h - r[3], "Z"];
68140    };
68141
68142    return Bar;
68143
68144  })(Morris.Grid);
68145
68146  Morris.Donut = (function(_super) {
68147    __extends(Donut, _super);
68148
68149    Donut.prototype.defaults = {
68150      colors: ['#0B62A4', '#3980B5', '#679DC6', '#95BBD7', '#B0CCE1', '#095791', '#095085', '#083E67', '#052C48', '#042135'],
68151      backgroundColor: '#FFFFFF',
68152      labelColor: '#000000',
68153      formatter: Morris.commas,
68154      resize: false
68155    };
68156
68157    function Donut(options) {
68158      this.resizeHandler = __bind(this.resizeHandler, this);
68159      this.select = __bind(this.select, this);
68160      this.click = __bind(this.click, this);
68161      var _this = this;
68162      if (!(this instanceof Morris.Donut)) {
68163        return new Morris.Donut(options);
68164      }
68165      this.options = $.extend({}, this.defaults, options);
68166      if (typeof options.element === 'string') {
68167        this.el = $(document.getElementById(options.element));
68168      } else {
68169        this.el = $(options.element);
68170      }
68171      if (this.el === null || this.el.length === 0) {
68172        throw new Error("Graph placeholder not found.");
68173      }
68174      if (options.data === void 0 || options.data.length === 0) {
68175        return;
68176      }
68177      this.raphael = new Raphael(this.el[0]);
68178      if (this.options.resize) {
68179        $(window).bind('resize', function(evt) {
68180          if (_this.timeoutId != null) {
68181            window.clearTimeout(_this.timeoutId);
68182          }
68183          return _this.timeoutId = window.setTimeout(_this.resizeHandler, 100);
68184        });
68185      }
68186      this.setData(options.data);
68187    }
68188
68189    Donut.prototype.redraw = function() {
68190      var C, cx, cy, i, idx, last, max_value, min, next, seg, total, value, w, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;
68191      this.raphael.clear();
68192      cx = this.el.width() / 2;
68193      cy = this.el.height() / 2;
68194      w = (Math.min(cx, cy) - 10) / 3;
68195      total = 0;
68196      _ref = this.values;
68197      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
68198        value = _ref[_i];
68199        total += value;
68200      }
68201      min = 5 / (2 * w);
68202      C = 1.9999 * Math.PI - min * this.data.length;
68203      last = 0;
68204      idx = 0;
68205      this.segments = [];
68206      _ref1 = this.values;
68207      for (i = _j = 0, _len1 = _ref1.length; _j < _len1; i = ++_j) {
68208        value = _ref1[i];
68209        next = last + min + C * (value / total);
68210        seg = new Morris.DonutSegment(cx, cy, w * 2, w, last, next, this.data[i].color || this.options.colors[idx % this.options.colors.length], this.options.backgroundColor, idx, this.raphael);
68211        seg.render();
68212        this.segments.push(seg);
68213        seg.on('hover', this.select);
68214        seg.on('click', this.click);
68215        last = next;
68216        idx += 1;
68217      }
68218      this.text1 = this.drawEmptyDonutLabel(cx, cy - 10, this.options.labelColor, 15, 800);
68219      this.text2 = this.drawEmptyDonutLabel(cx, cy + 10, this.options.labelColor, 14);
68220      max_value = Math.max.apply(Math, this.values);
68221      idx = 0;
68222      _ref2 = this.values;
68223      _results = [];
68224      for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
68225        value = _ref2[_k];
68226        if (value === max_value) {
68227          this.select(idx);
68228          break;
68229        }
68230        _results.push(idx += 1);
68231      }
68232      return _results;
68233    };
68234
68235    Donut.prototype.setData = function(data) {
68236      var row;
68237      this.data = data;
68238      this.values = (function() {
68239        var _i, _len, _ref, _results;
68240        _ref = this.data;
68241        _results = [];
68242        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
68243          row = _ref[_i];
68244          _results.push(parseFloat(row.value));
68245        }
68246        return _results;
68247      }).call(this);
68248      return this.redraw();
68249    };
68250
68251    Donut.prototype.click = function(idx) {
68252      return this.fire('click', idx, this.data[idx]);
68253    };
68254
68255    Donut.prototype.select = function(idx) {
68256      var row, s, segment, _i, _len, _ref;
68257      _ref = this.segments;
68258      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
68259        s = _ref[_i];
68260        s.deselect();
68261      }
68262      segment = this.segments[idx];
68263      segment.select();
68264      row = this.data[idx];
68265      return this.setLabels(row.label, this.options.formatter(row.value, row));
68266    };
68267
68268    Donut.prototype.setLabels = function(label1, label2) {
68269      var inner, maxHeightBottom, maxHeightTop, maxWidth, text1bbox, text1scale, text2bbox, text2scale;
68270      inner = (Math.min(this.el.width() / 2, this.el.height() / 2) - 10) * 2 / 3;
68271      maxWidth = 1.8 * inner;
68272      maxHeightTop = inner / 2;
68273      maxHeightBottom = inner / 3;
68274      this.text1.attr({
68275        text: label1,
68276        transform: ''
68277      });
68278      text1bbox = this.text1.getBBox();
68279      text1scale = Math.min(maxWidth / text1bbox.width, maxHeightTop / text1bbox.height);
68280      this.text1.attr({
68281        transform: "S" + text1scale + "," + text1scale + "," + (text1bbox.x + text1bbox.width / 2) + "," + (text1bbox.y + text1bbox.height)
68282      });
68283      this.text2.attr({
68284        text: label2,
68285        transform: ''
68286      });
68287      text2bbox = this.text2.getBBox();
68288      text2scale = Math.min(maxWidth / text2bbox.width, maxHeightBottom / text2bbox.height);
68289      return this.text2.attr({
68290        transform: "S" + text2scale + "," + text2scale + "," + (text2bbox.x + text2bbox.width / 2) + "," + text2bbox.y
68291      });
68292    };
68293
68294    Donut.prototype.drawEmptyDonutLabel = function(xPos, yPos, color, fontSize, fontWeight) {
68295      var text;
68296      text = this.raphael.text(xPos, yPos, '').attr('font-size', fontSize).attr('fill', color);
68297      if (fontWeight != null) {
68298        text.attr('font-weight', fontWeight);
68299      }
68300      return text;
68301    };
68302
68303    Donut.prototype.resizeHandler = function() {
68304      this.timeoutId = null;
68305      this.raphael.setSize(this.el.width(), this.el.height());
68306      return this.redraw();
68307    };
68308
68309    return Donut;
68310
68311  })(Morris.EventEmitter);
68312
68313  Morris.DonutSegment = (function(_super) {
68314    __extends(DonutSegment, _super);
68315
68316    function DonutSegment(cx, cy, inner, outer, p0, p1, color, backgroundColor, index, raphael) {
68317      this.cx = cx;
68318      this.cy = cy;
68319      this.inner = inner;
68320      this.outer = outer;
68321      this.color = color;
68322      this.backgroundColor = backgroundColor;
68323      this.index = index;
68324      this.raphael = raphael;
68325      this.deselect = __bind(this.deselect, this);
68326      this.select = __bind(this.select, this);
68327      this.sin_p0 = Math.sin(p0);
68328      this.cos_p0 = Math.cos(p0);
68329      this.sin_p1 = Math.sin(p1);
68330      this.cos_p1 = Math.cos(p1);
68331      this.is_long = (p1 - p0) > Math.PI ? 1 : 0;
68332      this.path = this.calcSegment(this.inner + 3, this.inner + this.outer - 5);
68333      this.selectedPath = this.calcSegment(this.inner + 3, this.inner + this.outer);
68334      this.hilight = this.calcArc(this.inner);
68335    }
68336
68337    DonutSegment.prototype.calcArcPoints = function(r) {
68338      return [this.cx + r * this.sin_p0, this.cy + r * this.cos_p0, this.cx + r * this.sin_p1, this.cy + r * this.cos_p1];
68339    };
68340
68341    DonutSegment.prototype.calcSegment = function(r1, r2) {
68342      var ix0, ix1, iy0, iy1, ox0, ox1, oy0, oy1, _ref, _ref1;
68343      _ref = this.calcArcPoints(r1), ix0 = _ref[0], iy0 = _ref[1], ix1 
68343= _ref[2], iy1 = _ref[3];
68344      _ref1 = this.calcArcPoints(r2), ox0 = _ref1[0], oy0 = _ref1[1], ox1 = _ref1[2], oy1 = _ref1[3];
68345      return ("M" + ix0 + "," + iy0) + ("A" + r1 + "," + r1 + ",0," + this.is_long + ",0," + ix1 + "," + iy1) + ("L" + ox1 + "," + oy1) + ("A" + r2 + "," + r2 + ",0," + this.is_long + ",1," + ox0 + "," + oy0) + "Z";
68346    };
68347
68348    DonutSegment.prototype.calcArc = function(r) {
68349      var ix0, ix1, iy0, iy1, _ref;
68350      _ref = this.calcArcPoints(r), ix0 = _ref[0], iy0 = _ref[1], ix1 = _ref[2], iy1 = _ref[3];
68351      return ("M" + ix0 + "," + iy0) + ("A" + r + "," + r + ",0," + this.is_long + ",0," + ix1 + "," + iy1);
68352    };
68353
68354    DonutSegment.prototype.render = function() {
68355      var _this = this;
68356      this.arc = this.drawDonutArc(this.hilight, this.color);
68357      return this.seg = this.drawDonutSegment(this.path, this.color, this.backgroundColor, function() {
68358        return _this.fire('hover', _this.index);
68359      }, function() {
68360        return _this.fire('click', _this.index);
68361      });
68362    };
68363
68364    DonutSegment.prototype.drawDonutArc = function(path, color) {
68365      return this.raphael.path(path).attr({
68366        stroke: color,
68367        'stroke-width': 2,
68368        opacity: 0
68369      });
68370    };
68371
68372    DonutSegment.prototype.drawDonutSegment = function(path, fillColor, strokeColor, hoverFunction, clickFunction) {
68373      return this.raphael.path(path).attr({
68374        fill: fillColor,
68375        stroke: strokeColor,
68376        'stroke-width': 3
68377      }).hover(hoverFunction).click(clickFunction);
68378    };
68379
68380    DonutSegment.prototype.select = function() {
68381      if (!this.selected) {
68382        this.seg.animate({
68383          path: this.selectedPath
68384        }, 150, '<>');
68385        this.arc.animate({
68386          opacity: 1
68387        }, 150, '<>');
68388        return this.selected = true;
68389      }
68390    };
68391
68392    DonutSegment.prototype.deselect = function() {
68393      if (this.selected) {
68394        this.seg.animate({
68395          path: this.path
68396        }, 150, '<>');
68397        this.arc.animate({
68398          opacity: 0
68399        }, 150, '<>');
68400        return this.selected = false;
68401      }
68402    };
68403
68404    return DonutSegment;
68405
68406  })(Morris.EventEmitter);
68407
68408}).call(this);
68409
68410(function (root, factory) {
68411  if (typeof define === 'function' && define.amd) {
68412    // AMD. Register as an anonymous module unless amdModuleId is set
68413    define('Chartist', [], function () {
68414      return (root['Chartist'] = factory());
68415    });
68416  } else if (typeof module === 'object' && module.exports) {
68417    // Node. Does not work with strict CommonJS, but
68418    // only CommonJS-like environments that support module.exports,
68419    // like Node.
68420    module.exports = factory();
68421  } else {
68422    root['Chartist'] = factory();
68423  }
68424}(this, function () {
68425
68426/* Chartist.js 0.11.0
68427 * Copyright © 2017 Gion Kunz
68428 * Free to use under either the WTFPL license or the MIT license.
68429 * https://raw.githubusercontent.com/gionkunz/chartist-js/master/LICENSE-WTFPL
68430 * https://raw.githubusercontent.com/gionkunz/chartist-js/master/LICENSE-MIT
68431 */
68432/**
68433 * The core module of Chartist that is mainly providing static functions and higher level functions for chart modules.
68434 *
68435 * @module Chartist.Core
68436 */
68437var Chartist = {
68438  version: '0.11.0'
68439};
68440
68441(function (window, document, Chartist) {
68442  'use strict';
68443
68444  /**
68445   * This object contains all namespaces used within Chartist.
68446   *
68447   * @memberof Chartist.Core
68448   * @type {{svg: string, xmlns: string, xhtml: string, xlink: string, ct: string}}
68449   */
68450  Chartist.namespaces = {
68451    svg: 'http://www.w3.org/2000/svg',
68452    xmlns: 'http://www.w3.org/2000/xmlns/',
68453    xhtml: 'http://www.w3.org/1999/xhtml',
68454    xlink: 'http://www.w3.org/1999/xlink',
68455    ct: 'http://gionkunz.github.com/chartist-js/ct'
68456  };
68457
68458  /**
68459   * Helps to simplify functional style code
68460   *
68461   * @memberof Chartist.Core
68462   * @param {*} n This exact value will be returned by the noop function
68463   * @return {*} The same value that was provided to the n parameter
68464   */
68465  Chartist.noop = function (n) {
68466    return n;
68467  };
68468
68469  /**
68470   * Generates a-z from a number 0 to 26
68471   *
68472   * @memberof Chartist.Core
68473   * @param {Number} n A number from 0 to 26 that will result in a letter a-z
68474   * @return {String} A character from a-z based on the input number n
68475   */
68476  Chartist.alphaNumerate = function (n) {
68477    // Limit to a-z
68478    return String.fromCharCode(97 + n % 26);
68479  };
68480
68481  /**
68482   * Simple recursive object extend
68483   *
68484   * @memberof Chartist.Core
68485   * @param {Object} target Target object where the source will be merged into
68486   * @param {Object...} sources This object (objects) will be merged into target and then target is returned
68487   * @return {Object} An object that has the same reference as target but is extended and merged with the properties of source
68488   */
68489  Chartist.extend = function (target) {
68490    var i, source, sourceProp;
68491    target = target || {};
68492
68493    for (i = 1; i < arguments.length; i++) {
68494      source = arguments[i];
68495      for (var prop in source) {
68496        sourceProp = source[prop];
68497        if (typeof sourceProp === 'object' && sourceProp !== null && !(sourceProp instanceof Array)) {
68498          target[prop] = Chartist.extend(target[prop], sourceProp);
68499        } else {
68500          target[prop] = sourceProp;
68501        }
68502      }
68503    }
68504
68505    return target;
68506  };
68507
68508  /**
68509   * Replaces all occurrences of subStr in str with newSubStr and returns a new string.
68510   *
68511   * @memberof Chartist.Core
68512   * @param {String} str
68513   * @param {String} subStr
68514   * @param {String} newSubStr
68515   * @return {String}
68516   */
68517  Chartist.replaceAll = function(str, subStr, newSubStr) {
68518    return str.replace(new RegExp(subStr, 'g'), newSubStr);
68519  };
68520
68521  /**
68522   * Converts a number to a string with a unit. If a string is passed then this will be returned unmodified.
68523   *
68524   * @memberof Chartist.Core
68525   * @param {Number} value
68526   * @param {String} unit
68527   * @return {String} Returns the passed number value with unit.
68528   */
68529  Chartist.ensureUnit = function(value, unit) {
68530    if(typeof value === 'number') {
68531      value = value + unit;
68532    }
68533
68534    return value;
68535  };
68536
68537  /**
68538   * Converts a number or string to a quantity object.
68539   *
68540   * @memberof Chartist.Core
68541   * @param {String|Number} input
68542   * @return {Object}
68542 Returns an object containing the value as number and the unit as string.
68543   */
68544  Chartist.quantity = function(input) {
68545    if (typeof input === 'string') {
68546      var match = (/^(\d+)\s*(.*)$/g).exec(input);
68547      return {
68548        value : +match[1],
68549        unit: match[2] || undefined
68550      };
68551    }
68552    return { value: input };
68553  };
68554
68555  /**
68556   * This is a wrapper around document.querySelector that will return the query if it's already of type Node
68557   *
68558   * @memberof Chartist.Core
68559   * @param {String|Node} query The query to use for selecting a Node or a DOM node that will be returned directly
68560   * @return {Node}
68561   */
68562  Chartist.querySelector = function(query) {
68563    return query instanceof Node ? query : document.querySelector(query);
68564  };
68565
68566  /**
68567   * Functional style helper to produce array with given length initialized with undefined values
68568   *
68569   * @memberof Chartist.Core
68570   * @param length
68571   * @return {Array}
68572   */
68573  Chartist.times = function(length) {
68574    return Array.apply(null, new Array(length));
68575  };
68576
68577  /**
68578   * Sum helper to be used in reduce functions
68579   *
68580   * @memberof Chartist.Core
68581   * @param previous
68582   * @param current
68583   * @return {*}
68584   */
68585  Chartist.sum = function(previous, current) {
68586    return previous + (current ? current : 0);
68587  };
68588
68589  /**
68590   * Multiply helper to be used in `Array.map` for multiplying each value of an array with a factor.
68591   *
68592   * @memberof Chartist.Core
68593   * @param {Number} factor
68594   * @returns {Function} Function that can be used in `Array.map` to multiply each value in an array
68595   */
68596  Chartist.mapMultiply = function(factor) {
68597    return function(num) {
68598      return num * factor;
68599    };
68600  };
68601
68602  /**
68603   * Add helper to be used in `Array.map` for adding a addend to each value of an array.
68604   *
68605   * @memberof Chartist.Core
68606   * @param {Number} addend
68607   * @returns {Function} Function that can be used in `Array.map` to add a addend to each value in an array
68608   */
68609  Chartist.mapAdd = function(addend) {
68610    return function(num) {
68611      return num + addend;
68612    };
68613  };
68614
68615  /**
68616   * Map for multi dimensional arrays where their nested arrays will be mapped in serial. The output array will have the length of the largest nested array. The callback function is called with variable arguments where each argument is the nested array value (or undefined if there are no more values).
68617   *
68618   * @memberof Chartist.Core
68619   * @param arr
68620   * @param cb
68621   * @return {Array}
68622   */
68623  Chartist.serialMap = function(arr, cb) {
68624    var result = [],
68625        length = Math.max.apply(null, arr.map(function(e) {
68626          return e.length;
68627        }));
68628
68629    Chartist.times(length).forEach(function(e, index) {
68630      var args = arr.map(function(e) {
68631        return e[index];
68632      });
68633
68634      result[index] = cb.apply(null, args);
68635    });
68636
68637    return result;
68638  };
68639
68640  /**
68641   * This helper function can be used to round values with certain precision level after decimal. This is used to prevent rounding errors near float point precision limit.
68642   *
68643   * @memberof Chartist.Core
68644   * @param {Number} value The value that should be rounded with precision
68645   * @param {Number} [digits] The number of digits after decimal used to do the rounding
68646   * @returns {number} Rounded value
68647   */
68648  Chartist.roundWithPrecision = function(value, digits) {
68649    var precision = Math.pow(10, digits || Chartist.precision);
68650    return Math.round(value * precision) / precision;
68651  };
68652
68653  /**
68654   * Precision level used internally in Chartist for rounding. If you require more decimal places you can increase this number.
68655   *
68656   * @memberof Chartist.Core
68657   * @type {number}
68658   */
68659  Chartist.precision = 8;
68660
68661  /**
68662   * A map with characters to escape for strings to be safely used as attribute values.
68663   *
68664   * @memberof Chartist.Core
68665   * @type {Object}
68666   */
68667  Chartist.escapingMap = {
68668    '&': '&amp;',
68669    '<': '&lt;',
68670    '>': '&gt;',
68671    '"': '&quot;',
68672    '\'': '&#039;'
68673  };
68674
68675  /**
68676   * This function serializes arbitrary data to a string. In case of data that can't be easily converted to a string, this function will create a wrapper object and serialize the data using JSON.stringify. The outcoming string will always be escaped using Chartist.escapingMap.
68677   * If called with null or undefined the function will return immediately with null or undefined.
68678   *
68679   * @memberof Chartist.Core
68680   * @param {Number|String|Object} data
68681   * @return {String}
68682   */
68683  Chartist.serialize = function(data) {
68684    if(data === null || data === undefined) {
68685      return data;
68686    } else if(typeof data === 'number') {
68687      data = ''+data;
68688    } else if(typeof data === 'object') {
68689      data = JSON.stringify({data: data});
68690    }
68691
68692    return Object.keys(Chartist.escapingMap).reduce(function(result, key) {
68693      return Chartist.replaceAll(result, key, Chartist.escapingMap[key]);
68694    }, data);
68695  };
68696
68697  /**
68698   * This function de-serializes a string previously serialized with Chartist.serialize. The string will always be unescaped using Chartist.escapingMap before it's returned. Based on the input value the return type can be Number, String or Object. JSON.parse is used with try / catch to see if the unescaped string can be parsed into an Object and this Object will be returned on success.
68699   *
68700   * @memberof Chartist.Core
68701   * @param {String} data
68702   * @return {String|Number|Object}
68703   */
68704  Chartist.deserialize = function(data) {
68705    if(typeof data !== 'string') {
68706      return data;
68707    }
68708
68709    data = Object.keys(Chartist.escapingMap).reduce(function(result, key) {
68710      return Chartist.replaceAll(result, Chartist.escapingMap[key], key);
68711    }, data);
68712
68713    try {
68714      data = JSON.parse(data);
68715      data = data.data !== undefined ? data.data : data;
68716    } catch(e) {}
68717
68718    return data;
68719  };
68720
68721  /**
68722   * Create or reinitialize the SVG element for the chart
68723   *
68724   * @memberof Chartist.Core
68725   * @param {Node} container The containing DOM Node object that will be used to plant the SVG element
68726   * @param {String} width Set the width of the SVG element. Default is 100%
68727   * @param {String} height Set the height of the SVG element. Default is 100%
68728   * @param {String} className Specify a class to be added to the SVG element
68729   * @return {Object} The created/reinitialized SVG element
68730   */
68731  Chartist.createSvg = function (container, width, height, className) {
68732    var svg;
68733
68734    width = width || '100%';
68735    height = height || '100%';
68736
68737    // Check if there is a previous SVG element in the container that c
68737ontains the Chartist XML namespace and remove it
68738    // Since the DOM API does not support namespaces we need to manually search the returned list http://www.w3.org/TR/selectors-api/
68739    Array.prototype.slice.call(container.querySelectorAll('svg')).filter(function filterChartistSvgObjects(svg) {
68740      return svg.getAttributeNS(Chartist.namespaces.xmlns, 'ct');
68741    }).forEach(function removePreviousElement(svg) {
68742      container.removeChild(svg);
68743    });
68744
68745    // Create svg object with width and height or use 100% as default
68746    svg = new Chartist.Svg('svg').attr({
68747      width: width,
68748      height: height
68749    }).addClass(className);
68750
68751    svg._node.style.width = width;
68752    svg._node.style.height = height;
68753
68754    // Add the DOM node to our container
68755    container.appendChild(svg._node);
68756
68757    return svg;
68758  };
68759
68760  /**
68761   * Ensures that the data object passed as second argument to the charts is present and correctly initialized.
68762   *
68763   * @param  {Object} data The data object that is passed as second argument to the charts
68764   * @return {Object} The normalized data object
68765   */
68766  Chartist.normalizeData = function(data, reverse, multi) {
68767    var labelCount;
68768    var output = {
68769      raw: data,
68770      normalized: {}
68771    };
68772
68773    // Check if we should generate some labels based on existing series data
68774    output.normalized.series = Chartist.getDataArray({
68775      series: data.series || []
68776    }, reverse, multi);
68777
68778    // If all elements of the normalized data array are arrays we're dealing with
68779    // multi series data and we need to find the largest series if they are un-even
68780    if (output.normalized.series.every(function(value) {
68781        return value instanceof Array;
68782      })) {
68783      // Getting the series with the the most elements
68784      labelCount = Math.max.apply(null, output.normalized.series.map(function(series) {
68785        return series.length;
68786      }));
68787    } else {
68788      // We're dealing with Pie data so we just take the normalized array length
68789      labelCount = output.normalized.series.length;
68790    }
68791
68792    output.normalized.labels = (data.labels || []).slice();
68793    // Padding the labels to labelCount with empty strings
68794    Array.prototype.push.apply(
68795      output.normalized.labels,
68796      Chartist.times(Math.max(0, labelCount - output.normalized.labels.length)).map(function() {
68797        return '';
68798      })
68799    );
68800
68801    if(reverse) {
68802      Chartist.reverseData(output.normalized);
68803    }
68804
68805    return output;
68806  };
68807
68808  /**
68809   * This function safely checks if an objects has an owned property.
68810   *
68811   * @param {Object} object The object where to check for a property
68812   * @param {string} property The property name
68813   * @returns {boolean} Returns true if the object owns the specified property
68814   */
68815  Chartist.safeHasProperty = function(object, property) {
68816    return object !== null &&
68817      typeof object === 'object' &&
68818      object.hasOwnProperty(property);
68819  };
68820
68821  /**
68822   * Checks if a value is considered a hole in the data series.
68823   *
68824   * @param {*} value
68825   * @returns {boolean} True if the value is considered a data hole
68826   */
68827  Chartist.isDataHoleValue = function(value) {
68828    return value === null ||
68829      value === undefined ||
68830      (typeof value === 'number' && isNaN(value));
68831  };
68832
68833  /**
68834   * Reverses the series, labels and series data arrays.
68835   *
68836   * @memberof Chartist.Core
68837   * @param data
68838   */
68839  Chartist.reverseData = function(data) {
68840    data.labels.reverse();
68841    data.series.reverse();
68842    for (var i = 0; i < data.series.length; i++) {
68843      if(typeof(data.series[i]) === 'object' && data.series[i].data !== undefined) {
68844        data.series[i].data.reverse();
68845      } else if(data.series[i] instanceof Array) {
68846        data.series[i].reverse();
68847      }
68848    }
68849  };
68850
68851  /**
68852   * Convert data series into plain array
68853   *
68854   * @memberof Chartist.Core
68855   * @param {Object} data The series object that contains the data to be visualized in the chart
68856   * @param {Boolean} [reverse] If true the whole data is reversed by the getDataArray call. This will modify the data object passed as first parameter. The labels as well as the series order is reversed. The whole series data arrays are reversed too.
68857   * @param {Boolean} [multi] Create a multi dimensional array from a series data array where a value object with `x` and `y` values will be created.
68858   * @return {Array} A plain array that contains the data to be visualized in the chart
68859   */
68860  Chartist.getDataArray = function(data, reverse, multi) {
68861    // Recursively walks through nested arrays and convert string values to numbers and objects with value properties
68862    // to values. Check the tests in data core -> data normalization for a detailed specification of expected values
68863    function recursiveConvert(value) {
68864      if(Chartist.safeHasProperty(value, 'value')) {
68865        // We are dealing with value object notation so we need to recurse on value property
68866        return recursiveConvert(value.value);
68867      } else if(Chartist.safeHasProperty(value, 'data')) {
68868        // We are dealing with series object notation so we need to recurse on data property
68869        return recursiveConvert(value.data);
68870      } else if(value instanceof Array) {
68871        // Data is of type array so we need to recurse on the series
68872        return value.map(recursiveConvert);
68873      } else if(Chartist.isDataHoleValue(value)) {
68874        // We're dealing with a hole in the data and therefore need to return undefined
68875        // We're also returning undefined for multi value output
68876        return undefined;
68877      } else {
68878        // We need to prepare multi value output (x and y data)
68879        if(multi) {
68880          var multiValue = {};
68881
68882          // Single series value arrays are assumed to specify the Y-Axis value
68883          // For example: [1, 2] => [{x: undefined, y: 1}, {x: undefined, y: 2}]
68884          // If multi is a string then it's assumed that it specified which dimension should be filled as default
68885          if(typeof multi === 'string') {
68886            multiValue[multi] = Chartist.getNumberOrUndefined(value);
68887          } else {
68888            multiValue.y = Chartist.getNumberOrUndefined(value);
68889          }
68890
68891          multiValue.x = value.hasOwnProperty('x') ? Chartist.getNumberOrUndefined(value.x) : multiValue.x;
68892          multiValue.y = value.hasOwnProperty('y') ? Chartist.getNumberOrUndefined(value.y) : multiValue.y;
68893
68894          return multiValue;
68895
68896        } else {
68897          // We can return simple data
68898          return Chartist.getNumberOrUndefined(value);
68899        }
68900      }
68901    }
68902
68903    return data.series.map(recursiveConvert);
68904  };
68905
68906  /**
68907   * Converts a number into a padding object.
68908   *
68909   * @memberof Chartist.Core
68910   * @param {Object|Number} padding
68911   * @param {Number} [fallback] This value is used to fill missing values if a incomplete padding object was passed
68912   * @returns {Object}
68912 Returns a padding object containing top, right, bottom, left properties filled with the padding number passed in as argument. If the argument is something else than a number (presumably already a correct padding object) then this argument is directly returned.
68913   */
68914  Chartist.normalizePadding = function(padding, fallback) {
68915    fallback = fallback || 0;
68916
68917    return typeof padding === 'number' ? {
68918      top: padding,
68919      right: padding,
68920      bottom: padding,
68921      left: padding
68922    } : {
68923      top: typeof padding.top === 'number' ? padding.top : fallback,
68924      right: typeof padding.right === 'number' ? padding.right : fallback,
68925      bottom: typeof padding.bottom === 'number' ? padding.bottom : fallback,
68926      left: typeof padding.left === 'number' ? padding.left : fallback
68927    };
68928  };
68929
68930  Chartist.getMetaData = function(series, index) {
68931    var value = series.data ? series.data[index] : series[index];
68932    return value ? value.meta : undefined;
68933  };
68934
68935  /**
68936   * Calculate the order of magnitude for the chart scale
68937   *
68938   * @memberof Chartist.Core
68939   * @param {Number} value The value Range of the chart
68940   * @return {Number} The order of magnitude
68941   */
68942  Chartist.orderOfMagnitude = function (value) {
68943    return Math.floor(Math.log(Math.abs(value)) / Math.LN10);
68944  };
68945
68946  /**
68947   * Project a data length into screen coordinates (pixels)
68948   *
68949   * @memberof Chartist.Core
68950   * @param {Object} axisLength The svg element for the chart
68951   * @param {Number} length Single data value from a series array
68952   * @param {Object} bounds All the values to set the bounds of the chart
68953   * @return {Number} The projected data length in pixels
68954   */
68955  Chartist.projectLength = function (axisLength, length, bounds) {
68956    return length / bounds.range * axisLength;
68957  };
68958
68959  /**
68960   * Get the height of the area in the chart for the data series
68961   *
68962   * @memberof Chartist.Core
68963   * @param {Object} svg The svg element for the chart
68964   * @param {Object} options The Object that contains all the optional values for the chart
68965   * @return {Number} The height of the area in the chart for the data series
68966   */
68967  Chartist.getAvailableHeight = function (svg, options) {
68968    return Math.max((Chartist.quantity(options.height).value || svg.height()) - (options.chartPadding.top +  options.chartPadding.bottom) - options.axisX.offset, 0);
68969  };
68970
68971  /**
68972   * Get highest and lowest value of data array. This Array contains the data that will be visualized in the chart.
68973   *
68974   * @memberof Chartist.Core
68975   * @param {Array} data The array that contains the data to be visualized in the chart
68976   * @param {Object} options The Object that contains the chart options
68977   * @param {String} dimension Axis dimension 'x' or 'y' used to access the correct value and high / low configuration
68978   * @return {Object} An object that contains the highest and lowest value that will be visualized on the chart.
68979   */
68980  Chartist.getHighLow = function (data, options, dimension) {
68981    // TODO: Remove workaround for deprecated global high / low config. Axis high / low configuration is preferred
68982    options = Chartist.extend({}, options, dimension ? options['axis' + dimension.toUpperCase()] : {});
68983
68984    var highLow = {
68985        high: options.high === undefined ? -Number.MAX_VALUE : +options.high,
68986        low: options.low === undefined ? Number.MAX_VALUE : +options.low
68987      };
68988    var findHigh = options.high === undefined;
68989    var findLow = options.low === undefined;
68990
68991    // Function to recursively walk through arrays and find highest and lowest number
68992    function recursiveHighLow(data) {
68993      if(data === undefined) {
68994        return undefined;
68995      } else if(data instanceof Array) {
68996        for (var i = 0; i < data.length; i++) {
68997          recursiveHighLow(data[i]);
68998        }
68999      } else {
69000        var value = dimension ? +data[dimension] : +data;
69001
69002        if (findHigh && value > highLow.high) {
69003          highLow.high = value;
69004        }
69005
69006        if (findLow && value < highLow.low) {
69007          highLow.low = value;
69008        }
69009      }
69010    }
69011
69012    // Start to find highest and lowest number recursively
69013    if(findHigh || findLow) {
69014      recursiveHighLow(data);
69015    }
69016
69017    // Overrides of high / low based on reference value, it will make sure that the invisible reference value is
69018    // used to generate the chart. This is useful when the chart always needs to contain the position of the
69019    // invisible reference value in the view i.e. for bipolar scales.
69020    if (options.referenceValue || options.referenceValue === 0) {
69021      highLow.high = Math.max(options.referenceValue, highLow.high);
69022      highLow.low = Math.min(options.referenceValue, highLow.low);
69023    }
69024
69025    // If high and low are the same because of misconfiguration or flat data (only the same value) we need
69026    // to set the high or low to 0 depending on the polarity
69027    if (highLow.high <= highLow.low) {
69028      // If both values are 0 we set high to 1
69029      if (highLow.low === 0) {
69030        highLow.high = 1;
69031      } else if (highLow.low < 0) {
69032        // If we have the same negative value for the bounds we set bounds.high to 0
69033        highLow.high = 0;
69034      } else if (highLow.high > 0) {
69035        // If we have the same positive value for the bounds we set bounds.low to 0
69036        highLow.low = 0;
69037      } else {
69038        // If data array was empty, values are Number.MAX_VALUE and -Number.MAX_VALUE. Set bounds to prevent errors
69039        highLow.high = 1;
69040        highLow.low = 0;
69041      }
69042    }
69043
69044    return highLow;
69045  };
69046
69047  /**
69048   * Checks if a value can be safely coerced to a number. This includes all values except null which result in finite numbers when coerced. This excludes NaN, since it's not finite.
69049   *
69050   * @memberof Chartist.Core
69051   * @param value
69052   * @returns {Boolean}
69053   */
69054  Chartist.isNumeric = function(value) {
69055    return value === null ? false : isFinite(value);
69056  };
69057
69058  /**
69059   * Returns true on all falsey values except the numeric value 0.
69060   *
69061   * @memberof Chartist.Core
69062   * @param value
69063   * @returns {boolean}
69064   */
69065  Chartist.isFalseyButZero = function(value) {
69066    return !value && value !== 0;
69067  };
69068
69069  /**
69070   * Returns a number if the passed parameter is a valid number or the function will return undefined. On all other values than a valid number, this function will return undefined.
69071   *
69072   * @memberof Chartist.Core
69073   * @param value
69074   * @returns {*}
69075   */
69076  Chartist.getNumberOrUndefined = function(value) {
69077    return Chartist.isNumeric(value) ? +value : undefined;
69078  };
69079
69080  /**
69081   * Checks if provided value object is multi value (contains x or y properties)
69082   *
69083   * @memberof Chartist.Core
69084   * @param value
69085   */
69086  Chartist.isMultiValue = function(value) {
69087    return typeof value === 'object' && ('x' in value || 'y' in value);
69088  };
69089
69090  /**
69091   * Gets a value from a dimension `value.x` or `value.y` while returning value directly if it's a valid numeric value. If the value is not numeric and it's falsey this function will return `defaultValue`.
69092   *
69093   * @memberof Chartist.Core
69094   * @param value
69095   * @param dimension
69096   * @param defaultValue
69097   * @returns {*}
69098   */
69099  Chartist.getMultiValue = function(value, dimension) {
69100    if(Chartist.isMultiValue(value)) {
69101      return Chartist.getNumberOrUndefined(value[dimension || 'y']);
69102    } else {
69103      return Chartist.getNumberOrUndefined(value);
69104    }
69105  };
69106
69107  /**
69108   * Pollard Rho Algorithm to find smallest factor of an integer value. There are more efficient algorithms for factorization, but this one is quite efficient and not so complex.
69109   *
69110   * @memberof Chartist.Core
69111   * @param {Number} num An integer number where the smallest factor should be searched for
69112   * @returns {Number} The smallest integer factor of the parameter num.
69113   */
69114  Chartist.rho = function(num) {
69115    if(num === 1) {
69116      return num;
69117    }
69118
69119    function gcd(p, q) {
69120      if (p % q === 0) {
69121        return q;
69122      } else {
69123        return gcd(q, p % q);
69124      }
69125    }
69126
69127    function f(x) {
69128      return x * x + 1;
69129    }
69130
69131    var x1 = 2, x2 = 2, divisor;
69132    if (num % 2 === 0) {
69133      return 2;
69134    }
69135
69136    do {
69137      x1 = f(x1) % num;
69138      x2 = f(f(x2)) % num;
69139      divisor = gcd(Math.abs(x1 - x2), num);
69140    } while (divisor === 1);
69141
69142    return divisor;
69143  };
69144
69145  /**
69146   * Calculate and retrieve all the bounds for the chart and return them in one array
69147   *
69148   * @memberof Chartist.Core
69149   * @param {Number}
69149 axisLength The length of the Axis used for
69150   * @param {Object} highLow An object containing a high and low property indicating the value range of the chart.
69151   * @param {Number} scaleMinSpace The minimum projected length a step should result in
69152   * @param {Boolean} onlyInteger
69153   * @return {Object} All the values to set the bounds of the chart
69154   */
69155  Chartist.getBounds = function (axisLength, highLow, scaleMinSpace, onlyInteger) {
69156    var i,
69157      optimizationCounter = 0,
69158      newMin,
69159      newMax,
69160      bounds = {
69161        high: highLow.high,
69162        low: highLow.low
69163      };
69164
69165    bounds.valueRange = bounds.high - bounds.low;
69166    bounds.oom = Chartist.orderOfMagnitude(bounds.valueRange);
69167    bounds.step = Math.pow(10, bounds.oom);
69168    bounds.min = Math.floor(bounds.low / bounds.step) * bounds.step;
69169    bounds.max = Math.ceil(bounds.high / bounds.step) * bounds.step;
69170    bounds.range = bounds.max - bounds.min;
69171    bounds.numberOfSteps = Math.round(bounds.range / bounds.step);
69172
69173    // Optimize scale step by checking if subdivision is possible based on horizontalGridMinSpace
69174    // If we are already below the scaleMinSpace value we will scale up
69175    var length = Chartist.projectLength(axisLength, bounds.step, bounds);
69176    var scaleUp = length < scaleMinSpace;
69177    var smallestFactor = onlyInteger ? Chartist.rho(bounds.range) : 0;
69178
69179    // First check if we should only use integer steps and if step 1 is still larger than scaleMinSpace so we can use 1
69180    if(onlyInteger && Chartist.projectLength(axisLength, 1, bounds) >= scaleMinSpace) {
69181      bounds.step = 1;
69182    } else if(onlyInteger && smallestFactor < bounds.step && Chartist.projectLength(axisLength, smallestFactor, bounds) >= scaleMinSpace) {
69183      // If step 1 was too small, we can try the smallest factor of range
69184      // If the smallest factor is smaller than the current bounds.step and the projected length of smallest factor
69185      // is larger than the scaleMinSpace we should go for it.
69186      bounds.step = smallestFactor;
69187    } else {
69188      // Trying to divide or multiply by 2 and find the best step value
69189      while (true) {
69190        if (scaleUp && Chartist.projectLength(axisLength, bounds.step, bounds) <= scaleMinSpace) {
69191          bounds.step *= 2;
69192        } else if (!scaleUp && Chartist.projectLength(axisLength, bounds.step / 2, bounds) >= scaleMinSpace) {
69193          bounds.step /= 2;
69194          if(onlyInteger && bounds.step % 1 !== 0) {
69195            bounds.step *= 2;
69196            break;
69197          }
69198        } else {
69199          break;
69200        }
69201
69202        if(optimizationCounter++ > 1000) {
69203          throw new Error('Exceeded maximum number of iterations while optimizing scale step!');
69204        }
69205      }
69206    }
69207
69208    var EPSILON = 2.221E-16;
69209    bounds.step = Math.max(bounds.step, EPSILON);
69210    function safeIncrement(value, increment) {
69211      // If increment is too small use *= (1+EPSILON) as a simple nextafter
69212      if (value === (value += increment)) {
69213      	value *= (1 + (increment > 0 ? EPSILON : -EPSILON));
69214      }
69215      return value;
69216    }
69217
69218    // Narrow min and max based on new step
69219    newMin = bounds.min;
69220    newMax = bounds.max;
69221    while (newMin + bounds.step <= bounds.low) {
69222    	newMin = safeIncrement(newMin, bounds.step);
69223    }
69224    while (newMax - bounds.step >= bounds.high) {
69225    	newMax = safeIncrement(newMax, -bounds.step);
69226    }
69227    bounds.min = newMin;
69228    bounds.max = newMax;
69229    bounds.range = bounds.max - bounds.min;
69230
69231    var values = [];
69232    for (i = bounds.min; i <= bounds.max; i = safeIncrement(i, bounds.step)) {
69233      var value = Chartist.roundWithPrecision(i);
69234      if (value !== values[values.length - 1]) {
69235        values.push(value);
69236      }
69237    }
69238    bounds.values = values;
69239    return bounds;
69240  };
69241
69242  /**
69243   * Calculate cartesian coordinates of polar coordinates
69244   *
69245   * @memberof Chartist.Core
69246   * @param {Number} centerX X-axis coordinates of center point of circle segment
69247   * @param {Number} centerY X-axis coordinates of center point of circle segment
69248   * @param {Number} radius Radius of circle segment
69249   * @param {Number} angleInDegrees Angle of circle segment in degrees
69250   * @return {{x:Number, y:Number}} Coordinates of point on circumference
69251   */
69252  Chartist.polarToCartesian = function (centerX, centerY, radius, angleInDegrees) {
69253    var angleInRadians = (angleInDegrees - 90) * Math.PI / 180.0;
69254
69255    return {
69256      x: centerX + (radius * Math.cos(angleInRadians)),
69257      y: centerY + (radius * Math.sin(angleInRadians))
69258    };
69259  };
69260
69261  /**
69262   * Initialize chart drawing rectangle (area where chart is drawn) x1,y1 = bottom left / x2,y2 = top right
69263   *
69264   * @memberof Chartist.Core
69265   * @param {Object} svg The svg element for the chart
69266   * @param {Object} options The Object that contains all the optional values for the chart
69267   * @param {Number} [fallbackPadding] The fallback padding if partial padding objects are used
69268   * @return {Object} The chart rectangles coordinates inside the svg element plus the rectangles measurements
69269   */
69270  Chartist.createChartRect = function (svg, options, fallbackPadding) {
69271    var hasAxis = !!(options.axisX || options.axisY);
69272    var yAxisOffset = hasAxis ? options.axisY.offset : 0;
69273    var xAxisOffset = hasAxis ? options.axisX.offset : 0;
69274    // If width or height results in invalid value (including 0) we fallback to the unitless settings or even 0
69275    var width = svg.width() || Chartist.quantity(options.width).value || 0;
69276    var height = svg.height() || Chartist.quantity(options.height).value || 0;
69277    var normalizedPadding = Chartist.normalizePadding(options.chartPadding, fallbackPadding);
69278
69279    // If settings were to small to cope with offset (legacy) and padding, we'll adjust
69280    width = Math.max(width, yAxisOffset + normalizedPadding.left + normalizedPadding.right);
69281    height = Math.max(height, xAxisOffset + normalizedPadding.top + normalizedPadding.bottom);
69282
69283    var chartRect = {
69284      padding: normalizedPadding,
69285      width: function () {
69286        return this.x2 - this.x1;
69287      },
69288      height: function () {
69289        return this.y1 - this.y2;
69290      }
69291    };
69292
69293    if(hasAxis) {
69294      if (options.axisX.position === 'start') {
69295        chartRect.y2 = normalizedPadding.top + xAxisOffset;
69296        chartRect.y1 = Math.max(height - normalizedPadding.bottom, chartRect.y2 + 1);
69297      } else {
69298        chartRect.y2 = normalizedPadding.top;
69299        chartRect.y1 = Math.max(height - normalizedPadding.bottom - xAxisOffset, chartRect.y2 + 1);
69300      }
69301
69302      if (options.axisY.position === 'start') {
69303        chartRect.x1 = normalizedPadding.left + yAxisOffset;
69304        chartRect.x2 = Math.max(width - normalizedPadding.right, chartRect.x1 + 1);
69305      } else {
69306        chartRect.x1 = normalizedPadding.left;
69307        chartRect.x2 = Math.max(width - normalizedPadding.right - yAxisOffset, chartRect.x1 + 1);
69308      }
69309    } else {
69310      chartRect.x1 = normalizedPadding.left;
69311      chartRect.x2 = Math.max(width - normalizedPadding.right, chartRect.x1 + 1);
69312      chartRect.y2 = normalizedPadding.top;
69313      chartRect.y1 = Math.max(height - normalizedPadding.bottom, chartRect.y2 + 1);
69314    }
69315
69316    return chartRect;
69317  };
69318
69319  /**
69320   * Creates a grid line based on a projected value.
69321   *
69322   * @memberof Chartist.Core
69323   * @param position
69324   * @param index
69325   * @param axis
69326   * @param offset
69327   * @param length
69328   * @param group
69329   * @param classes
69330   * @param eventEmitter
69331   */
69332  Chartist.createGrid = function(position, index, axis, offset, length, group, classes, eventEmitter) {
69333    var positionalData = {};
69334    positionalData[axis.units.pos + '1'] = position;
69335    positionalData[axis.units.pos + '2'] = position;
69336    positionalData[axis.counterUnits.pos + '1'] = offset;
69337    positionalData[axis.counterUnits.pos + '2'] = offset + length;
69338
69339    var gridElement = group.elem('line', positionalData, classes.join(' '));
69340
69341    // Event for grid draw
69342    eventEmitter.emit('draw',
69343      Chartist.extend({
69344        type: 'grid',
69345        axis: axis,
69346        index: index,
69347        group: group,
69348        element: gridElement
69349      }, positionalData)
69350    );
69351  };
69352
69353  /**
69354   * Creates a grid background rect and emits the draw event.
69355   *
69356   * @memberof Chartist.Core
69357   * @param gridGroup
69358   * @param chartRect
69359   * @param className
69360   * @param eventEmitter
69361   */
69362  Chartist.createGridBackground = function (gridGroup, chartRect, className, eventEmitter) {
69363    var gridBackground = gridGroup.elem('rect', {
69364        x: chartRect.x1,
69365        y: chartRect.y2,
69366        width: chartRect.width(),
69367        height: chartRect.height(),
69368      }, className, true);
69369
69370      // Event for grid background draw
69371      eventEmitter.emit('draw', {
69372        type: 'gridBackground',
69373        group: gridGroup,
69374        element: gridBackground
69375      });
69376  };
69377
69378  /**
69379   * Creates a label based on a projected value and an axis.
69380   *
69381   * @memberof Chartist.Core
69382   * @param position
69383   * @param length
69384   * @param index
69385   * @param labels
69386   * @param axis
69387   * @param axisOffset
69388   * @param labelOffset
69389   * @param group
69390   * @param classes
69391   * @param useForeignObject
69392   * @param eventEmitter
69393   */
69394  Chartist.createLabel = function(position, length, index, labels, axis, axisOffset, labelOffset, group, classes, useForeignObject, eventEmitter) {
69395    var labelElement;
69396    var positionalData = {};
69397
69398    positionalData[axis.units.pos] = position + labelOffset[axis.units.pos];
69399    positionalData[axis.counterUnits.pos] = labelOffset[axis.counterUnits.pos];
69400    positionalData[axis.units.len] = length;
69401    positionalData[axis.counterUnits.len] = Math.max(0, axisOffset - 10);
69402
69403    if(useForeignObject) {
69404      // We need to set width and height explicitly to px as span will not expand with width and height being
69405      // 100% in all browsers
69406      var content = document.createElement('span');
69407      content.className = classes.join(' ');
69408      content.setAttribute('xmlns', Chartist.namespaces.xhtml);
69409      content.innerText = labels[index];
69410      content.style[axis.units.len] = Math.round(positionalData[axis.units.len]) + 'px';
69411      content.style[axis.counterUnits.len] = Math.round(positionalData[axis.counterUnits.len]) + 'px';
69412
69413      labelElement = group.foreignObject(content, Chartist.extend({
69414        style: 'overflow: visible;'
69415      }, positionalData));
69416    } else {
69417      labelElement = group.elem('text', positionalData, classes.join(' ')).text(labels[index]);
69418    }
69419
69420    eventEmitter.emit('draw', Chartist.extend({
69421      type: 'label',
69422      axis: axis,
69423      index: index,
69424      group: group,
69425      element: labelElement,
69426      text: labels[index]
69427    }, positionalData));
69428  };
69429
69430  /**
69431   * Helper to read series specific options from options object. It automatically falls back to the global option if
69432   * there is no option in the series options.
69433   *
69434   * @param {Object} series Series object
69435   * @param {Object} options Chartist options object
69436   * @param {string} key The options key that should be used to obtain the options
69437   * @returns {*}
69438   */
69439  Chartist.getSeriesOption = function(series, options, key) {
69440    if(series.name && options.series && options.series[series.name]) {
69441      var seriesOptions = options.series[series.name];
69442      return seriesOptions.hasOwnProperty(key) ? seriesOptions[key] : options[key];
69443    } else {
69444      return options[key];
69445    }
69446  };
69447
69448  /**
69449   * Provides options handling functionality with callback for options changes triggered by responsive options and media query matches
69450   *
69451   * @memberof Chartist.Core
69452   * @param {Object} options Options set by user
69453   * @param {Array} responsiveOptions Optional functions to add responsive behavior to chart
69454   * @param {Object} eventEmitter The event emitter that will be used to emit the options changed events
69455   * @return {Object} The consolidated options object from the defaults, base and matching responsive options
69456   */
69457  Chartist.optionsProvider = function (options, responsiveOptions, eventEmitter) {
69458    var baseOptions = Chartist.extend({}, options),
69459      currentOptions,
69460      mediaQueryListeners = [],
69461      i;
69462
69463    function updateCurrentOptions(mediaEvent) {
69464      var previousOptions = currentOptions;
69465      currentOptions = Chartist.extend({}, baseOptions);
69466
69467      if (responsiveOptions) {
69468        for (i = 0; i < responsiveOptions.length; i++) {
69469          var mql = window.matchMedia(responsiveOptions[i][0]);
69470          if (mql.matches) {
69471            currentOptions = Chartist.extend(currentOptions, responsiveOptions[i][1]);
69472          }
69473        }
69474      }
69475
69476      if(eventEmitter && mediaEvent) {
69477        eventEmitter.emit('optionsChanged', {
69478          previousOptions: previousOptions,
69479          currentOptions: currentOptions
69480        });
69481      }
69482    }
69483
69484    function removeMediaQueryListeners() {
69485      mediaQueryListeners.forEach(function(mql) {
69486        mql.removeListener(updateCurrentOptions);
69487      });
69488    }
69489
69490    if (!window.matchMedia) {
69491      throw 'window.matchMedia not found! Make sure you\'re using a polyfill.';
69492    } else if (responsiveOptions) {
69493
69494      for (i = 0; i < responsiveOptions.length; i++) {
69495        var mql = window.matchMedia(responsiveOptions[i][0]);
69496        mql.addListener(updateCurrentOptions);
69497        mediaQueryListeners.push(mql);
69498      }
69499    }
69500    // Execute initially without an event argument so we get the correct options
69501    updateCurrentOptions();
69502
69503    return {
69504      removeMediaQueryListeners: removeMediaQueryListeners,
69505      getCurrentOptions: function getCurrentOptions() {
69506        return Chartist.extend({}, currentOptions);
69507      }
69508    };
69509  };
69510
69511
69512  /**
69513   * Splits a list of coordinates and associated values into segments. Each returned segment contains a pathCoordinates
69514   * valueData property describing the segment.
69515   *
69516   * With the default options, segments consist of contiguous sets of points that do not have an undefined value. Any
69517   * points with undefined values are discarded.
69518   *
69519   * **Options**
69520   * The following options are used to determine how segments are formed
69521   * ```javascript
69522   * var options = {
69523   *   // If fillHoles is true, undefined values are simply discarded without creating a new segment. Assuming other options are default, this returns single segment.
69524   *   fillHoles: false,
69525   *   // If increasingX is true, the coordinates in all segments have strictly increasing x-values.
69526   *   increasingX: false
69527   * };
69528   * ```
69529   *
69530   * @memberof Chartist.Core
69531   * @param {Array} pathCoordinates List of point coordinates to be split in the form [x1, y1, x2, y2 ... xn, yn]
69532   * @param {Array} values List of associated point values in the form [v1, v2 .. vn]
69533   * @param {Object} options Options set by user
69534   * @return {Array} List of segments, each containing a pathCoordinates and valueData property.
69535   */
69536  Chartist.splitIntoSegments = function(pathCoordinates, valueData, options) {
69537    var defaultOptions = {
69538      increasingX: false,
69539      fillHoles: false
69540    };
69541
69542    options = Chartist.extend({}, defaultOptions, options);
69543
69544    var segments = [];
69545    var hole = true;
69546
69547    for(var i = 0; i < pathCoordinates.length; i += 2) {
69548      // If this value is a "hole" we set the hole flag
69549      if(Chartist.getMultiValue(valueData[i / 2].value) === undefined) {
69550      // if(valueData[i / 2].value === undefined) {
69551        if(!options.fillHoles) {
69552          hole = true;
69553        }
69554      } else {
69555        if(options.increasingX && i >= 2 && pathCoordinates[i] <= pathCoordinates[i-2]) {
69556          // X is not increasing, so we need to make sure we start a new segment
69557          hole = true;
69558        }
69559
69560
69561        // If it's a valid value we need to check if we're coming out of a hole and create a new empty segment
69562        if(hole) {
69563          segments.push({
69564            pathCoordinates: [],
69565            valueData: []
69566          });
69567          // As we have a valid value now, we are not in a "hole" anymore
69568          hole = false;
69569        }
69570
69571        // Add to the segment pathCoordinates and valueData
69572        segments[segments.length - 1].pathCoordinates.push(pathCoordinates[i], pathCoordinates[i + 1]);
69573        segments[segments.length - 1].valueData.push(valueData[i / 2]);
69574      }
69575    }
69576
69577    return segments;
69578  };
69579}(window, document, Chartist));
69580;/**
69581 * Chartist path interpolation functions.
69582 *
69583 * @module Chartist.Interpolation
69584 */
69585/* global Chartist */
69586(function(window, document, Chartist) {
69587  'use strict';
69588
69589  Chartist.Interpolation = {};
69590
69591  /**
69592   * This interpolation function does not smooth the path and the result is only containing lines and no curves.
69593   *
69594   * @example
69595   * var chart = new Chartist.Line('.ct-chart', {
69596   *   labels: [1, 2, 3, 4, 5],
69597   *   series: [[1, 2, 8, 1, 7]]
69598   * }, {
69599   *   lineSmooth: Chartist.Interpolation.none({
69600   *     fillHoles: false
69601   *   })
69602   * });
69603   *
69604   *
69605   * @memberof Chartist.Interpolation
69606   * @return {Function}
69607   */
69608  Chartist.Interpolation.none = function(options) {
69609    var defaultOptions = {
69610      fillHoles: false
69611    };
69612    options = Chartist.extend({}, defaultOptions, options);
69613    return function none(pathCoordinates, valueData) {
69614      var path = new Chartist.Svg.Path();
69615      var hole = true;
69616
69617      for(var i = 0; i < pathCoordinates.length; i += 2) {
69618        var currX = pathCoordinates[i];
69619        var currY = pathCoordinates[i + 1];
69620        var currData = valueData[i / 2];
69621
69622        if(Chartist.getMultiValue(currData.value) !== undefined) {
69623
69624          if(hole) {
69625            path.move(currX, currY, false, currData);
69626          } else {
69627            path.line(currX, currY, false, currData);
69628          }
69629
69630          hole = false;
69631        } else if(!options.fillHoles) {
69632          hole = true;
69633        }
69634      }
69635
69636      return path;
69637    };
69638  };
69639
69640  /**
69641   * Simple smoothing creates horizontal handles that are positioned with a fraction of the length between two data points. You can use the divisor option to specify the amount of smoothing.
69642   *
69643   * Simple smoothing can be used instead of `Chartist.Smoothing.cardinal` if you'd like to get rid of the artifacts it produces sometimes. Simple smoothing produces less flowing lines but is accurate by hitting the points and it also doesn't swing below or above the given data point.
69644   *
69645   * All smoothing functions within Chartist are factory functions that accept an options parameter. The simple interpolation function accepts one configuration parameter `divisor`, between 1 and ∞, which controls the smoothing characteristics.
69646   *
69647   * @example
69648   * var chart = new Chartist.Line('.ct-chart', {
69649   *   labels: [1, 2, 3, 4, 5],
69650   *   series: [[1, 2, 8, 1, 7]]
69651   * }, {
69652   *   lineSmooth: Chartist.Interpolation.simple({
69653   *     divisor: 2,
69654   *     fillHoles: false
69655   *   })
69656   * });
69657   *
69658   *
69659   * @memberof Chartist.Interpolation
69660   * @param {Object} options The options of the simple interpolation factory function.
69661   * @return {Function}
69662   */
69663  Chartist.Interpolation.simple = function(options) {
69664    var defaultOptions = {
69665      divisor: 2,
69666      fillHoles: false
69667    };
69668    options = Chartist.extend({}, defaultOptions, options);
69669
69670    var d = 1 / Math.max(1, options.divisor);
69671
69672    return function simple(pathCoordinates, valueData) {
69673      var path = new Chartist.Svg.Path();
69674      var prevX, prevY, prevData;
69675
69676      for(var i = 0; i < pathCoordinates.length; i += 2) {
69677        var currX = pathCoordinates[i];
69678        var currY = pathCoordinates[i + 1];
69679        var length = (currX - prevX) * d;
69680        var currData = valueData[i / 2];
69681
69682        if(currData.value !== undefined) {
69683
69684          if(prevData === undefined) {
69685            path.move(currX, currY, false, currData);
69686          } else {
69687            path.curve(
69688              prevX + length,
69689              prevY,
69690              currX - length,
69691              currY,
69692              currX,
69693              currY,
69694              false,
69695              currData
69696            );
69697          }
69698
69699          prevX = currX;
69700          prevY = currY;
69701          prevData = currData;
69702        } else if(!options.fillHoles) {
69703          prevX = currX = prevData = undefined;
69704        }
69705      }
69706
69707      return path;
69708    };
69709  };
69710
69711  /**
69712   * Cardinal / Catmull-Rome spline interpolation is the default smoothing function in Chartist. It produces nice results where the splines will always meet the points. It produces some artifacts though when data values are increased or decreased rapidly. The line may not follow a very accurate path and if the line should be accurate this smoothing function does not produce the best results.
69713   *
69714   * Cardinal splines can only be created if there are more than two data points. If this is not the case this smoothing will fallback to `Chartist.Smoothing.none`.
69715   *
69716   * All smoothing functions within Chartist are factory functions that accept an options parameter. The cardinal interpolation function accepts one configuration parameter `tension`, between 0 and 1, which controls the smoothing intensity.
69717   *
69718   * @example
69719   * var chart = new Chartist.Line('.ct-chart', {
69720   *   labels: [1, 2, 3, 4, 5],
69721   *   series: [[1, 2, 8, 1, 7]]
69722   * }, {
69723   *   lineSmooth: Chartist.Interpolation.cardinal({
69724   *     tension: 1,
69725   *     fillHoles: false
69726   *   })
69727   * });
69728   *
69729   * @memberof Chartist.Interpolation
69730   * @param {Object} options The options of the cardinal factory function.
69731   * @return {Function}
69732   */
69733  Chartist.Interpolation.cardinal = function(options) {
69734    var defaultOptions = {
69735      tension: 1,
69736      fillHoles: false
69737    };
69738
69739    options = Chartist.extend({}, defaultOptions, options);
69740
69741    var t = Math.min(1, Math.max(0, options.tension)),
69742      c = 1 - t;
69743
69744    return function cardinal(pathCoordinates, valueData) {
69745      // First we try to split the coordinates into segments
69746      // This is necessary to treat "holes" in line charts
69747      var segments = Chartist.splitIntoSegments(pathCoordinates, valueData, {
69748        fillHoles: options.fillHoles
69749      });
69750
69751      if(!segments.length) {
69752        // If there were no segments return 'Chartist.Interpolation.none'
69753        return Chartist.Interpolation.none()([]);
69754      } else if(segments.length > 1) {
69755        // If the split resulted in more that one segment we need to interpolate each segment individually and join them
69756        // afterwards together into a single path.
69757          var paths = [];
69758        // For each segment we will recurse the cardinal function
69759        segments.forEach(function(segment) {
69760          paths.push(cardinal(segment.pathCoordinates, segment.valueData));
69761        });
69762        // Join the segment path data into a single path and return
69763        return Chartist.Svg.Path.join(paths);
69764      } else {
69765        // If there was only one segment we can proceed regularly by using pathCoordinates and valueData from the first
69766        // segment
69767        pathCoordinates = segments[0].pathCoordinates;
69768        valueData = segments[0].valueData;
69769
69770        // If less than two points we need to fallback to no smoothing
69771        if(pathCoordinates.length <= 4) {
69772          return Chartist.Interpolation.none()(pathCoordinates, valueData);
69773        }
69774
69775        var path = new Chartist.Svg.Path().move(pathCoordinates[0], pathCoordinates[1], false, valueData[0]),
69776          z;
69777
69778        for (var i = 0, iLen = pathCoordinates.length; iLen - 2 * !z > i; i += 2) {
69779          var p = [
69780            {x: +pathCoordinates[i - 2], y: +pathCoordinates[i - 1]},
69781            {x: +pathCoordinates[i], y: +pathCoordinates[i + 1]},
69782            {x: +pathCoordinates[i + 2], y: +pathCoordinates[i + 3]},
69783            {x: +pathCoordinates[i + 4], y: +pathCoordinates[i + 5]}
69784          ];
69785          if (z) {
69786            if (!i) {
69787              p[0] = {x: +pathCoordinates[iLen - 2], y: +pathCoordinates[iLen - 1]};
69788            } else if (iLen - 4 === i) {
69789              p[3] = {x: +pathCoordinates[0], y: +pathCoordinates[1]};
69790            } else if (iLen - 2 === i) {
69791              p[2] = {x: +pathCoordinates[0], y: +pathCoordinates[1]};
69792              p[3] = {x: +pathCoordinates[2], y: +pathCoordinates[3]};
69793            }
69794          } else {
69795            if (iLen - 4 === i) {
69796              p[3] = p[2];
69797            } else if (!i) {
69798              p[0] = {x: +pathCoordinates[i], y: +pathCoordinates[i + 1]};
69799            }
69800          }
69801
69802          path.curve(
69803            (t * (-p[0].x + 6 * p[1].x + p[2].x) / 6) + (c * p[2].x),
69804            (t * (-p[0].y + 6 * p[1].y + p[2].y) / 6) + (c * p[2].y),
69805            (t * (p[1].x + 6 * p[2].x - p[3].x) / 6) + (c * p[2].x),
69806            (t * (p[1].y + 6 * p[2].y - p[3].y) / 6) + (c * p[2].y),
69807            p[2].x,
69808            p[2].y,
69809            false,
69810            valueData[(i + 2) / 2]
69811          );
69812        }
69813
69814        return path;
69815      }
69816    };
69817  };
69818
69819  /**
69820   * Monotone Cubic spline interpolation produces a smooth curve which preserves monotonicity. Unlike cardinal splines, the curve will not extend beyond the range of y-values of the original data points.
69821   *
69822   * Monotone Cubic splines can only be created if there are more than two data points. If this is not the case this smoothing will fallback to `Chartist.Smoothing.none`.
69823   *
69824   * The x-values of subsequent points must be increasing to fit a Monotone Cubic spline. If this condition is not met for a pair of adjacent points, then there will be a break in the curve between those data points.
69825   *
69826   * All smoothing functions within Chartist are factory functions that accept an options parameter.
69827   *
69828   * @example
69829   * var chart = new Chartist.Line('.ct-chart', {
69830   *   labels: [1, 2, 3, 4, 5],
69831   *   series: [[1, 2, 8, 1, 7]]
69832   * }, {
69833   *   lineSmooth: Chartist.Interpolation.monotoneCubic({
69834   *     fillHoles: false
69835   *   })
69836   * });
69837   *
69838   * @memberof Chartist.Interpolation
69839   * @param {Object} options The options of the monotoneCubic factory function.
69840   * @return {Function}
69841   */
69842  Chartist.Interpolation.monotoneCubic = function(options) {
69843    var defaultOptions = {
69844      fillHoles: false
69845    };
69846
69847    options = Chartist.extend({}, defaultOptions, options);
69848
69849    return function monotoneCubic(pathCoordinates, valueData) {
69850      // First we try to split the coordinates into segments
69851      // This is necessary to treat "holes" in line charts
69852      var segments = Chartist.splitIntoSegments(pathCoordinates, valueData, {
69853        fillHoles: options.fillHoles,
69854        increasingX: true
69855      });
69856
69857      if(!segments.length) {
69858        // If there were no segments return 'Chartist.Interpolation.none'
69859        return Chartist.Interpolation.none()([]);
69860      } else if(segments.length > 1) {
69861        // If the split resulted in more that one segment we need to interpolate each segment individually and join them
69862        // afterwards together into a single path.
69863          var paths = [];
69864        // For each segment we will recurse the monotoneCubic fn function
69865        segments.forEach(function(segment) {
69866          paths.push(monotoneCubic(segment.pathCoordinates, segment.valueData));
69867        });
69868        // Join the segment path data into a single path and return
69869        return Chartist.Svg.Path.join(paths);
69870      } else {
69871        // If there was only one segment we can proceed regularly by using pathCoordinates and valueData from the first
69872        // segment
69873        pathCoordinates = segments[0].pathCoordinates;
69874        valueData = segments[0].valueData;
69875
69876        // If less than three points we need to fallback to no smoothing
69877        if(pathCoordinates.length <= 4) {
69878          return Chartist.Interpolation.none()(pathCoordinates, valueData);
69879        }
69880
69881        var xs = [],
69882          ys = [],
69883          i,
69884          n = pathCoordinates.length / 2,
69885          ms = [],
69886          ds = [], dys = [], dxs = [],
69887          path;
69888
69889        // Populate x and y coordinates into separate arrays, for readability
69890
69891        for(i = 0; i < n; i++) {
69892          xs[i] = pathCoordinates[i * 2];
69893          ys[i] = pathCoordinates[i * 2 + 1];
69894        }
69895
69896        // Calculate deltas and derivative
69897
69898        for(i = 0; i < n - 1; i++) {
69899          dys[i] = ys[i + 1] - ys[i];
69900          dxs[i] = xs[i + 1] - xs[i];
69901          ds[i] = dys[i] / dxs[i];
69902        }
69903
69904        // Determine desired slope (m) at each point using Fritsch-Carlson method
69905        // See: http://math.stackexchange.com/questions/45218/implementation-of-monotone-cubic-interpolation
69906
69907        ms[0] = ds[0];
69908        ms[n - 1] = ds[n - 2];
69909
69910        for(i = 1; i < n - 1; i++) {
69911          if(ds[i] === 0 || ds[i - 1] === 0 || (ds[i - 1] > 0) !== (ds[i] > 0)) {
69912            ms[i] = 0;
69913          } else {
69914            ms[i] = 3 * (dxs[i - 1] + dxs[i]) / (
69915              (2 * dxs[i] + dxs[i - 1]) / ds[i - 1] +
69916              (dxs[i] + 2 * dxs[i - 1]) / ds[i]);
69917
69918            if(!isFinite(ms[i])) {
69919              ms[i] = 0;
69920            }
69921          }
69922        }
69923
69924        // Now build a path from the slopes
69925
69926        path = new Chartist.Svg.Path().move(xs[0], ys[0], false, valueData[0]);
69927
69928        for(i = 0; i < n - 1; i++) {
69929          path.curve(
69930            // First control point
69931            xs[i] + dxs[i] / 3,
69932            ys[i] + ms[i] * dxs[i] / 3,
69933            // Second control point
69934            xs[i + 1] - dxs[i] / 3,
69935            ys[i + 1] - ms[i + 1] * dxs[i] / 3,
69936            // End point
69937            xs[i + 1],
69938            ys[i + 1],
69939
69940            false,
69941            valueData[i + 1]
69942          );
69943        }
69944
69945        return path;
69946      }
69947    };
69948  };
69949
69950  /**
69951   * Step interpolation will cause the line chart to move in steps rather than diagonal or smoothed lines. This interpolation will create additional points that will also be drawn when the `showPoint` option is enabled.
69952   *
69953   * All smoothing functions within Chartist are factory functions that accept an options parameter. The step interpolation function accepts one configuration parameter `postpone`, that can be `true` or `false`. The default value is `true` and will cause the step to occur where the value actually changes. If a different behaviour is needed where the step is shifted to the left and happens before the actual value, this option can be set to `false`.
69954   *
69955   * @example
69956   * var chart = new Chartist.Line('.ct-chart', {
69957   *   labels: [1, 2, 3, 4, 5],
69958   *   series: [[1, 2, 8, 1, 7]]
69959   * }, {
69960   *   lineSmooth: Chartist.Interpolation.step({
69961   *     postpone: true,
69962   *     fillHoles: false
69963   *   })
69964   * });
69965   *
69966   * @memberof Chartist.Interpolation
69967   * @param options
69968   * @returns {Function}
69969   */
69970  Chartist.Interpolation.step = function(options) {
69971    var defaultOptions = {
69972      postpone: true,
69973      fillHoles: false
69974    };
69975
69976    options = Chartist.extend({}, defaultOptions, options);
69977
69978    return function step(pathCoordinates, valueData) {
69979      var path = new Chartist.Svg.Path();
69980
69981      var prevX, prevY, prevData;
69982
69983      for (var i = 0; i < pathCoordinates.length; i += 2) {
69984        var currX = pathCoordinates[i];
69985        var currY = pathCoordinates[i + 1];
69986        var currData = valueData[i / 2];
69987
69988        // If the current point is also not a hole we can draw the step lines
69989        if(currData.value !== undefined) {
69990          if(prevData === undefined) {
69991            path.move(currX, currY, false, currData);
69992          } else {
69993            if(options.postpone) {
69994              // If postponed we should draw the step line with the value of the previous value
69995              path.line(currX, prevY, false, prevData);
69996            } else {
69997              // If not postponed we should draw the step line with the value of the current value
69998              path.line(prevX, currY, false, currData);
69999            }
70000            // Line to the actual point (this should only be a Y-Axis movement
70001            path.line(currX, currY, false, currData);
70002          }
70003
70004          prevX = currX;
70005          prevY = currY;
70006          prevData = currData;
70007        } else if(!options.fillHoles) {
70008          prevX = prevY = prevData = undefined;
70009        }
70010      }
70011
70012      return path;
70013    };
70014  };
70015
70016}(window, document, Chartist));
70017;/**
70018 * A very basic event module that helps to generate and catch events.
70019 *
70020 * @module Chartist.Event
70021 */
70022/* global Chartist */
70023(function (window, document, Chartist) {
70024  'use strict';
70025
70026  Chartist.EventEmitter = function () {
70027    var handlers = [];
70028
70029    /**
70030     * Add an event handler for a specific event
70031     *
70032     * @memberof Chartist.Event
70033     * @param {String} event The event name
70034     * @param {Function} handler A event handler function
70035     */
70036    function addEventHandler(event, handler) {
70037      handlers[event] = handlers[event] || [];
70038      handlers[event].push(handler);
70039    }
70040
70041    /**
70042     * Remove an event handler of a specific event name or remove all event handlers for a specific event.
70043     *
70044     * @memberof Chartist.Event
70045     * @param {String} event The event name where a specific or all handlers should be removed
70046     * @param {Function} [handler] An optional event handler function. If specified only this 
70046specific handler will be removed and otherwise all handlers are removed.
70047     */
70048    function removeEventHandler(event, handler) {
70049      // Only do something if there are event handlers with this name existing
70050      if(handlers[event]) {
70051        // If handler is set we will look for a specific handler and only remove this
70052        if(handler) {
70053          handlers[event].splice(handlers[event].indexOf(handler), 1);
70054          if(handlers[event].length === 0) {
70055            delete handlers[event];
70056          }
70057        } else {
70058          // If no handler is specified we remove all handlers for this event
70059          delete handlers[event];
70060        }
70061      }
70062    }
70063
70064    /**
70065     * Use this function to emit an event. All handlers that are listening for this event will be triggered with the data parameter.
70066     *
70067     * @memberof Chartist.Event
70068     * @param {String} event The event name that should be triggered
70069     * @param {*} data Arbitrary data that will be passed to the event handler callback functions
70070     */
70071    function emit(event, data) {
70072      // Only do something if there are event handlers with this name existing
70073      if(handlers[event]) {
70074        handlers[event].forEach(function(handler) {
70075          handler(data);
70076        });
70077      }
70078
70079      // Emit event to star event handlers
70080      if(handlers['*']) {
70081        handlers['*'].forEach(function(starHandler) {
70082          starHandler(event, data);
70083        });
70084      }
70085    }
70086
70087    return {
70088      addEventHandler: addEventHandler,
70089      removeEventHandler: removeEventHandler,
70090      emit: emit
70091    };
70092  };
70093
70094}(window, document, Chartist));
70095;/**
70096 * This module provides some basic prototype inheritance utilities.
70097 *
70098 * @module Chartist.Class
70099 */
70100/* global Chartist */
70101(function(window, document, Chartist) {
70102  'use strict';
70103
70104  function listToArray(list) {
70105    var arr = [];
70106    if (list.length) {
70107      for (var i = 0; i < list.length; i++) {
70108        arr.push(list[i]);
70109      }
70110    }
70111    return arr;
70112  }
70113
70114  /**
70115   * Method to extend from current prototype.
70116   *
70117   * @memberof Chartist.Class
70118   * @param {Object} properties The object that serves as definition for the prototype that gets created for the new class. This object should always contain a constructor property that is the desired constructor for the newly created class.
70119   * @param {Object} [superProtoOverride] By default extens will use the current class prototype or Chartist.class. With this parameter you can specify any super prototype that will be used.
70120   * @return {Function} Constructor function of the new class
70121   *
70122   * @example
70123   * var Fruit = Class.extend({
70124     * color: undefined,
70125     *   sugar: undefined,
70126     *
70127     *   constructor: function(color, sugar) {
70128     *     this.color = color;
70129     *     this.sugar = sugar;
70130     *   },
70131     *
70132     *   eat: function() {
70133     *     this.sugar = 0;
70134     *     return this;
70135     *   }
70136     * });
70137   *
70138   * var Banana = Fruit.extend({
70139     *   length: undefined,
70140     *
70141     *   constructor: function(length, sugar) {
70142     *     Banana.super.constructor.call(this, 'Yellow', sugar);
70143     *     this.length = length;
70144     *   }
70145     * });
70146   *
70147   * var banana = new Banana(20, 40);
70148   * console.log('banana instanceof Fruit', banana instanceof Fruit);
70149   * console.log('Fruit is prototype of banana', Fruit.prototype.isPrototypeOf(banana));
70150   * console.log('bananas prototype is Fruit', Object.getPrototypeOf(banana) === Fruit.prototype);
70151   * console.log(banana.sugar);
70152   * console.log(banana.eat().sugar);
70153   * console.log(banana.color);
70154   */
70155  function extend(properties, superProtoOverride) {
70156    var superProto = superProtoOverride || this.prototype || Chartist.Class;
70157    var proto = Object.create(superProto);
70158
70159    Chartist.Class.cloneDefinitions(proto, properties);
70160
70161    var constr = function() {
70162      var fn = proto.constructor || function () {},
70163        instance;
70164
70165      // If this is linked to the Chartist namespace the constructor was not called with new
70166      // To provide a fallback we will instantiate here and return the instance
70167      instance = this === Chartist ? Object.create(proto) : this;
70168      fn.apply(instance, Array.prototype.slice.call(arguments, 0));
70169
70170      // If this constructor was not called with new we need to return the instance
70171      // This will not harm when the constructor has been called with new as the returned value is ignored
70172      return instance;
70173    };
70174
70175    constr.prototype = proto;
70176    constr.super = superProto;
70177    constr.extend = this.extend;
70178
70179    return constr;
70180  }
70181
70182  // Variable argument list clones args > 0 into args[0] and retruns modified args[0]
70183  function cloneDefinitions() {
70184    var args = listToArray(arguments);
70185    var target = args[0];
70186
70187    args.splice(1, args.length - 1).forEach(function (source) {
70188      Object.getOwnPropertyNames(source).forEach(function (propName) {
70189        // If this property already exist in target we delete it first
70190        delete target[propName];
70191        // Define the property with the descriptor from source
70192        Object.defineProperty(target, propName,
70193          Object.getOwnPropertyDescriptor(source, propName));
70194      });
70195    });
70196
70197    return target;
70198  }
70199
70200  Chartist.Class = {
70201    extend: extend,
70202    cloneDefinitions: cloneDefinitions
70203  };
70204
70205}(window, document, Chartist));
70206;/**
70207 * Base for all chart types. The methods in Chartist.Base are inherited to all chart types.
70208 *
70209 * @module Chartist.Base
70210 */
70211/* global Chartist */
70212(function(window, document, Chartist) {
70213  'use strict';
70214
70215  // TODO: Currently we need to re-draw the chart on window resize. This is usually very bad and will affect performance.
70216  // This is done because we can't work with relative coordinates when drawing the chart because SVG Path does not
70217  // work with relative positions yet. We need to check if we can do a viewBox hack to switch to percentage.
70218  // See http://mozilla.6506.n7.nabble.com/Specyfing-paths-with-percentages-unit-td247474.html
70219  // Update: can be done using the above method tested here: http://codepen.io/gionkunz/pen/KDvLj
70220  // The problem is with the label offsets that can't be converted into percentage and affecting the chart container
70221  /**
70222   * Updates the chart which currently does a full reconstruction of the SVG DOM
70223   *
70224   * @param {Object} [data] Optional data you'd like to set for the chart before it will update. If not specified the update method will use the data that is already configured with the chart.
70225   * @param {Object} [options] Optional options you'd like to add to the previous options for the chart before it will update. If not specified the update method will use the options that have been already configured with the chart.
70226   * @param {Boolean} [override] If set to true, the passed options will be used to extend the options that have been configured already. Otherwise the chart default options will be used as the base
70227   * @memberof Chartist.Base
70228   */
70229  function update(data, options, override) {
70230    if(data) {
70231      this.data = data || {};
70232      this.data.labels = this.data.labels || [];
70233      this.data.series = this.data.series || [];
70234      // Event for data transformation that allows to manipulate the data before it gets rendered in the charts
70235      this.eventEmitter.emit('data', {
70236        type: 'update',
70237        data: this.data
70238      });
70239    }
70240
70241    if(options) {
70242      this.options = Chartist.extend({}, override ? this.options : this.defaultOptions, options);
70243
70244      // If chartist was not initialized yet, we just set the options and leave the rest to the initialization
70245      // Otherwise we re-create the optionsProvider at this point
70246      if(!this.initializeTimeoutId) {
70247        this.optionsProvider.removeMediaQueryListeners();
70248        this.optionsProvider = Chartist.optionsProvider(this.options, this.responsiveOptions, this.eventEmitter);
70249      }
70250    }
70251
70252    // Only re-created the chart if it has been initialized yet
70253    if(!this.initializeTimeoutId) {
70254      this.createChart(this.optionsProvider.getCurrentOptions());
70255    }
70256
70257    // Return a reference to the chart object to chain up calls
70258    return this;
70259  }
70260
70261  /**
70262   * This method can be called on the API object of each chart and will un-register all event listeners that were added to other components. This currently includes a window.resize listener as well as media query listeners if any responsive options have been provided. Use this function if you need to destroy and recreate Chartist charts dynamically.
70263   *
70264   * @memberof Chartist.Base
70265   */
70266  function detach() {
70267    // Only detach if initialization already occurred on this chart. If this chart still hasn't initialized (therefore
70268    // the initializationTimeoutId is still a valid timeout reference, we will clear the timeout
70269    if(!this.initializeTimeoutId) {
70270      window.removeEventListener('resize', this.resizeListener);
70271      this.optionsProvider.removeMediaQueryListeners();
70272    } else {
70273      window.clearTimeout(this.initializeTimeoutId);
70274    }
70275
70276    return this;
70277  }
70278
70279  /**
70280   * Use this function to register event handlers. The handler callbacks are synchronous and will run in the main thread rather than the event loop.
70281   *
70282   * @memberof Chartist.Base
70283   * @param {String} event Name of the event. Check the examples for supported events.
70284   * @param {Function} handler The handler function that will be called when an event with the given name was emitted. This function will receive a data argument which contains event data. See the example for more details.
70285   */
70286  function on(event, handler) {
70287    this.eventEmitter.addEventHandler(event, handler);
70288    return this;
70289  }
70290
70291  /**
70292   * Use this function to un-register event handlers. If the handler function parameter is omitted all handlers for the given event will be un-registered.
70293   *
70294   * @memberof Chartist.Base
70295   * @param {String} event Name of the event for which a handler should be removed
70296   * @param {Function} [handler] The handler function that that was previously used to register a new event handler. This handler will be removed from the event handler list. If this parameter is omitted then all event handlers for the given event are removed from the list.
70297   */
70298  function off(event, handler) {
70299    this.eventEmitter.removeEventHandler(event, handler);
70300    return this;
70301  }
70302
70303  function initialize() {
70304    // Add window resize listener that re-creates the chart
70305    window.addEventListener('resize', this.resizeListener);
70306
70307    // Obtain current options based on matching media queries (if responsive options are given)
70308    // This will also register a listener that is re-creating the chart based on media changes
70309    this.optionsProvider = Chartist.optionsProvider(this.options, this.responsiveOptions, this.eventEmitter);
70310    // Register options change listener that will trigger a chart update
70311    this.eventEmitter.addEventHandler('optionsChanged', function() {
70312      this.update();
70313    }.bind(this));
70314
70315    // Before the first chart creation we need to register us with all plugins that are configured
70316    // Initialize all relevant plugins with our chart object and the plugin options specified in the config
70317    if(this.options.plugins) {
70318      this.options.plugins.forEach(function(plugin) {
70319        if(plugin instanceof Array) {
70320          plugin[0](this, plugin[1]);
70321        } else {
70322          plugin(this);
70323        }
70324      }.bind(this));
70325    }
70326
70327    // Event for data transformation that allows to manipulate the data before it gets rendered in the charts
70328    this.eventEmitter.emit('data', {
70329      type: 'initial',
70330      data: this.data
70331    });
70332
70333    // Create the first chart
70334    this.createChart(this.optionsProvider.getCurrentOptions());
70335
70336    // As chart is initialized from the event loop now we can reset our timeout reference
70337    // This is important if the chart gets initialized on the same element twice
70338    this.initializeTimeoutId = undefined;
70339  }
70340
70341  /**
70342   * Constructor of chart base class.
70343   *
70344   * @param query
70345   * @param data
70346   * @param defaultOptions
70347   * @param options
70348   * @param responsiveOptions
70349   * @constructor
70350   */
70351  function Base(query, data, defaultOptions, options, responsiveOptions) {
70352    this.container = Chartist.querySelector(query);
70353    this.data = data || {};
70354    this.data.labels = this.data.labels || [];
70355    this.data.series = this.data.series || [];
70356    this.defaultOptions = defaultOptions;
70357    this.options = options;
70358    this.responsiveOptions = responsiveOptions;
70359    this.eventEmitter = Chartist.EventEmitter();
70360    this.supportsForeignObject = Chartist.Svg.isSupported('Extensibility');
70361    this.supportsAnimations = Chartist.Svg.isSupported('AnimationEventsAttribute');
70362    this.resizeListener = function resizeListener(){
70363      this.update();
70364    }.bind(this);
70365
70366    if(this.container) {
70367      // If chartist was already initialized in this container we are detaching all event listeners first
70368      if(this.container.__chartist__) {
70369        this.container.__chartist__.detach();
70370      }
70371
70372      this.container.__chartist__ = this;
70373    }
70374
70375    // Using event loop for first draw to make it possible to register event listeners in the same call stack where
70376    // the chart was created.
70377    this.initializeTimeoutId = setTimeout(initialize.bind(this), 0);
70378  }
70379
70380  // Creating the chart base class
70381  Chartist.Base = Chartist.Class.extend({
70382    constructor: Base,
70383    optionsProvider: undefined,
70384    container: undefined,
70385    svg: undefined,
70386    eventEmitter: undefined,
70387    createChart: function() {
70388      throw new Error('Base chart type can\'t be instantiated!');
70389    },
70390    update: update,
70391    detach: detach,
70392    on: on,
70393    off: off,
70394    version: Chartist.version,
70395    supportsForeignObject: false
70396  });
70397
70398}(window, document, Chartist));
70399;/**
70400 * Chartist SVG module for simple SVG DOM abstraction
70401 *
70402 * @module Chartist.Svg
70403 */
70404/* global Chartist */
70405(function(window, document, Chartist) {
70406  'use strict';
70407
70408  /**
70409   * Chartist.Svg creates a new SVG object wrapper with a starting element. You can use the wrapper to fluently create sub-elements and modify them.
70410   *
70411   * @memberof Chartist.Svg
70412   * @constructor
70413   * @param {String|Element} name The name of the SVG element to create or an SVG dom element which should be wrapped into Chartist.Svg
70414   * @param {Object} attributes An object with properties that will be added as attributes to the SVG element that is created. Attributes with undefined values will not be added.
70415   * @param {String} className This class or class list will be added to the SVG element
70416   * @param {Object} parent The parent SVG wrapper object where this newly created wrapper and it's element will be attached to as child
70417   * @param {Boolean} insertFirst If this param is set to true in conjunction with a parent element the newly created element will be added as first child element in the parent element
70418   */
70419  function Svg(name, attributes, className, parent, insertFirst) {
70420    // If Svg is getting called with an SVG element we just return the wrapper
70421    if(name instanceof Element) {
70422      this._node = name;
70423    } else {
70424      this._node = document.createElementNS(Chartist.namespaces.svg, name);
70425
70426      // If this is an SVG element created then custom namespace
70427      if(name === 'svg') {
70428        this.attr({
70429          'xmlns:ct': Chartist.namespaces.ct
70430        });
70431      }
70432    }
70433
70434    if(attributes) {
70435      this.attr(attributes);
70436    }
70437
70438    if(className) {
70439      this.addClass(className);
70440    }
70441
70442    if(parent) {
70443      if (insertFirst && parent._node.firstChild) {
70444        parent._node.insertBefore(this._node, parent._node.firstChild);
70445      } else {
70446        parent._node.appendChild(this._node);
70447      }
70448    }
70449  }
70450
70451  /**
70452   * Set attributes on the current SVG element of the wrapper you're currently working on.
70453   *
70454   * @memberof Chartist.Svg
70455   * @param {Object|String} attributes An object with properties that will be added as attributes to the SVG element that is created. Attributes with undefined values will not be added. If this parameter is a String then the function is used as a getter and will return the attribute value.
70456   * @param {String} [ns] If specified, the attribute will be obtained using getAttributeNs. In order to write namepsaced attributes you can use the namespace:attribute notation within the attributes object.
70457   * @return {Object|String} The current wrapper object will be returned so it can be used for chaining or the attribute value if used as getter function.
70458   */
70459  function attr(attributes, ns) {
70460    if(typeof attributes === 'string') {
70461      if(ns) {
70462        return this._node.getAttributeNS(ns, attributes);
70463      } else {
70464        return this._node.getAttribute(attributes);
70465      }
70466    }
70467
70468    Object.keys(attributes).forEach(function(key) {
70469      // If the attribute value is undefined we can skip this one
70470      if(attributes[key] === undefined) {
70471        return;
70472      }
70473
70474      if (key.indexOf(':') !== -1) {
70475        var namespacedAttribute = key.split(':');
70476        this._node.setAttributeNS(Chartist.namespaces[namespacedAttribute[0]], key, attributes[key]);
70477      } else {
70478        this._node.setAttribute(key, attributes[key]);
70479      }
70480    }.bind(this));
70481
70482    return this;
70483  }
70484
70485  /**
70486   * Create a new SVG element whose wrapper object will be selected for further operations. This way you can also create nested groups easily.
70487   *
70488   * @memberof Chartist.Svg
70489   * @param {String} name The name of the SVG element that should be created as child element of the currently selected element wrapper
70490   * @param {Object} [attributes] An object with properties that will be added as attributes to the SVG element that is created. Attributes with undefined values will not be added.
70491   * @param {String} [className] This class or class list will be added to the SVG element
70492   * @param {Boolean} [insertFirst] If this param is set to true in conjunction with a parent element the newly created element will be added as first child element in the parent element
70493   * @return {Chartist.Svg} Returns a Chartist.Svg wrapper object that can be used to modify the containing SVG data
70494   */
70495  function elem(name, attributes, className, insertFirst) {
70496    return new Chartist.Svg(name, attributes, className, this, insertFirst);
70497  }
70498
70499  /**
70500   * Returns the parent Chartist.SVG wrapper object
70501   *
70502   * @memberof Chartist.Svg
70503   * @return {Chartist.Svg} Returns a Chartist.Svg wrapper around the parent node of the current node. If the parent node is not existing or it's not an SVG node then this function will return null.
70504   */
70505  function parent() {
70506    return this._node.parentNode instanceof SVGElement ? new Chartist.Svg(this._node.parentNode) : null;
70507  }
70508
70509  /**
70510   * This method returns a Chartist.Svg wrapper around the root SVG element of the current tree.
70511   *
70512   * @memberof Chartist.Svg
70513   * @return {Chartist.Svg} The root SVG element wrapped in a Chartist.Svg element
70514   */
70515  function root() {
70516    var node = this._node;
70517    while(node.nodeName !== 'svg') {
70518      node = node.parentNode;
70519    }
70520    return new Chartist.Svg(node);
70521  }
70522
70523  /**
70524   * Find the first child SVG element of the current element that matches a CSS selector. The returned object is a Chartist.Svg wrapper.
70525   *
70526   * @memberof Chartist.Svg
70527   * @param {String} selector A CSS selector that is used to query for child SVG elements
70528   * @return {Chartist.Svg} The SVG wrapper for the element found or null if no element was found
70529   */
70530  function querySelector(selector) {
70531    var foundNode = this._node.querySelector(selector);
70532    return foundNode ? new Chartist.Svg(foundNode) : null;
70533  }
70534
70535  /**
70536   * Find the all child SVG elements of the current element that match a CSS selector. The returned object is a Chartist.Svg.List wrapper.
70537   *
70538   * @memberof Chartist.Svg
70539   * @param {String} selector A CSS selector that is used to query for child SVG elements
70540   * @return {Chartist.Svg.List} The SVG wrapper list for the element found or null if no element was found
70541   */
70542  function querySelectorAll(selector) {
70543    var foundNodes = this._node.querySelectorAll(selector);
70544    return foundNodes.length ? new Chartist.Svg.List(foundNodes) : null;
70545  }
70546
70547  /**
70548   * Returns the underlying SVG node for the current element.
70549   *
70550   * @memberof Chartist.Svg
70551   * @returns {Node}
70552   */
70553  function getNode() {
70554    return this._node;
70555  }
70556
70557  /**
70558   * This method creates a foreignObject (see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/foreignObject) that allows to embed HTML content into a SVG graphic. With the help of foreignObjects you can enable the usage of regular HTML elements inside of SVG where they are subject for SVG positioning and transformation but the Browser will use the HTML rendering capabilities for the containing DOM.
70559   *
70560   * @memberof Chartist.Svg
70561   * @param {Node|String} content The DOM Node, or HTML string that will be converted to a DOM Node, that is then placed into and wrapped by the foreignObject
70562   * @param {String} [attributes] An object with properties that will be added as attributes to the foreignObject element that is created. Attributes with undefined values will not be added.
70563   * @param {String} [className] This class or class list will be added to the SVG element
70564   * @param {Boolean} [insertFirst] Specifies if the foreignObject should be inserted as first child
70565   * @return {Chartist.Svg} New wrapper object that wraps the foreignObject element
70566   */
70567  function foreignObject(content, attributes, className, insertFirst) {
70568    // If content is string then we convert it to DOM
70569    // TODO: Handle case where content is not a string nor a DOM Node
70570    if(typeof content === 'string') {
70571      var container = document.createElement('div');
70572      container.innerHTML = content;
70573      content = container.firstChild;
70574    }
70575
70576    // Adding namespace to content element
70577    content.setAttribute('xmlns', Chartist.namespaces.xmlns);
70578
70579    // Creating the foreignObject without required extension attribute (as described here
70580    // http://www.w3.org/TR/SVG/extend.html#ForeignObjectElement)
70581    var fnObj = this.elem('foreignObject', attributes, className, insertFirst);
70582
70583    // Add content to foreignObjectElement
70584    fnObj._node.appendChild(content);
70585
70586    return fnObj;
70587  }
70588
70589  /**
70590   * This method adds a new text element to the current Chartist.Svg wrapper.
70591   *
70592   * @memberof Chartist.Svg
70593   * @param {String} t The text that should be added to the text element that is created
70594   * @return {Chartist.Svg} The same wrapper object that was used to add the newly created element
70595   */
70596  function text(t) {
70597    this._node.appendChild(document.createTextNode(t));
70598    return this;
70599  }
70600
70601  /**
70602   * This method will clear all child nodes of the current wrapper object.
70603   *
70604   * @memberof Chartist.Svg
70605   * @return {Chartist.Svg} The same wrapper object that got emptied
70606   */
70607  function empty() {
70608    while (this._node.firstChild) {
70609      this._node.removeChild(this._node.firstChild);
70610    }
70611
70612    return this;
70613  }
70614
70615  /**
70616   * This method will cause the current wrapper to remove itself from its parent wrapper. Use this method if you'd like to get rid of an element in a given DOM structure.
70617   *
70618   * @memberof Chartist.Svg
70619   * @return {Chartist.Svg} The parent wrapper object of the element that got removed
70620   */
70621  function remove() {
70622    this._node.parentNode.removeChild(this._node);
70623    return this.parent();
70624  }
70625
70626  /**
70627   * This method will replace the element with a new element that can be created outside of the current DOM.
70628   *
70629   * @memberof Chartist.Svg
70630   * @param {Chartist.Svg} newElement The new Chartist.Svg object that will be used to replace the current wrapper object
70631   * @return {Chartist.Svg} The wrapper of the new element
70632   */
70633  function replace(newElement) {
70634    this._node.parentNode.replaceChild(newElement._node, this._node);
70635    return newElement;
70636  }
70637
70638  /**
70639   * This method will append an element to the current element as a child.
70640   *
70641   * @memberof Chartist.Svg
70642   * @param {Chartist.Svg} element The Chartist.Svg element that should be added as a child
70643   * @param {Boolean} [insertFirst] Specifies if the element should be inserted as first child
70644   * @return {Chartist.Svg} The wrapper of the appended object
70645   */
70646  function append(element, insertFirst) {
70647    if(insertFirst && this._node.firstChild) {
70648      this._node.insertBefore(element._node, this._node.firstChild);
70649    } else {
70650      this._node.appendChild(element._node);
70651    }
70652
70653    return this;
70654  }
70655
70656  /**
70657   * Returns an array of class names that are attached to the current wrapper element. This method can not be chained further.
70658   *
70659   * @memberof Chartist.Svg
70660   * @return {Array} A list of classes or an empty array if there are no classes on the current element
70661   */
70662  function classes() {
70663    return this._node.getAttribute('class') ? this._node.getAttribute('class').trim().split(/\s+/) : [];
70664  }
70665
70666  /**
70667   * Adds one or a space separated list of classes to the current element and ensures the classes are only existing once.
70668   *
70669   * @memberof Chartist.Svg
70670   * @param {String} names A white space separated list of class names
70671   * @return {Chartist.Svg} The wrapper of the current element
70672   */
70673  function addClass(names) {
70674    this._node.setAttribute('class',
70675      this.classes(this._node)
70676        .concat(names.trim().split(/\s+/))
70677        .filter(function(elem, pos, self) {
70678          return self.indexOf(elem) === pos;
70679        }).join(' ')
70680    );
70681
70682    return this;
70683  }
70684
70685  /**
70686   * Removes one or a space separated list of classes from the current element.
70687   *
70688   * @memberof Chartist.Svg
70689   * @param {String} names A white space separated list of class names
70690   * @return {Chartist.Svg} The wrapper of the current element
70691   */
70692  function removeClass(names) {
70693    var removedClasses = names.trim().split(/\s+/);
70694
70695    this._node.setAttribute('class', this.classes(this._node).filter(function(name) {
70696      return removedClasses.indexOf(name) === -1;
70697    }).join(' '));
70698
70699    return this;
70700  }
70701
70702  /**
70703   * Removes all classes from the current element.
70704   *
70705   * @memberof Chartist.Svg
70706   * @return {Chartist.Svg} The wrapper of the current element
70707   */
70708  function removeAllClasses() {
70709    this._node.setAttribute('class', '');
70710
70711    return this;
70712  }
70713
70714  /**
70715   * Get element height using `getBoundingClientRect`
70716   *
70717   * @memberof Chartist.Svg
70718   * @return {Number} The elements height in pixels
70719   */
70720  function height() {
70721    return this._node.getBoundingClientRect().height;
70722  }
70723
70724  /**
70725   * Get element width using `getBoundingClientRect`
70726   *
70727   * @memberof Chartist.Core
70728   * @return {Number} The elements width in pixels
70729   */
70730  function width() {
70731    return this._node.getBoundingClientRect().width;
70732  }
70733
70734  /**
70735   * The animate function lets you animate the current element with SMIL animations. You can add animations for multiple attributes at the same time by using an animation definition object. This object should contain SMIL animation attributes. Please refer to http://www.w3.org/TR/SVG/animate.html for a detailed specification about the available animation attributes. Additionally an easing property can be passed in the animation definition object. This can be a string with a name of an easing function in `Chartist.Svg.Easing` or an array with four numbers specifying a cubic Bézier curve.
70736   * **An animations object could look like this:**
70737   * ```javascript
70738   * element.animate({
70739   *   opacity: {
70740   *     dur: 1000,
70741   *     from: 0,
70742   *     to: 1
70743   *   },
70744   *   x1: {
70745   *     dur: '1000ms',
70746   *     from: 100,
70747   *     to: 200,
70748   *     easing: 'easeOutQuart'
70749   *   },
70750   *   y1: {
70751   *     dur: '2s',
70752   *     from: 0,
70753   *     to: 100
70754   *   }
70755   * });
70756   * ```
70757   * **Automatic unit conversion**
70758   * For the `dur` and the `begin` animate attribute you can also omit a unit by passing a number. The number will automatically be converted to milli seconds.
70759   * **Guided mode**
70760   * The default behavior of SMIL animations with offset using the `begin` attribute is that the attribute will keep it's original value until the animation starts. Mostly this behavior is not desired as you'd like to have your element attributes already initialized with the animation `from` value even before the animation starts. Also if you don't specify `fill="freeze"` on an animate element or if you delete the animation after it's done (which is done in guided mode) the attribute will switch back to the initial value. This behavior is also not desired when performing simple one-time animations. For one-time animations you'd want to trigger animations immediately instead of relative to the document begin time. That's why in guided mode Chartist.Svg will also use the `begin` property to schedule a timeout and manually start the animation after the timeout. If you're using multiple SMIL definition objects for an attribute (in an array), guided mode will be disabled for this attribute, even if you explicitly enabled it.
70761   * If guided mode is enabled the following behavior is added:
70762   * - Before the animation starts (even when delayed with `begin`) the animated attribute will be set already to the `from` value of the animation
70763   * - `begin` is explicitly set to `indefinite` so it can be started manually without relying on document begin time (creation)
70764   * - The animate element will be forced to use `fill="freeze"`
70765   * - The animation will be triggered with `beginElement()` in a timeout where `begin` of the definition object is interpreted in milli seconds. If no `begin` was specified the timeout is triggered immediately.
70766   * - After the animation the element attribute value will be set to the `to` value of the animation
70767   * - The animate element is deleted from the DOM
70768   *
70769   * @memberof Chartist.Svg
70770   * @param {Object} animations An animations object where the property keys are the attributes you'd like to animate. The properties should be objects again that contain the SMIL animation attributes (usually begin, dur, from, and to). The property begin and dur is auto converted (see Automatic unit conversion). You can also schedule multiple animations for the same attribute by passing an Array of SMIL definition objects. Attributes that contain an array of SMIL definition objects will not be executed in guided mode.
70771   * @param {Boolean} guided Specify if guided mode should be activated for this animation (see Guided mode). If not otherwise specified, guided mode will be activated.
70772   * @param {Object} eventEmitter If specified, this event emitter will be notified when an animation starts or ends.
70773   * @return {Chartist.Svg} The current element where the animation was added
70774   */
70775  function animate(animations, guided, eventEmitter) {
70776    if(guided === undefined) {
70777      guided = true;
70778    }
70779
70780    Object.keys(animations).forEach(function createAnimateForAttributes(attribute) {
70781
70782      function createAnimate(animationDefinition, guided) {
70783        var attributeProperties = {},
70784          animate,
70785          timeout,
70786          easing;
70787
70788        // Check if an easing is specified in the definition object and delete it from the object as it will not
70789        // be part of the animate element attributes.
70790        if(animationDefinition.easing) {
70791          // If already an easing Bézier curve array we take it or we lookup a easing array in the Easing object
70792          easing = animationDefinition.easing instanceof Array ?
70793            animationDefinition.easing :
70794            Chartist.Svg.Easing[animationDefinition.easing];
70795          delete animationDefinition.easing;
70796        }
70797
70798        // If numeric dur or begin was provided we assume milli seconds
70799        animationDefinition.begin = Chartist.ensureUnit(animationDefinition.begin, 'ms');
70800        animationDefinition.dur = Chartist.ensureUnit(animationDefinition.dur, 'ms');
70801
70802        if(easing) {
70803          animationDefinition.calcMode = 'spline';
70804          animationDefinition.keySplines = easing.join(' ');
70805          animationDefinition.keyTimes = '0;1';
70806        }
70807
70808        // Adding "fill: freeze" if we are in guided mode and set initial attribute values
70809        if(guided) {
70810          animationDefinition.fill = 'freeze';
70811          // Animated property on our element should already be set to the animation from value in guided mode
70812          attributeProperties[attribute] = animationDefinition.from;
70813          this.attr(attributeProperties);
70814
70815          // In guided mode we also set begin to indefinite so we can trigger the start manually and put the begin
70816          // which needs to be in ms aside
70817          timeout = Chartist.quantity(animationDefinition.begin || 0).value;
70818          animationDefinition.begin = 'indefinite';
70819        }
70820
70821        animate = this.elem('animate', Chartist.extend({
70822          attributeName: attribute
70823        }, animationDefinition));
70824
70825        if(guided) {
70826          // If guided we take the value that was put aside in timeout and trigger the animation manually with a timeout
70827          setTimeout(function() {
70828            // If beginElement fails we set the animated attribute to the end position and remove the animate element
70829            // This happens if the SMIL ElementTimeControl interface is not supported or any other problems occured in
70830            // the browser. (Currently FF 34 does not support animate elements in foreignObjects)
70831            try {
70832              animate._node.beginElement();
70833            } catch(err) {
70834              // Set animated attribute to current animated value
70835              attributeProperties[attribute] = animationDefinition.to;
70836              this.attr(attributeProperties);
70837              // Remove the animate element as it's no longer required
70838              animate.remove();
70839            }
70840          }.bind(this), timeout);
70841        }
70842
70843        if(eventEmitter) {
70844          animate._node.addEventListener('beginEvent', function handleBeginEvent() {
70845            eventEmitter.emit('animationBegin', {
70846              element: this,
70847              animate: animate._node,
70848              params: animationDefinition
70849            });
70850          }.bind(this));
70851        }
70852
70853        animate._node.addEventListener('endEvent', function handleEndEvent() {
70854          if(eventEmitter) {
70855            eventEmitter.emit('animationEnd', {
70856              element: this,
70857              animate: animate._node,
70858              params: animationDefinition
70859            });
70860          }
70861
70862          if(guided) {
70863            // Set animated attribute to current animated value
70864            attributeProperties[attribute] = animationDefinition.to;
70865            this.attr(attributeProperties);
70866            // Remove the animate element as it's no longer required
70867            animate.remove();
70868          }
70869        }.bind(this));
70870      }
70871
70872      // If current attribute is an array of definition objects we create an animate for each and disable guided mode
70873      if(animations[attribute] instanceof Array) {
70874        animations[attribute].forEach(function(animationDefinition) {
70875          createAnimate.bind(this)(animationDefinition, false);
70876        }.bind(this));
70877      } else {
70878        createAnimate.bind(this)(animations[attribute], guided);
70879      }
70880
70881    }.bind(this));
70882
70883    return this;
70884  }
70885
70886  Chartist.Svg = Chartist.Class.extend({
70887    constructor: Svg,
70888    attr: attr,
70889    elem: elem,
70890    parent: parent,
70891    root: root,
70892    querySelector: querySelector,
70893    querySelectorAll: querySelectorAll,
70894    getNode: getNode,
70895    foreignObject: foreignObject,
70896    text: text,
70897    empty: empty,
70898    remove: remove,
70899    replace: replace,
70900    append: append,
70901    classes: classes,
70902    addClass: addClass,
70903    removeClass: removeClass,
70904    removeAllClasses: removeAllClasses,
70905    height: height,
70906    width: width,
70907    animate: animate
70908  });
70909
70910  /**
70911   * This method checks for support of a given SVG feature like Extensibility, SVG-animation or the like. Check http://www.w3.org/TR/SVG11/feature for a detailed list.
70912   *
70913   * @memberof Chartist.Svg
70914   * @param {String} feature The SVG 1.1 feature that should be checked for support.
70915   * @return {Boolean} True of false if the feature is supported or not
70916   */
70917  Chartist.Svg.isSupported = function(feature) {
70918    return document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#' + feature, '1.1');
70919  };
70920
70921  /**
70922   * This Object contains some standard easing cubic bezier curves. Then can be used with their name in the `Chartist.Svg.animate`. You can also extend the list and use your own name in the `animate` function. Click the show code button to see the available bezier functions.
70923   *
70924   * @memberof Chartist.Svg
70925   */
70926  var easingCubicBeziers = {
70927    easeInSine: [0.47, 0, 0.745, 0.715],
70928    easeOutSine: [0.39, 0.575, 0.565, 1],
70929    easeInOutSine: [0.445, 0.05, 0.55, 0.95],
70930    easeInQuad: [0.55, 0.085, 0.68, 0.53],
70931    easeOutQuad: [0.25, 0.46, 0.45, 0.94],
70932    easeInOutQuad: [0.455, 0.03, 0.515, 0.955],
70933    easeInCubic: [0.55, 0.055, 0.675, 0.19],
70934    easeOutCubic: [0.215, 0.61, 0.355, 1],
70935    easeInOutCubic: [0.645, 0.045, 0.355, 1],
70936    easeInQuart: [0.895, 0.03, 0.685, 0.22],
70937    easeOutQuart: [0.165, 0.84, 0.44, 1],
70938    easeInOutQuart: [0.77, 0, 0.175, 1],
70939    easeInQuint: [0.755, 0.05, 0.855, 0.06],
70940    easeOutQuint: [0.23, 1, 0.32, 1],
70941    easeInOutQuint: [0.86, 0, 0.07, 1],
70942    easeInExpo: [0.95, 0.05, 0.795, 0.035],
70943    easeOutExpo: [0.19, 1, 0.22, 1],
70944    easeInOutExpo: [1, 0, 0, 1],
70945    easeInCirc: [0.6, 0.04, 0.98, 0.335],
70946    easeOutCirc: [0.075, 0.82, 0.165, 1],
70947    easeInOutCirc: [0.785, 0.135, 0.15, 0.86],
70948    easeInBack: [0.6, -0.28, 0.735, 0.045],
70949    easeOutBack: [0.175, 0.885, 0.32, 1.275],
70950    easeInOutBack: [0.68, -0.55, 0.265, 1.55]
70951  };
70952
70953  Chartist.Svg.Easing = easingCubicBeziers;
70954
70955  /**
70956   * This helper class is to wrap multiple `Chartist.Svg` elements into a list where you can call the `Chartist.Svg` functions on all elements in the list with one call. This is helpful when you'd like to perform calls with `Chartist.Svg` on multiple elements.
70957   * An instance of this class is also returned by `Chartist.Svg.querySelectorAll`.
70958   *
70959   * @memberof Chartist.Svg
70960   * @param {Array<Node>|NodeList} nodeList An Array of SVG DOM nodes or a SVG DOM NodeList (as returned by document.querySelectorAll)
70961   * @constructor
70962   */
70963  function SvgList(nodeList) {
70964    var list = this;
70965
70966    this.svgElements = [];
70967    for(var i = 0; i < nodeList.length; i++) {
70968      this.svgElements.push(new Chartist.Svg(nodeList[i]));
70969    }
70970
70971    // Add delegation methods for Chartist.Svg
70972    Object.keys(Chartist.Svg.prototype).filter(function(prototypeProperty) {
70973      return ['constructor',
70974          'parent',
70975          'querySelector',
70976          'querySelectorAll',
70977          'replace',
70978          'append',
70979          'classes',
70980          'height',
70981          'width'].indexOf(prototypeProperty) === -1;
70982    }
70982).forEach(function(prototypeProperty) {
70983      list[prototypeProperty] = function() {
70984        var args = Array.prototype.slice.call(arguments, 0);
70985        list.svgElements.forEach(function(element) {
70986          Chartist.Svg.prototype[prototypeProperty].apply(element, args);
70987        });
70988        return list;
70989      };
70990    });
70991  }
70992
70993  Chartist.Svg.List = Chartist.Class.extend({
70994    constructor: SvgList
70995  });
70996}(window, document, Chartist));
70997;/**
70998 * Chartist SVG path module for SVG path description creation and modification.
70999 *
71000 * @module Chartist.Svg.Path
71001 */
71002/* global Chartist */
71003(function(window, document, Chartist) {
71004  'use strict';
71005
71006  /**
71007   * Contains the descriptors of supported element types in a SVG path. Currently only move, line and curve are supported.
71008   *
71009   * @memberof Chartist.Svg.Path
71010   * @type {Object}
71011   */
71012  var elementDescriptions = {
71013    m: ['x', 'y'],
71014    l: ['x', 'y'],
71015    c: ['x1', 'y1', 'x2', 'y2', 'x', 'y'],
71016    a: ['rx', 'ry', 'xAr', 'lAf', 'sf', 'x', 'y']
71017  };
71018
71019  /**
71020   * Default options for newly created SVG path objects.
71021   *
71022   * @memberof Chartist.Svg.Path
71023   * @type {Object}
71024   */
71025  var defaultOptions = {
71026    // The accuracy in digit count after the decimal point. This will be used to round numbers in the SVG path. If this option is set to false then no rounding will be performed.
71027    accuracy: 3
71028  };
71029
71030  function element(command, params, pathElements, pos, relative, data) {
71031    var pathElement = Chartist.extend({
71032      command: relative ? command.toLowerCase() : command.toUpperCase()
71033    }, params, data ? { data: data } : {} );
71034
71035    pathElements.splice(pos, 0, pathElement);
71036  }
71037
71038  function forEachParam(pathElements, cb) {
71039    pathElements.forEach(function(pathElement, pathElementIndex) {
71040      elementDescriptions[pathElement.command.toLowerCase()].forEach(function(paramName, paramIndex) {
71041        cb(pathElement, paramName, pathElementIndex, paramIndex, pathElements);
71042      });
71043    });
71044  }
71045
71046  /**
71047   * Used to construct a new path object.
71048   *
71049   * @memberof Chartist.Svg.Path
71050   * @param {Boolean} close If set to true then this path will be closed when stringified (with a Z at the end)
71051   * @param {Object} options Options object that overrides the default objects. See default options for more details.
71052   * @constructor
71053   */
71054  function SvgPath(close, options) {
71055    this.pathElements = [];
71056    this.pos = 0;
71057    this.close = close;
71058    this.options = Chartist.extend({}, defaultOptions, options);
71059  }
71060
71061  /**
71062   * Gets or sets the current position (cursor) inside of the path. You can move around the cursor freely but limited to 0 or the count of existing elements. All modifications with element functions will insert new elements at the position of this cursor.
71063   *
71064   * @memberof Chartist.Svg.Path
71065   * @param {Number} [pos] If a number is passed then the cursor is set to this position in the path element array.
71066   * @return {Chartist.Svg.Path|Number} If the position parameter was passed then the return value will be the path object for easy call chaining. If no position parameter was passed then the current position is returned.
71067   */
71068  function position(pos) {
71069    if(pos !== undefined) {
71070      this.pos = Math.max(0, Math.min(this.pathElements.length, pos));
71071      return this;
71072    } else {
71073      return this.pos;
71074    }
71075  }
71076
71077  /**
71078   * Removes elements from the path starting at the current position.
71079   *
71080   * @memberof Chartist.Svg.Path
71081   * @param {Number} count Number of path elements that should be removed from the current position.
71082   * @return {Chartist.Svg.Path} The current path object for easy call chaining.
71083   */
71084  function remove(count) {
71085    this.pathElements.splice(this.pos, count);
71086    return this;
71087  }
71088
71089  /**
71090   * Use this function to add a new move SVG path element.
71091   *
71092   * @memberof Chartist.Svg.Path
71093   * @param {Number} x The x coordinate for the move element.
71094   * @param {Number} y The y coordinate for the move element.
71095   * @param {Boolean} [relative] If set to true the move element will be created with relative coordinates (lowercase letter)
71096   * @param {*} [data] Any data that should be stored with the element object that will be accessible in pathElement
71097   * @return {Chartist.Svg.Path} The current path object for easy call chaining.
71098   */
71099  function move(x, y, relative, data) {
71100    element('M', {
71101      x: +x,
71102      y: +y
71103    }, this.pathElements, this.pos++, relative, data);
71104    return this;
71105  }
71106
71107  /**
71108   * Use this function to add a new line SVG path element.
71109   *
71110   * @memberof Chartist.Svg.Path
71111   * @param {Number} x The x coordinate for the line element.
71112   * @param {Number} y The y coordinate for the line element.
71113   * @param {Boolean} [relative] If set to true the line element will be created with relative coordinates (lowercase letter)
71114   * @param {*} [data] Any data that should be stored with the element object that will be accessible in pathElement
71115   * @return {Chartist.Svg.Path} The current path object for easy call chaining.
71116   */
71117  function line(x, y, relative, data) {
71118    element('L', {
71119      x: +x,
71120      y: +y
71121    }, this.pathElements, this.pos++, relative, data);
71122    return this;
71123  }
71124
71125  /**
71126   * Use this function to add a new curve SVG path element.
71127   *
71128   * @memberof Chartist.Svg.Path
71129   * @param {Number} x1 The x coordinate for the first control point of the bezier curve.
71130   * @param {Number} y1 The y coordinate for the first control point of the bezier curve.
71131   * @param {Number} x2 The x coordinate for the second control point of the bezier curve.
71132   * @param {Number} y2 The y coordinate for the second control point of the bezier curve.
71133   * @param {Number} x The x coordinate for the target point of the curve element.
71134   * @param {Number} y The y coordinate for the target point of the curve element.
71135   * @param {Boolean} [relative] If set to true the curve element will be created with relative coordinates (lowercase letter)
71136   * @param {*} [data] Any data that should be stored with the element object that will be accessible in pathElement
71137   * @return {Chartist.Svg.Path} The current path object for easy call chaining.
71138   */
71139  function curve(x1, y1, x2, y2, x, y, relative, data) {
71140    element('C', {
71141      x1: +x1,
71142      y1: +y1,
71143      x2: +x2,
71144      y2: +y2,
71145      x: +x,
71146      y: +y
71147    }, this.pathElements, this.pos++, relative, data);
71148    return this;
71149  }
71150
71151  /**
71152   * Use this function to add a new non-bezier curve SVG path element.
71153   *
71154   * @memberof Chartist.Svg.Path
71155   * @param {Number} rx The radius to be used for the x-axis of the arc.
71156   * @param {Number} ry The radius to be used for the y-axis of the arc.
71157   * @param {Number} xAr Defines the orientation of the arc
71158   * @param {Number} lAf Large arc flag
71159   * @param {Number} sf Sweep flag
71160   * @param {Number} x The x coordinate for the target point of the curve element.
71161   * @param {Number} y The y coordinate for the target point of the curve element.
71162   * @param {Boolean} [relative] If set to true the curve element will be created with relative coordinates (lowercase letter)
71163   * @param {*} [data] Any data that should be stored with the element object that will be accessible in pathElement
71164   * @return {Chartist.Svg.Path} The current path object for easy call chaining.
71165   */
71166  function arc(rx, ry, xAr, lAf, sf, x, y, relative, data) {
71167    element('A', {
71168      rx: +rx,
71169      ry: +ry,
71170      xAr: +xAr,
71171      lAf: +lAf,
71172      sf: +sf,
71173      x: +x,
71174      y: +y
71175    }, this.pathElements, this.pos++, relative, data);
71176    return this;
71177  }
71178
71179  /**
71180   * Parses an SVG path seen in the d attribute of path elements, and inserts the parsed elements into the existing path object at the current cursor position. Any closing path indicators (Z at the end of the path) will be ignored by the parser as this is provided by the close option in the options of the path object.
71181   *
71182   * @memberof Chartist.Svg.Path
71183   * @param {String} path Any SVG path that contains move (m), line (l) or curve (c) components.
71184   * @return {Chartist.Svg.Path} The current path object for easy call chaining.
71185   */
71186  function parse(path) {
71187    // Parsing the SVG path string into an array of arrays [['M', '10', '10'], ['L', '100', '100']]
71188    var chunks = path.replace(/([A-Za-z])([0-9])/g, '$1 $2')
71189      .replace(/([0-9])([A-Za-z])/g, '$1 $2')
71190      .split(/[\s,]+/)
71191      .reduce(function(result, element) {
71192        if(element.match(/[A-Za-z]/)) {
71193          result.push([]);
71194        }
71195
71196        result[result.length - 1].push(element);
71197        return result;
71198      }, []);
71199
71200    // If this is a closed path we remove the Z at the end because this is determined by the close option
71201    if(chunks[chunks.length - 1][0].toUpperCase() === 'Z') {
71202      chunks.pop();
71203    }
71204
71205    // Using svgPathElementDescriptions to map raw path arrays into objects that contain the command and the parameters
71206    // For example {command: 'M', x: '10', y: '10'}
71207    var elements = chunks.map(function(chunk) {
71208        var command = chunk.shift(),
71209          description = elementDescriptions[command.toLowerCase()];
71210
71211        return Chartist.extend({
71212          command: command
71213        }, description.reduce(function(result, paramName, index) {
71214          result[paramName] = +chunk[index];
71215          return result;
71216        }, {}));
71217      });
71218
71219    // Preparing a splice call with the elements array as var arg params and insert the parsed elements at the current position
71220    var spliceArgs = [this.pos, 0];
71221    Array.prototype.push.apply(spliceArgs, elements);
71222    Array.prototype.splice.apply(this.pathElements, spliceArgs);
71223    // Increase the internal position by the element count
71224    this.pos += elements.length;
71225
71226    return this;
71227  }
71228
71229  /**
71230   * This function renders to current SVG path object into a final SVG string that can be used in the d attribute of SVG path elements. It uses the accuracy option to round big decimals. If the close parameter was set in the constructor of this path object then a path closing Z will be appended to the output string.
71231   *
71232   * @memberof Chartist.Svg.Path
71233   * @return {String}
71234   */
71235  function stringify() {
71236    var accuracyMultiplier = Math.pow(10, this.options.accuracy);
71237
71238    return this.pathElements.reduce(function(path, pathElement) {
71239        var params = elementDescriptions[pathElement.command.toLowerCase()].map(function(paramName) {
71240          return this.options.accuracy ?
71241            (Math.round(pathElement[paramName] * accuracyMultiplier) / accuracyMultiplier) :
71242            pathElement[paramName];
71243        }.bind(this));
71244
71245        return path + pathElement.command + params.join(',');
71246      }.bind(this), '') + (this.close ? 'Z' : '');
71247  }
71248
71249  /**
71250   * Scales all elements in the current SVG path object. There is an individual parameter for each coordinate. Scaling will also be done for control points of curves, affecting the given coordinate.
71251   *
71252   * @memberof Chartist.Svg.Path
71253   * @param {Number} x The number which will be used to scale the x, x1 and x2 of all path elements.
71254   * @param {Number} y The number which will be used to scale the y, y1 and y2 of all path elements.
71255   * @return {Chartist.Svg.Path} The current path object for easy call chaining.
71256   */
71257  function scale(x, y) {
71258    forEachParam(this.pathElements, function(pathElement, paramName) {
71259      pathElement[paramName] *= paramName[0] === 'x' ? x : y;
71260    });
71261    return this;
71262  }
71263
71264  /**
71265   * Translates all elements in the current SVG path object. The translation is relative and there is an individual parameter for each coordinate. Translation will also be done for control points of curves, affecting the given coordinate.
71266   *
71267   * @memberof Chartist.Svg.Path
71268   * @param {Number} x The number which will be used to translate the x, x1 and x2 of all path elements.
71269   * @param {Number} y The number which will be used to translate the y, y1 and y2 of all path elements.
71270   * @return {Chartist.Svg.Path} The current path object for easy call chaining.
71271   */
71272  function translate(x, y) {
71273    forEachParam(this.pathElements, function(pathElement, paramName) {
71274      pathElement[paramName] += paramName[0] === 'x' ? x : y;
71275    });
71276    return this;
71277  }
71278
71279  /**
71280   * This function will run over all existing path elements and then loop over their attributes. The callback function will be called for every path element attribute that exists in the current path.
71281   * The method signature of the callback function looks like this:
71282   * ```javascript
71283   * function(pathElement, paramName, pathElementIndex, paramIndex, pathElements)
71284   * ```
71285   * If something else than undefined is returned by the callback function, this value will be used to replace the old value. This allows you to build custom transformations of path objects that can't be achieved using the basic transformation functions scale and translate.
71286   *
71287   * @memberof Chartist.Svg.Path
71288   * @param {Function} transformFnc The callback function for the transformation. Check the signature in the function description.
71289   * @return {Chartist.Svg.Path} The current path object for easy call chaining.
71290   */
71291  function transform(transformFnc) {
71292    forEachParam(this.pathElements, function(pathElement, paramName, pathElementIndex, paramIndex, pathElements) {
71293      var transformed = transformFnc(pathElement, paramName, pathElementIndex, paramIndex, pathElements);
71294      if(transformed || transformed === 0) {
71295        pathElement[paramName] = transformed;
71296      }
71297    });
71298    return this;
71299  }
71300
71301  /**
71302   * This function clones a whole path object with all its properties. This is a deep clone and path element objects will also be cloned.
71303   *
71304   * @memberof Chartist.Svg.Path
71305   * @param {Boolean} [close] Optional option to set the new cloned path to closed. If not specified or false, the original path close option will be used.
71306   * @return {Chartist.Svg.Path}
71307   */
71308  function clone(close) {
71309    var c = new Chartist.Svg.Path(close || this.close);
71310    c.pos = this.pos;
71311    c.pathElements = this.pathElements.slice().map(function cloneElements(pathElement) {
71312      return Chartist.extend({}, pathElement);
71313    });
71314    c.options = Chartist.extend({}, this.options);
71315    return c;
71316  }
71317
71318  /**
71319   * Split a Svg.Path object by a specific command in the path chain. The path chain will be split and an array of newly created paths objects will be returned. This is useful if you'd like to split an SVG path by it's move commands, for example, in order to isolate chunks of drawings.
71320   *
71321   * @memberof Chartist.Svg.Path
71322   * @param {String} command The command you'd like to use to split the path
71323   * @return {Array<Chartist.Svg.Path>}
71324   */
71325  function splitByCommand(command) {
71326    var split = [
71327      new Chartist.Svg.Path()
71328    ];
71329
71330    this.pathElements.forEach(function(pathElement) {
71331      if(pathElement.command === command.toUpperCase() && split[split.length - 1].pathElements.length !== 0) {
71332        split.push(new Chartist.Svg.Path());
71333      }
71334
71335      split[split.length - 1].pathElements.push(pathElement);
71336    });
71337
71338    return split;
71339  }
71340
71341  /**
71342   * This static function on `Chartist.Svg.Path` is joining multiple paths together into one paths.
71343   *
71344   * @memberof Chartist.Svg.Path
71345   * @param {Array<Chartist.Svg.Path>} paths A list of paths to be joined together. The order is important.
71346   * @param {boolean} close If the newly created path should be a closed path
71347   * @param {Object} options Path options for the newly created path.
71348   * @return {Chartist.Svg.Path}
71349   */
71350
71351  function join(paths, close, options) {
71352    var joinedPath = new Chartist.Svg.Path(close, options);
71353    for(var i = 0; i < paths.length; i++) {
71354      var path = paths[i];
71355      for(var j = 0; j < path.pathElements.length; j++) {
71356        joinedPath.pathElements.push(path.pathElements[j]);
71357      }
71358    }
71359    return joinedPath;
71360  }
71361
71362  Chartist.Svg.Path = Chartist.Class.extend({
71363    constructor: SvgPath,
71364    position: position,
71365    remove: remove,
71366    move: move,
71367    line: line,
71368    curve: curve,
71369    arc: arc,
71370    scale: scale,
71371    translate: translate,
71372    transform: transform,
71373    parse: parse,
71374    stringify: stringify,
71375    clone: clone,
71376    splitByCommand: splitByCommand
71377  });
71378
71379  Chartist.Svg.Path.elementDescriptions = elementDescriptions;
71380  Chartist.Svg.Path.join = join;
71381}(window, document, Chartist));
71382;/* global Chartist */
71383(function (window, document, Chartist) {
71384  'use strict';
71385
71386  var axisUnits = {
71387    x: {
71388      pos: 'x',
71389      len: 'width',
71390      dir: 'horizontal',
71391      rectStart: 'x1',
71392      rectEnd: 'x2',
71393      rectOffset: 'y2'
71394    },
71395    y: {
71396      pos: 'y',
71397      len: 'height',
71398      dir: 'vertical',
71399      rectStart: 'y2',
71400      rectEnd: 'y1',
71401      rectOffset: 'x1'
71402    }
71403  };
71404
71405  function Axis(units, chartRect, ticks, options) {
71406    this.units = units;
71407    this.counterUnits = units === axisUnits.x ? axisUnits.y : axisUnits.x;
71408    this.chartRect = chartRect;
71409    this.axisLength = chartRect[units.rectEnd] - chartRect[units.rectStart];
71410    this.gridOffset = chartRect[units.rectOffset];
71411    this.ticks = ticks;
71412    this.options = options;
71413  }
71414
71415  function createGridAndLabels(gridGroup, labelGroup, useForeignObject, chartOptions, eventEmitter) {
71416    var axisOptions = chartOptions['axis' + this.units.pos.toUpperCase()];
71417    var projectedValues = this.ticks.map(this.projectValue.bind(this));
71418    var labelValues = this.ticks.map(axisOptions.labelInterpolationFnc);
71419
71420    projectedValues.forEach(function(projectedValue, index) {
71421      var labelOffset = {
71422        x: 0,
71423        y: 0
71424      };
71425
71426      // TODO: Find better solution for solving this problem
71427      // Calculate how much space we have available for the label
71428      var labelLength;
71429      if(projectedValues[index + 1]) {
71430        // If we still have one label ahead, we can calculate the distance to the next tick / label
71431        labelLength = projectedValues[index + 1] - projectedValue;
71432      } else {
71433        // If we don't have a label ahead and we have only two labels in total, we just take the remaining distance to
71434        // on the whole axis length. We limit that to a minimum of 30 pixel, so that labels close to the border will
71435        // still be visible inside of the chart padding.
71436        labelLength = Math.max(this.axisLength - projectedValue, 30);
71437      }
71438
71439      // Skip grid lines and labels where interpolated label values are falsey (execpt for 0)
71440      if(Chartist.isFalseyButZero(labelValues[index]) && labelValues[index] !== '') {
71441        return;
71442      }
71443
71444      // Transform to global coordinates using the chartRect
71445      // We also need to set the label offset for the createLabel function
71446      if(this.units.pos === 'x') {
71447        projectedValue = this.chartRect.x1 + projectedValue;
71448        labelOffset.x = chartOptions.axisX.labelOffset.x;
71449
71450        // If the labels should be positioned in start position (top side for vertical axis) we need to set a
71451        // different offset as for positioned with end (bottom)
71452        if(chartOptions.axisX.position === 'start') {
71453          labelOffset.y = this.chartRect.padding.top + chartOptions.axisX.labelOffset.y + (useForeignObject ? 5 : 20);
71454        } else {
71455          labelOffset.y = this.chartRect.y1 + chartOptions.axisX.labelOffset.y + (useForeignObject ? 5 : 20);
71456        }
71457      } else {
71458        projectedValue = this.chartRect.y1 - projectedValue;
71459        labelOffset.y = chartOptions.axisY.labelOffset.y - (useForeignObject ? labelLength : 0);
71460
71461        // If the labels should be positioned in start position (left side for horizontal axis) we need to set a
71462        // different offset as for positioned with end (right side)
71463        if(chartOptions.axisY.position === 'start') {
71464          labelOffset.x = useForeignObject ? this.chartRect.padding.left + chartOptions.axisY.labelOffset.x : this.chartRect.x1 - 10;
71465        } else {
71466          labelOffset.x = this.chartRect.x2 + chartOptions.axisY.labelOffset.x + 10;
71467        }
71468      }
71469
71470      if(axisOptions.showGrid) {
71471        Chartist.createGrid(projectedValue, index, this, this.gridOffset, this.chartRect[this.counterUnits.len](), gridGroup, [
71472          chartOptions.classNames.grid,
71473          chartOptions.classNames[this.units.dir]
71474        ], eventEmitter);
71475      }
71476
71477      if(axisOptions.showLabel) {
71478        Chartist.createLabel(projectedValue, labelLength, index, labelValues, this, axisOptions.offset, labelOffset, labelGroup, [
71479          chartOptions.classNames.label,
71480          chartOptions.classNames[this.units.dir],
71481          (axisOptions.position === 'start' ? chartOptions.classNames[axisOptions.position] : chartOptions.classNames['end'])
71482        ], useForeignObject, eventEmitter);
71483      }
71484    }.bind(this));
71485  }
71486
71487  Chartist.Axis = Chartist.Class.extend({
71488    constructor: Axis,
71489    createGridAndLabels: createGridAndLabels,
71490    projectValue: function(value, index, data) {
71491      throw new Error('Base axis can\'t be instantiated!');
71492    }
71493  });
71494
71495  Chartist.Axis.units = axisUnits;
71496
71497}(window, document, Chartist));
71498;/**
71499 * The auto scale axis uses standard linear scale projection of values along an axis. It uses order of magnitude to find a scale automatically and evaluates the available space in order to find the perfect amount of ticks for your chart.
71500 * **Options**
71501 * The following options are used by this axis in addition to the default axis options outlined in the axis configuration of the chart default settings.
71502 * ```javascript
71503 * var options = {
71504 *   // If high is specified then the axis will display values explicitly up to this value and the computed maximum from the data is ignored
71505 *   high: 100,
71506 *   // If low is specified then the axis will display values explicitly down to this value and the computed minimum from the data is ignored
71507 *   low: 0,
71508 *   // This option will be used when finding the right scale division settings. The amount of ticks on the scale will be determined so that as many ticks as possible will be displayed, while not violating this minimum required space (in pixel).
71509 *   scaleMinSpace: 20,
71510 *   // Can be set to true or false. If set to true, the scale will be generated with whole numbers only.
71511 *   onlyInteger: true,
71512 *   // The reference value can be used to make sure that this value will always be on the chart. This is especially useful on bipolar charts where the bipolar center always needs to be part of the chart.
71513 *   referenceValue: 5
71514 * };
71515 * ```
71516 *
71517 * @module Chartist.AutoScaleAxis
71518 */
71519/* global Chartist */
71520(function (window, document, Chartist) {
71521  'use strict';
71522
71523  function AutoScaleAxis(axisUnit, data, chartRect, options) {
71524    // Usually we calculate highLow based on the data but this can be overriden by a highLow object in the options
71525    var highLow = options.highLow || Chartist.getHighLow(data, options, axisUnit.pos);
71526    this.bounds = Chartist.getBounds(chartRect[axisUnit.rectEnd] - chartRect[axisUnit.rectStart], highLow, options.scaleMinSpace || 20, options.onlyInteger);
71527    this.range = {
71528      min: this.bounds.min,
71529      max: this.bounds.max
71530    };
71531
71532    Chartist.AutoScaleAxis.super.constructor.call(this,
71533      axisUnit,
71534      chartRect,
71535      this.bounds.values,
71536      options);
71537  }
71538
71539  function projectValue(value) {
71540    return this.axisLength * (+Chartist.getMultiValue(value, this.units.pos) - this.bounds.min) / this.bounds.range;
71541  }
71542
71543  Chartist.AutoScaleAxis = Chartist.Axis.extend({
71544    constructor: AutoScaleAxis,
71545    projectValue: projectValue
71546  });
71547
71548}(window, document, Chartist));
71549;/**
71550 * The fixed scale axis uses standard linear projection of values along an axis. It makes use of a divisor option to divide the range provided from the minimum and maximum value or the options high and low that will override the computed minimum and maximum.
71551 * **Options**
71552 * The following options are used by this axis in addition to the default axis options outlined in the axis configuration of the chart default settings.
71553 * ```javascript
71554 * var options = {
71555 *   // If high is specified then the axis will display values explicitly up to this value and the computed maximum from the data is ignored
71556 *   high: 100,
71557 *   // If low is specified then the axis will display values explicitly down to this value and the computed minimum from the data is ignored
71558 *   low: 0,
71559 *   // If specified then the value range determined from minimum to maximum (or low and high) will be divided by this number and ticks will be generated at those division points. The default divisor is 1.
71560 *   divisor: 4,
71561 *   // If ticks is explicitly set, then the axis will not compute the ticks with the divisor, but directly use the data in ticks to determine at what points on the axis a tick need to be generated.
71562 *   ticks: [1, 10, 20, 30]
71563 * };
71564 * ```
71565 *
71566 * @module Chartist.FixedScaleAxis
71567 */
71568/* global Chartist */
71569(function (window, document, Chartist) {
71570  'use strict';
71571
71572  function FixedScaleAxis(axisUnit, data, chartRect, options) {
71573    var highLow = options.highLow || Chartist.getHighLow(data, options, axisUnit.pos);
71574    this.divisor = options.divisor || 1;
71575    this.ticks = options.ticks || Chartist.times(this.divisor).map(function(value, index) {
71576      return highLow.low + (highLow.high - highLow.low) / this.divisor * index;
71577    }.bind(this));
71578    this.ticks.sort(function(a, b) {
71579      return a - b;
71580    });
71581    this.range = {
71582      min: highLow.low,
71583      max: highLow.high
71584    };
71585
71586    Chartist.FixedScaleAxis.super.constructor.call(this,
71587      axisUnit,
71588      chartRect,
71589      this.ticks,
71590      options);
71591
71592    this.stepLength = this.axisLength / this.divisor;
71593  }
71594
71595  function projectValue(value) {
71596    return this.axisLength * (+Chartist.getMultiValue(value, this.units.pos) - this.range.min) / (this.range.max - this.range.min);
71597  }
71598
71599  Chartist.FixedScaleAxis = Chartist.Axis.extend({
71600    constructor: FixedScaleAxis,
71601    projectValue: projectValue
71602  });
71603
71604}(window, document, Chartist));
71605;/**
71606 * The step axis for step based charts like bar chart or step based line charts. It uses a fixed amount of ticks that will be equally distributed across the whole axis length. The projection is done using the index of the data value rather than the value itself and therefore it's only useful for distribution purpose.
71607 * **Options**
71608 * The following options are used by this axis in addition to the default axis options outlined in the axis configuration of the chart default settings.
71609 * ```javascript
71610 * var options = {
71611 *   // Ticks to be used to distribute across the axis length. As this axis type relies on the index of the value rather than the value, arbitrary data that can be converted to a string can be used as ticks.
71612 *   ticks: ['One', 'Two', 'Three'],
71613 *   // If set to true the full width will be used to distribute the values where the last value will be at the maximum of the axis length. If false the spaces between the ticks will be evenly distributed instead.
71614 *   stretch: true
71615 * };
71616 * ```
71617 *
71618 * @module Chartist.StepAxis
71619 */
71620/* global Chartist */
71621(function (window, document, Chartist) {
71622  'use strict';
71623
71624  function StepAxis(axisUnit, data, chartRect, options) {
71625    Chartist.StepAxis.super.constructor.call(this,
71626      axisUnit,
71627      chartRect,
71628      options.ticks,
71629      options);
71630
71631    var calc = Math.max(1, options.ticks.length - (options.stretch ? 1 : 0));
71632    this.stepLength = this.axisLength / calc;
71633  }
71634
71635  function projectValue(value, index) {
71636    return this.stepLength * index;
71637  }
71638
71639  Chartist.StepAxis = Chartist.Axis.extend({
71640    constructor: StepAxis,
71641    projectValue: projectValue
71642  });
71643
71644}(window, document, Chartist));
71645;/**
71646 * The Chartist line chart can be used to draw Line or Scatter charts. If used in the browser you can access the global `Chartist` namespace where you find the `Line` function as a main entry point.
71647 *
71648 * For examples on how to use the line chart please check the examples of the `Chartist.Line` method.
71649 *
71650 * @module Chartist.Line
71651 */
71652/* global Chartist */
71653(function(window, document, Chartist){
71654  'use strict';
71655
71656  /**
71657   * Default options in line charts. Expand the code view to see a detailed list of options with comments.
71658   *
71659   * @memberof Chartist.Line
71660   */
71661  var defaultOptions = {
71662    // Options for X-Axis
71663    axisX: {
71664      // The offset of the labels to the chart area
71665      offset: 30,
71666      // Position where labels are placed. Can be set to `start` or `end` where `start` is equivalent to left or top on vertical axis and `end` is equivalent to right or bottom on horizontal axis.
71667      position: 'end',
71668      // Allows you to correct label positioning on this axis by positive or negative x and y offset.
71669      labelOffset: {
71670        x: 0,
71671        y: 0
71672      },
71673      // If labels should be shown or not
71674      showLabel: true,
71675      // If the axis grid should be drawn or not
71676      showGrid: true,
71677      // Interpolation function that allows you to intercept the value from the axis label
71678      labelInterpolationFnc: Chartist.noop,
71679      // Set the axis type to be used to project values on this axis. If not defined, Chartist.StepAxis will be used for the X-Axis, where the ticks option will be set to the labels in the data and the stretch option will be set to the global fullWidth option. This type can be changed to any axis constructor available (e.g. Chartist.FixedScaleAxis), where all axis options should be present here.
71680      type: undefined
71681    },
71682    // Options for Y-Axis
71683    axisY: {
71684      // The offset of the labels to the chart area
71685      offset: 40,
71686      // Position where labels are placed. Can be set to `start` or `end` where `start` is equivalent to left or top on vertical axis and `end` is equivalent to right or bottom on horizontal axis.
71687      position: 'start',
71688      // Allows you to correct label positioning on this axis by positive or negative x and y offset.
71689      labelOffset: {
71690        x: 0,
71691        y: 0
71692      },
71693      // If labels should be shown or not
71694      showLabel: true,
71695      // If the axis grid should be drawn or not
71696      showGrid: true,
71697      // Interpolation function that allows you to intercept the value from the axis label
71698      labelInterpolationFnc: Chartist.noop,
71699      // Set the axis type to be used to project values on this axis. If not defined, Chartist.AutoScaleAxis will be used for the Y-Axis, where the high and low options will be set to the global high and low options. This type can be changed to any axis constructor available (e.g. Chartist.FixedScaleAxis), where all axis options should be present here.
71700      type: undefined,
71701      // This value specifies the minimum height in pixel of the scale steps
71702      scaleMinSpace: 20,
71703      // Use only integer values (whole numbers) for the scale steps
71704      onlyInteger: false
71705    },
71706    // Specify a fixed width for the chart as a string (i.e. '100px' or '50%')
71707    width: undefined,
71708    // Specify a fixed height for the chart as a string (i.e. '100px' or '50%')
71709    height: undefined,
71710    // If the line should be drawn or not
71711    showLine: true,
71712    // If dots should be drawn or not
71713    showPoint: true,
71714    // If the line chart should draw an area
71715    showArea: false,
71716    // The base for the area chart that will be used to close the area shape (is normally 0)
71717    areaBase: 0,
71718    // Specify if the lines should be smoothed. This value can be true or false where true will result in smoothing using the default smoothing interpolation function Chartist.Interpolation.cardinal and false results in Chartist.Interpolation.none. You can also choose other smoothing / interpolation functions available in the Chartist.Interpolation module, or write your own interpolation function. Check the examples for a brief description.
71719    lineSmooth: true,
71720    // If the line chart should add a background fill to the .ct-grids group.
71721    showGridBackground: false,
71722    // Overriding the natural low of the chart allows you to zoom in or limit the charts lowest displayed value
71723    low: undefined,
71724    // Overriding the natural high of the chart allows you to zoom in or limit the charts highest displayed value
71725    high: undefined,
71726    // Padding of the chart drawing area to the container element and labels as a number or padding object {top: 5, right: 5, bottom: 5, left: 5}
71727    chartPadding: {
71728      top: 15,
71729      right: 15,
71730      bottom: 5,
71731      left: 10
71732    },
71733    // When set to true, the last grid line on the x-axis is not drawn and the chart elements will expand to the full available width of the chart. For the last label to be drawn correctly you might need to add chart padding or offset the last label with a draw event handler.
71734    fullWidth: false,
71735    // If true the whole data is reversed including labels, the series order as well as the whole series data arrays.
71736    reverseData: false,
71737    // Override the class names that get used to generate the SVG structure of the chart
71738    classNames: {
71739      chart: 'ct-chart-line',
71740      label: 'ct-label',
71741      labelGroup: 'ct-labels',
71742      series: 'ct-series',
71743      line: 'ct-line',
71744      point: 'ct-point',
71745      area: 'ct-area',
71746      grid: 'ct-grid',
71747      gridGroup: 'ct-grids',
71748      gridBackground: 'ct-grid-background',
71749      vertical: 'ct-vertical',
71750      horizontal: 'ct-horizontal',
71751      start: 'ct-start',
71752      end: 'ct-end'
71753    }
71754  };
71755
71756  /**
71757   * Creates a new chart
71758   *
71759   */
71760  function createChart(options) {
71761    var data = Chartist.normalizeData(this.data, options.reverseData, true);
71762
71763    // Create new svg object
71764    this.svg = Chartist.createSvg(this.container, options.width, options.height, options.classNames.chart);
71765    // Create groups for labels, grid and series
71766    var gridGroup = this.svg.elem('g').addClass(options.classNames.gridGroup);
71767    var seriesGroup = this.svg.elem('g');
71768    var labelGroup = this.svg.elem('g').addClass(options.classNames.labelGroup);
71769
71770    var chartRect = Chartist.createChartRect(this.svg, options, defaultOptions.padding);
71771    var axisX, axisY;
71772
71773    if(options.axisX.type === undefined) {
71774      axisX = new Chartist.StepAxis(Chartist.Axis.units.x, data.normalized.series, chartRect, Chartist.extend({}, options.axisX, {
71775        ticks: data.normalized.labels,
71776        stretch: options.fullWidth
71777      }));
71778    } else {
71779      axisX = options.axisX.type.call(Chartist, Chartist.Axis.units.x, data.normalized.series, chartRect, options.axisX);
71780    }
71781
71782    if(options.axisY.type === undefined) {
71783      axisY = new Chartist.AutoScaleAxis(Chartist.Axis.units.y, data.normalized.series, chartRect, Chartist.extend({}, options.axisY, {
71784        high: Chartist.isNumeric(options.high) ? options.high : options.axisY.high,
71785        low: Chartist.isNumeric(options.low) ? options.low : options.axisY.low
71786      }));
71787    } else {
71788      axisY = options.axisY.type.call(Chartist, Chartist.Axis.units.y, data.normalized.series, chartRect, options.axisY);
71789    }
71790
71791    axisX.createGridAndLabels(gridGroup, labelGroup, this.supportsForeignObject, options, this.eventEmitter);
71792    axisY.createGridAndLabels(gridGroup, labelGroup, this.supportsForeignObject, options, this.eventEmitter);
71793
71794    if (options.showGridBackground) {
71795      Chartist.createGridBackground(gridGroup, chartRect, options.classNames.gridBackground, this.eventEmitter);
71796    }
71797
71798    // Draw the series
71799    data.raw.series.forEach(function(series, seriesIndex) {
71800      var seriesElement = seriesGroup.elem('g');
71801
71802      // Write attributes to series group element. If series name or meta is undefined the attributes will not be written
71803      seriesElement.attr({
71804        'ct:series-name': series.name,
71805        'ct:meta': Chartist.serialize(series.meta)
71806      });
71807
71808      // Use series class from series data or if not set generate one
71809      seriesElement.addClass([
71810        options.classNames.series,
71811        (series.className || options.classNames.series + '-' + Chartist.alphaNumerate(seriesIndex))
71812      ].join(' '));
71813
71814      var pathCoordinates = [],
71815        pathData = [];
71816
71817      data.normalized.series[seriesIndex].forEach(function(value, valueIndex) {
71818        var p = {
71819          x: chartRect.x1 + axisX.projectValue(value, valueIndex, data.normalized.series[seriesIndex]),
71820          y: chartRect.y1 - axisY.projectValue(value, valueIndex, data.normalized.series[seriesIndex])
71821        };
71822        pathCoordinates.push(p.x, p.y);
71823        pathData.push({
71824          value: value,
71825          valueIndex: valueIndex,
71826          meta: Chartist.getMetaData(series, valueIndex)
71827        });
71828      }.bind(this));
71829
71830      var seriesOptions = {
71831        lineSmooth: Chartist.getSeriesOption(series, options, 'lineSmooth'),
71832        showPoint: Chartist.getSeriesOption(series, options, 'showPoint'),
71833        showLine: Chartist.getSeriesOption(series, options, 'showLine'),
71834        showArea: Chartist.getSeriesOption(series, options, 'showArea'),
71835        areaBase: Chartist.getSeriesOption(series, options, 'areaBase')
71836      };
71837
71838      var smoothing = typeof seriesOptions.lineSmooth === 'function' ?
71839        seriesOptions.lineSmooth : (seriesOptions.lineSmooth ? Chartist.Interpolation.monotoneCubic() : Chartist.Interpolation.none());
71840      // Interpolating path where pathData will be used to annotate each path element so we can trace back the original
71841      // index, value and meta data
71842      var path = smoothing(pathCoordinates, pathData);
71843
71844      // If we should show points we need to create them now to avoid secondary loop
71845      // Points are drawn from the pathElements returned by the interpolation function
71846      // Small offset for Firefox to render squares correctly
71847      if (seriesOptions.showPoint) {
71848
71849        path.pathElements.forEach(function(pathElement) {
71850          var point = seriesElement.elem('line', {
71851            x1: pathElement.x,
71852            y1: pathElement.y,
71853            x2: pathElement.x + 0.01,
71854            y2: pathElement.y
71855          }, options.classNames.point).attr({
71856            'ct:value': [pathElement.data.value.x, pathElement.data.value.y].filter(Chartist.isNumeric).join(','),
71857            'ct:meta': Chartist.serialize(pathElement.data.meta)
71858          });
71859
71860          this.eventEmitter.emit('draw', {
71861            type: 'point',
71862            value: pathElement.data.value,
71863            index: pathElement.data.valueIndex,
71864            meta: pathElement.data.meta,
71865            series: series,
71866            seriesIndex: seriesIndex,
71867            axisX: axisX,
71868            axisY: axisY,
71869            group: seriesElement,
71870            element: point,
71871            x: pathElement.x,
71872            y: pathElement.y
71873          });
71874        }.bind(this));
71875      }
71876
71877      if(seriesOptions.showLine) {
71878        var line = seriesElement.elem('path', {
71879          d: path.stringify()
71880        }, options.classNames.line, true);
71881
71882        this.eventEmitter.emit('draw', {
71883          type: 'line',
71884          values: data.normalized.series[seriesIndex],
71885          path: path.clone(),
71886          chartRect: chartRect,
71887          index: seriesIndex,
71888          series: series,
71889          seriesIndex: seriesIndex,
71890          seriesMeta: series.meta,
71891          axisX: axisX,
71892          axisY: axisY,
71893          group: seriesElement,
71894          element: line
71895        });
71896      }
71897
71898      // Area currently only works with axes that support a range!
71899      if(seriesOptions.showArea && axisY.range) {
71900        // If areaBase is outside the chart area (< min or > max) we need to set it respectively so that
71901        // the area is not drawn outside the chart area.
71902        var areaBase = Math.max(Math.min(seriesOptions.areaBase, axisY.range.max), axisY.range.min);
71903
71904        // We project the areaBase value into screen coordinates
71905        var areaBaseProjected = chartRect.y1 - axisY.projectValue(areaBase);
71906
71907        // In order to form the area we'll first split the path by move commands so we can chunk it up into segments
71908        path.splitByCommand('M').filter(function onlySolidSegments(pathSegment) {
71909          // We filter only "solid" segments that contain more than one point. Otherwise there's no need for an area
71910          return pathSegment.pathElements.length > 1;
71911        }).map(function convertToArea(solidPathSegments) {
71912          // Receiving the filtered solid path segments we can now convert those segments into fill areas
71913          var firstElement = solidPathSegments.pathElements[0];
71914          var lastElement = solidPathSegments.pathElements[solidPathSegments.pathElements.length - 1];
71915
71916          // Cloning the solid path segment with closing option and removing the first move command from the clone
71917          // We then insert a new move that should start at the area base and draw a straight line up or down
71918          // at the end of the path we add an additional straight line to the projected area base value
71919          // As the closing option is set our path will be automatically closed
71920          return solidPathSegments.clone(true)
71921            .position(0)
71922            .remove(1)
71923            .move(firstElement.x, areaBaseProjected)
71924            .line(firstElement.x, firstElement.y)
71925            .position(solidPathSegments.pathElements.length + 1)
71926            .line(lastElement.x, areaBaseProjected);
71927
71928        }
71928).forEach(function createArea(areaPath) {
71929          // For each of our newly created area paths, we'll now create path elements by stringifying our path objects
71930          // and adding the created DOM elements to the correct series group
71931          var area = seriesElement.elem('path', {
71932            d: areaPath.stringify()
71933          }, options.classNames.area, true);
71934
71935          // Emit an event for each area that was drawn
71936          this.eventEmitter.emit('draw', {
71937            type: 'area',
71938            values: data.normalized.series[seriesIndex],
71939            path: areaPath.clone(),
71940            series: series,
71941            seriesIndex: seriesIndex,
71942            axisX: axisX,
71943            axisY: axisY,
71944            chartRect: chartRect,
71945            index: seriesIndex,
71946            group: seriesElement,
71947            element: area
71948          });
71949        }.bind(this));
71950      }
71951    }.bind(this));
71952
71953    this.eventEmitter.emit('created', {
71954      bounds: axisY.bounds,
71955      chartRect: chartRect,
71956      axisX: axisX,
71957      axisY: axisY,
71958      svg: this.svg,
71959      options: options
71960    });
71961  }
71962
71963  /**
71964   * This method creates a new line chart.
71965   *
71966   * @memberof Chartist.Line
71967   * @param {String|Node} query A selector query string or directly a DOM element
71968   * @param {Object} data The data object that needs to consist of a labels and a series array
71969   * @param {Object} [options] The options object with options that override the default options. Check the examples for a detailed list.
71970   * @param {Array} [responsiveOptions] Specify an array of responsive option arrays which are a media query and options object pair => [[mediaQueryString, optionsObject],[more...]]
71971   * @return {Object} An object which exposes the API for the created chart
71972   *
71973   * @example
71974   * // Create a simple line chart
71975   * var data = {
71976   *   // A labels array that can contain any sort of values
71977   *   labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
71978   *   // Our series array that contains series objects or in this case series data arrays
71979   *   series: [
71980   *     [5, 2, 4, 2, 0]
71981   *   ]
71982   * };
71983   *
71984   * // As options we currently only set a static size of 300x200 px
71985   * var options = {
71986   *   width: '300px',
71987   *   height: '200px'
71988   * };
71989   *
71990   * // In the global name space Chartist we call the Line function to initialize a line chart. As a first parameter we pass in a selector where we would like to get our chart created. Second parameter is the actual data object and as a third parameter we pass in our options
71991   * new Chartist.Line('.ct-chart', data, options);
71992   *
71993   * @example
71994   * // Use specific interpolation function with configuration from the Chartist.Interpolation module
71995   *
71996   * var chart = new Chartist.Line('.ct-chart', {
71997   *   labels: [1, 2, 3, 4, 5],
71998   *   series: [
71999   *     [1, 1, 8, 1, 7]
72000   *   ]
72001   * }, {
72002   *   lineSmooth: Chartist.Interpolation.cardinal({
72003   *     tension: 0.2
72004   *   })
72005   * });
72006   *
72007   * @example
72008   * // Create a line chart with responsive options
72009   *
72010   * var data = {
72011   *   // A labels array that can contain any sort of values
72012   *   labels: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
72013   *   // Our series array that contains series objects or in this case series data arrays
72014   *   series: [
72015   *     [5, 2, 4, 2, 0]
72016   *   ]
72017   * };
72018   *
72019   * // In addition to the regular options we specify responsive option overrides that will override the default configutation based on the matching media queries.
72020   * var responsiveOptions = [
72021   *   ['screen and (min-width: 641px) and (max-width: 1024px)', {
72022   *     showPoint: false,
72023   *     axisX: {
72024   *       labelInterpolationFnc: function(value) {
72025   *         // Will return Mon, Tue, Wed etc. on medium screens
72026   *         return value.slice(0, 3);
72027   *       }
72028   *     }
72029   *   }],
72030   *   ['screen and (max-width: 640px)', {
72031   *     showLine: false,
72032   *     axisX: {
72033   *       labelInterpolationFnc: function(value) {
72034   *         // Will return M, T, W etc. on small screens
72035   *         return value[0];
72036   *       }
72037   *     }
72038   *   }]
72039   * ];
72040   *
72041   * new Chartist.Line('.ct-chart', data, null, responsiveOptions);
72042   *
72043   */
72044  function Line(query, data, options, responsiveOptions) {
72045    Chartist.Line.super.constructor.call(this,
72046      query,
72047      data,
72048      defaultOptions,
72049      Chartist.extend({}, defaultOptions, options),
72050      responsiveOptions);
72051  }
72052
72053  // Creating line chart type in Chartist namespace
72054  Chartist.Line = Chartist.Base.extend({
72055    constructor: Line,
72056    createChart: createChart
72057  });
72058
72059}(window, document, Chartist));
72060;/**
72061 * The bar chart module of Chartist that can be used to draw unipolar or bipolar bar and grouped bar charts.
72062 *
72063 * @module Chartist.Bar
72064 */
72065/* global Chartist */
72066(function(window, document, Chartist){
72067  'use strict';
72068
72069  /**
72070   * Default options in bar charts. Expand the code view to see a detailed list of options with comments.
72071   *
72072   * @memberof Chartist.Bar
72073   */
72074  var defaultOptions = {
72075    // Options for X-Axis
72076    axisX: {
72077      // The offset of the chart drawing area to the border of the container
72078      offset: 30,
72079      // Position where labels are placed. Can be set to `start` or `end` where `start` is equivalent to left or top on vertical axis and `end` is equivalent to right or bottom on horizontal axis.
72080      position: 'end',
72081      // Allows you to correct label positioning on this axis by positive or negative x and y offset.
72082      labelOffset: {
72083        x: 0,
72084        y: 0
72085      },
72086      // If labels should be shown or not
72087      showLabel: true,
72088      // If the axis grid should be drawn or not
72089      showGrid: true,
72090      // Interpolation function that allows you to intercept the value from the axis label
72091      labelInterpolationFnc: Chartist.noop,
72092      // This value specifies the minimum width in pixel of the scale steps
72093      scaleMinSpace: 30,
72094      // Use only integer values (whole numbers) for the scale steps
72095      onlyInteger: false
72096    },
72097    // Options for Y-Axis
72098    axisY: {
72099      // The offset of the chart drawing area to the border of the container
72100      offset: 40,
72101      // Position where labels are placed. Can be set to `start` or `end` where `start` is equivalent to left or top on vertical axis and `end` is equivalent to right or bottom on horizontal axis.
72102      position: 'start',
72103      // Allows you to correct label positioning on this axis by positive or negative x and y offset.
72104      labelOffset: {
72105        x: 0,
72106        y: 0
72107      },
72108      // If labels should be shown or not
72109      showLabel: true,
72110      // If the axis grid should be drawn or not
72111      showGrid: true,
72112      // Interpolation function that allows you to intercept the value from the axis label
72113      labelInterpolationFnc: Chartist.noop,
72114      // This value specifies the minimum height in pixel of the scale steps
72115      scaleMinSpace: 20,
72116      // Use only integer values (whole numbers) for the scale steps
72117      onlyInteger: false
72118    },
72119    // Specify a fixed width for the chart as a string (i.e. '100px' or '50%')
72120    width: undefined,
72121    // Specify a fixed height for the chart as a string (i.e. '100px' or '50%')
72122    height: undefined,
72123    // Overriding the natural high of the chart allows you to zoom in or limit the charts highest displayed value
72124    high: undefined,
72125    // Overriding the natural low of the chart allows you to zoom in or limit the charts lowest displayed value
72126    low: undefined,
72127    // Unless low/high are explicitly set, bar chart will be centered at zero by default. Set referenceValue to null to auto scale.
72128    referenceValue: 0,
72129    // Padding of the chart drawing area to the container element and labels as a number or padding object {top: 5, right: 5, bottom: 5, left: 5}
72130    chartPadding: {
72131      top: 15,
72132      right: 15,
72133      bottom: 5,
72134      left: 10
72135    },
72136    // Specify the distance in pixel of bars in a group
72137    seriesBarDistance: 15,
72138    // If set to true this property will cause the series bars to be stacked. Check the `stackMode` option for further stacking options.
72139    stackBars: false,
72140    // If set to 'overlap' this property will force the stacked bars to draw from the zero line.
72141    // If set to 'accumulate' this property will form a total for each series point. This will also influence the y-axis and the overall bounds of the chart. In stacked mode the seriesBarDistance property will have no effect.
72142    stackMode: 'accumulate',
72143    // Inverts the axes of the bar chart in order to draw a horizontal bar chart. Be aware that you also need to invert your axis settings as the Y Axis will now display the labels and the X Axis the values.
72144    horizontalBars: false,
72145    // If set to true then each bar will represent a series and the data array is expected to be a one dimensional array of data values rather than a series array of series. This is useful if the bar chart should represent a profile rather than some data over time.
72146    distributeSeries: false,
72147    // If true the whole data is reversed including labels, the series order as well as the whole series data arrays.
72148    reverseData: false,
72149    // If the bar chart should add a background fill to the .ct-grids group.
72150    showGridBackground: false,
72151    // Override the class names that get used to generate the SVG structure of the chart
72152    classNames: {
72153      chart: 'ct-chart-bar',
72154      horizontalBars: 'ct-horizontal-bars',
72155      label: 'ct-label',
72156      labelGroup: 'ct-labels',
72157      series: 'ct-series',
72158      bar: 'ct-bar',
72159      grid: 'ct-grid',
72160      gridGroup: 'ct-grids',
72161      gridBackground: 'ct-grid-background',
72162      vertical: 'ct-vertical',
72163      horizontal: 'ct-horizontal',
72164      start: 'ct-start',
72165      end: 'ct-end'
72166    }
72167  };
72168
72169  /**
72170   * Creates a new chart
72171   *
72172   */
72173  function createChart(options) {
72174    var data;
72175    var highLow;
72176
72177    if(options.distributeSeries) {
72178      data = Chartist.normalizeData(this.data, options.reverseData, options.horizontalBars ? 'x' : 'y');
72179      data.normalized.series = data.normalized.series.map(function(value) {
72180        return [value];
72181      });
72182    } else {
72183      data = Chartist.normalizeData(this.data, options.reverseData, options.horizontalBars ? 'x' : 'y');
72184    }
72185
72186    // Create new svg element
72187    this.svg = Chartist.createSvg(
72188      this.container,
72189      options.width,
72190      options.height,
72191      options.classNames.chart + (options.horizontalBars ? ' ' + options.classNames.horizontalBars : '')
72192    );
72193
72194    // Drawing groups in correct order
72195    var gridGroup = this.svg.elem('g').addClass(options.classNames.gridGroup);
72196    var seriesGroup = this.svg.elem('g');
72197    var labelGroup = this.svg.elem('g').addClass(options.classNames.labelGroup);
72198
72199    if(options.stackBars && data.normalized.series.length !== 0) {
72200
72201      // If stacked bars we need to calculate the high low from stacked values from each series
72202      var serialSums = Chartist.serialMap(data.normalized.series, function serialSums() {
72203        return Array.prototype.slice.call(arguments).map(function(value) {
72204          return value;
72205        }).reduce(function(prev, curr) {
72206          return {
72207            x: prev.x + (curr && curr.x) || 0,
72208            y: prev.y + (curr && curr.y) || 0
72209          };
72210        }, {x: 0, y: 0});
72211      });
72212
72213      highLow = Chartist.getHighLow([serialSums], options, options.horizontalBars ? 'x' : 'y');
72214
72215    } else {
72216
72217      highLow = Chartist.getHighLow(data.normalized.series, options, options.horizontalBars ? 'x' : 'y');
72218    }
72219
72220    // Overrides of high / low from settings
72221    highLow.high = +options.high || (options.high === 0 ? 0 : highLow.high);
72222    highLow.low = +options.low || (options.low === 0 ? 0 : highLow.low);
72223
72224    var chartRect = Chartist.createChartRect(this.svg, options, defaultOptions.padding);
72225
72226    var valueAxis,
72227      labelAxisTicks,
72228      labelAxis,
72229      axisX,
72230      axisY;
72231
72232    // We need to set step count based on some options combinations
72233    if(options.distributeSeries && options.stackBars) {
72234      // If distributed series are enabled and bars need to be stacked, we'll only have one bar and therefore should
72235      // use only the first label for the step axis
72236      labelAxisTicks = data.normalized.labels.slice(0, 1);
72237    } else {
72238      // If distributed series are enabled but stacked bars aren't, we should use the series labels
72239      // If we are drawing a regular bar chart with two dimensional series data, we just use the labels array
72240      // as the bars are normalized
72241      labelAxisTicks = data.normalized.labels;
72242    }
72243
72244    // Set labelAxis and valueAxis based on the horizontalBars setting. This setting will flip the axes if necessary.
72245    if(options.horizontalBars) {
72246      if(options.axisX.type === undefined) {
72247        valueAxis = axisX = new Chartist.AutoScaleAxis(Chartist.Axis.units.x, data.normalized.series, chartRect, Chartist.extend({}, options.axisX, {
72248          highLow: highLow,
72249          referenceValue: 0
72250        }));
72251      } else {
72252        valueAxis = axisX = options.axisX.type.call(Chartist, Chartist.Axis.units.x, data.normalized.series, chartRect, Chartist.extend({}, options.axisX, {
72253          highLow: highLow,
72254          referenceValue: 0
72255        }));
72256      }
72257
72258      if(options.axisY.type === undefined) {
72259        labelAxis = axisY = new Chartist.StepAxis(Chartist.Axis.units.y, data.normalized.series, chartRect, {
72260          ticks: labelAxisTicks
72261        });
72262      } else {
72263        labelAxis = axisY = options.axisY.type.call(Chartist, Chartist.Axis.units.y, data.normalized.series, chartRect, options.axisY);
72264      }
72265    } else {
72266      if(options.axisX.type === undefined) {
72267        labelAxis = axisX = new Chartist.StepAxis(Chartist.Axis.units.x, data.normalized.series, chartRect, {
72268          ticks: labelAxisTicks
72269        });
72270      } else {
72271        labelAxis = axisX = options.axisX.type.call(Chartist, Chartist.Axis.units.x, data.normalized.series, chartRect, options.axisX);
72272      }
72273
72274      if(options.axisY.type === undefined) {
72275        valueAxis = axisY = new Chartist.AutoScaleAxis(Chartist.Axis.units.y, data.normalized.series, chartRect, Chartist.extend({}, options.axisY, {
72276          highLow: highLow,
72277          referenceValue: 0
72278        }));
72279      } else {
72280        valueAxis = axisY = options.axisY.type.call(Chartist, Chartist.Axis.units.y, data.normalized.series, chartRect, Chartist.extend({}, options.axisY, {
72281          highLow: highLow,
72282          referenceValue: 0
72283        }));
72284      }
72285    }
72286
72287    // Projected 0 point
72288    var zeroPoint = options.horizontalBars ? (chartRect.x1 + valueAxis.project
72288Value(0)) : (chartRect.y1 - valueAxis.projectValue(0));
72289    // Used to track the screen coordinates of stacked bars
72290    var stackedBarValues = [];
72291
72292    labelAxis.createGridAndLabels(gridGroup, labelGroup, this.supportsForeignObject, options, this.eventEmitter);
72293    valueAxis.createGridAndLabels(gridGroup, labelGroup, this.supportsForeignObject, options, this.eventEmitter);
72294
72295    if (options.showGridBackground) {
72296      Chartist.createGridBackground(gridGroup, chartRect, options.classNames.gridBackground, this.eventEmitter);
72297    }
72298
72299    // Draw the series
72300    data.raw.series.forEach(function(series, seriesIndex) {
72301      // Calculating bi-polar value of index for seriesOffset. For i = 0..4 biPol will be -1.5, -0.5, 0.5, 1.5 etc.
72302      var biPol = seriesIndex - (data.raw.series.length - 1) / 2;
72303      // Half of the period width between vertical grid lines used to position bars
72304      var periodHalfLength;
72305      // Current series SVG element
72306      var seriesElement;
72307
72308      // We need to set periodHalfLength based on some options combinations
72309      if(options.distributeSeries && !options.stackBars) {
72310        // If distributed series are enabled but stacked bars aren't, we need to use the length of the normaizedData array
72311        // which is the series count and divide by 2
72312        periodHalfLength = labelAxis.axisLength / data.normalized.series.length / 2;
72313      } else if(options.distributeSeries && options.stackBars) {
72314        // If distributed series and stacked bars are enabled we'll only get one bar so we should just divide the axis
72315        // length by 2
72316        periodHalfLength = labelAxis.axisLength / 2;
72317      } else {
72318        // On regular bar charts we should just use the series length
72319        periodHalfLength = labelAxis.axisLength / data.normalized.series[seriesIndex].length / 2;
72320      }
72321
72322      // Adding the series group to the series element
72323      seriesElement = seriesGroup.elem('g');
72324
72325      // Write attributes to series group element. If series name or meta is undefined the attributes will not be written
72326      seriesElement.attr({
72327        'ct:series-name': series.name,
72328        'ct:meta': Chartist.serialize(series.meta)
72329      });
72330
72331      // Use series class from series data or if not set generate one
72332      seriesElement.addClass([
72333        options.classNames.series,
72334        (series.className || options.classNames.series + '-' + Chartist.alphaNumerate(seriesIndex))
72335      ].join(' '));
72336
72337      data.normalized.series[seriesIndex].forEach(function(value, valueIndex) {
72338        var projected,
72339          bar,
72340          previousStack,
72341          labelAxisValueIndex;
72342
72343        // We need to set labelAxisValueIndex based on some options combinations
72344        if(options.distributeSeries && !options.stackBars) {
72345          // If distributed series are enabled but stacked bars aren't, we can use the seriesIndex for later projection
72346          // on the step axis for label positioning
72347          labelAxisValueIndex = seriesIndex;
72348        } else if(options.distributeSeries && options.stackBars) {
72349          // If distributed series and stacked bars are enabled, we will only get one bar and therefore always use
72350          // 0 for projection on the label step axis
72351          labelAxisValueIndex = 0;
72352        } else {
72353          // On regular bar charts we just use the value index to project on the label step axis
72354          labelAxisValueIndex = valueIndex;
72355        }
72356
72357        // We need to transform coordinates differently based on the chart layout
72358        if(options.horizontalBars) {
72359          projected = {
72360            x: chartRect.x1 + valueAxis.projectValue(value && value.x ? value.x : 0, valueIndex, data.normalized.series[seriesIndex]),
72361            y: chartRect.y1 - labelAxis.projectValue(value && value.y ? value.y : 0, labelAxisValueIndex, data.normalized.series[seriesIndex])
72362          };
72363        } else {
72364          projected = {
72365            x: chartRect.x1 + labelAxis.projectValue(value && value.x ? value.x : 0, labelAxisValueIndex, data.normalized.series[seriesIndex]),
72366            y: chartRect.y1 - valueAxis.projectValue(value && value.y ? value.y : 0, valueIndex, data.normalized.series[seriesIndex])
72367          }
72368        }
72369
72370        // If the label axis is a step based axis we will offset the bar into the middle of between two steps using
72371        // the periodHalfLength value. Also we do arrange the different series so that they align up to each other using
72372        // the seriesBarDistance. If we don't have a step axis, the bar positions can be chosen freely so we should not
72373        // add any automated positioning.
72374        if(labelAxis instanceof Chartist.StepAxis) {
72375          // Offset to center bar between grid lines, but only if the step axis is not stretched
72376          if(!labelAxis.options.stretch) {
72377            projected[labelAxis.units.pos] += periodHalfLength * (options.horizontalBars ? -1 : 1);
72378          }
72379          // Using bi-polar offset for multiple series if no stacked bars or series distribution is used
72380          projected[labelAxis.units.pos] += (options.stackBars || options.distributeSeries) ? 0 : biPol * options.seriesBarDistance * (options.horizontalBars ? -1 : 1);
72381        }
72382
72383        // Enter value in stacked bar values used to remember previous screen value for stacking up bars
72384        previousStack = stackedBarValues[valueIndex] || zeroPoint;
72385        stackedBarValues[valueIndex] = previousStack - (zeroPoint - projected[labelAxis.counterUnits.pos]);
72386
72387        // Skip if value is undefined
72388        if(value === undefined) {
72389          return;
72390        }
72391
72392        var positions = {};
72393        positions[labelAxis.units.pos + '1'] = projected[labelAxis.units.pos];
72394        positions[labelAxis.units.pos + '2'] = projected[labelAxis.units.pos];
72395
72396        if(options.stackBars && (options.stackMode === 'accumulate' || !options.stackMode)) {
72397          // Stack mode: accumulate (default)
72398          // If bars are stacked we use the stackedBarValues reference and otherwise base all bars off the zero line
72399          // We want backwards compatibility, so the expected fallback without the 'stackMode' option
72400          // to be the original behaviour (accumulate)
72401          positions[labelAxis.counterUnits.pos + '1'] = previousStack;
72402          positions[labelAxis.counterUnits.pos + '2'] = stackedBarValues[valueIndex];
72403        } else {
72404          // Draw from the zero line normally
72405          // This is also the same code for Stack mode: overlap
72406          positions[labelAxis.counterUnits.pos + '1'] = zeroPoint;
72407          positions[labelAxis.counterUnits.pos + '2'] = projected[labelAxis.counterUnits.pos];
72408        }
72409
72410        // Limit x and y so that they are within the chart rect
72411        positions.x1 = Math.min(Math.max(positions.x1, chartRect.x1), chartRect.x2);
72412        positions.x2 = Math.min(Math.max(positions.x2, chartRect.x1), chartRect.x2);
72413        positions.y1 = Math.min(Math.max(positions.y1, chartRect.y2), chartRect.y1);
72414        positions.y2 = Math.min(Math.max(positions.y2, chartRect.y2), chartRect.y1);
72415
72416        var metaData = Chartist.getMetaData(series, valueIndex);
72417
72418        // Create bar element
72419        bar = seriesElement.elem('line', positions, options.classNames.bar).attr({
72420          'ct:value': [value.x, value.y].filter(Chartist.isNumeric).join(','),
72421          'ct:meta': Chartist.serialize(metaData)
72422        });
72423
72424        this.eventEmitter.emit('draw', Chartist.extend({
72425          type: 'bar',
72426          value: value,
72427          index: valueIndex,
72428          meta: metaData,
72429          series: series,
72430          seriesIndex: seriesIndex,
72431          axisX: axisX,
72432          axisY: axisY,
72433          chartRect: chartRect,
72434          group: seriesElement,
72435          element: bar
72436        }, positions));
72437      }.bind(this));
72438    }.bind(this));
72439
72440    this.eventEmitter.emit('created', {
72441      bounds: valueAxis.bounds,
72442      chartRect: chartRect,
72443      axisX: axisX,
72444      axisY: axisY,
72445      svg: this.svg,
72446      options: options
72447    });
72448  }
72449
72450  /**
72451   * This method creates a new bar chart and returns API object that you can use for later changes.
72452   *
72453   * @memberof Chartist.Bar
72454   * @param {String|Node} query A selector query string or directly a DOM element
72455   * @param {Object} data The data object that needs to consist of a labels and a series array
72456   * @param {Object} [options] The options object with options that override the default options. Check the examples for a detailed list.
72457   * @param {Array} [responsiveOptions] Specify an array of responsive option arrays which are a media query and options object pair => [[mediaQueryString, optionsObject],[more...]]
72458   * @return {Object} An object which exposes the API for the created chart
72459   *
72460   * @example
72461   * // Create a simple bar chart
72462   * var data = {
72463   *   labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
72464   *   series: [
72465   *     [5, 2, 4, 2, 0]
72466   *   ]
72467   * };
72468   *
72469   * // In the global name space Chartist we call the Bar function to initialize a bar chart. As a first parameter we pass in a selector where we would like to get our chart created and as a second parameter we pass our data object.
72470   * new Chartist.Bar('.ct-chart', data);
72471   *
72472   * @example
72473   * // This example creates a bipolar grouped bar chart where the boundaries are limitted to -10 and 10
72474   * new Chartist.Bar('.ct-chart', {
72475   *   labels: [1, 2, 3, 4, 5, 6, 7],
72476   *   series: [
72477   *     [1, 3, 2, -5, -3, 1, -6],
72478   *     [-5, -2, -4, -1, 2, -3, 1]
72479   *   ]
72480   * }, {
72481   *   seriesBarDistance: 12,
72482   *   low: -10,
72483   *   high: 10
72484   * });
72485   *
72486   */
72487  function Bar(query, data, options, responsiveOptions) {
72488    Chartist.Bar.super.constructor.call(this,
72489      query,
72490      data,
72491      defaultOptions,
72492      Chartist.extend({}, defaultOptions, options),
72493      responsiveOptions);
72494  }
72495
72496  // Creating bar chart type in Chartist namespace
72497  Chartist.Bar = Chartist.Base.extend({
72498    constructor: Bar,
72499    createChart: createChart
72500  });
72501
72502}(window, document, Chartist));
72503;/**
72504 * The pie chart module of Chartist that can be used to draw pie, donut or gauge charts
72505 *
72506 * @module Chartist.Pie
72507 */
72508/* global Chartist */
72509(function(window, document, Chartist) {
72510  'use strict';
72511
72512  /**
72513   * Default options in line charts. Expand the code view to see a detailed list of options with comments.
72514   *
72515   * @memberof Chartist.Pie
72516   */
72517  var defaultOptions = {
72518    // Specify a fixed width for the chart as a string (i.e. '100px' or '50%')
72519    width: undefined,
72520    // Specify a fixed height for the chart as a string (i.e. '100px' or '50%')
72521    height: undefined,
72522    // Padding of the chart drawing area to the container element and labels as a number or padding object {top: 5, right: 5, bottom: 5, left
72522: 5}
72523    chartPadding: 5,
72524    // Override the class names that are used to generate the SVG structure of the chart
72525    classNames: {
72526      chartPie: 'ct-chart-pie',
72527      chartDonut: 'ct-chart-donut',
72528      series: 'ct-series',
72529      slicePie: 'ct-slice-pie',
72530      sliceDonut: 'ct-slice-donut',
72531      sliceDonutSolid: 'ct-slice-donut-solid',
72532      label: 'ct-label'
72533    },
72534    // The start angle of the pie chart in degrees where 0 points north. A higher value offsets the start angle clockwise.
72535    startAngle: 0,
72536    // An optional total you can specify. By specifying a total value, the sum of the values in the series must be this total in order to draw a full pie. You can use this parameter to draw only parts of a pie or gauge charts.
72537    total: undefined,
72538    // If specified the donut CSS classes will be used and strokes will be drawn instead of pie slices.
72539    donut: false,
72540    // If specified the donut segments will be drawn as shapes instead of strokes.
72541    donutSolid: false,
72542    // Specify the donut stroke width, currently done in javascript for convenience. May move to CSS styles in the future.
72543    // This option can be set as number or string to specify a relative width (i.e. 100 or '30%').
72544    donutWidth: 60,
72545    // If a label should be shown or not
72546    showLabel: true,
72547    // Label position offset from the standard position which is half distance of the radius. This value can be either positive or negative. Positive values will position the label away from the center.
72548    labelOffset: 0,
72549    // This option can be set to 'inside', 'outside' or 'center'. Positioned with 'inside' the labels will be placed on half the distance of the radius to the border of the Pie by respecting the 'labelOffset'. The 'outside' option will place the labels at the border of the pie and 'center' will place the labels in the absolute center point of the chart. The 'center' option only makes sense in conjunction with the 'labelOffset' option.
72550    labelPosition: 'inside',
72551    // An interpolation function for the label value
72552    labelInterpolationFnc: Chartist.noop,
72553    // Label direction can be 'neutral', 'explode' or 'implode'. The labels anchor will be positioned based on those settings as well as the fact if the labels are on the right or left side of the center of the chart. Usually explode is useful when labels are positioned far away from the center.
72554    labelDirection: 'neutral',
72555    // If true the whole data is reversed including labels, the series order as well as the whole series data arrays.
72556    reverseData: false,
72557    // If true empty values will be ignored to avoid drawing unncessary slices and labels
72558    ignoreEmptyValues: false
72559  };
72560
72561  /**
72562   * Determines SVG anchor position based on direction and center parameter
72563   *
72564   * @param center
72565   * @param label
72566   * @param direction
72567   * @return {string}
72568   */
72569  function determineAnchorPosition(center, label, direction) {
72570    var toTheRight = label.x > center.x;
72571
72572    if(toTheRight && direction === 'explode' ||
72573      !toTheRight && direction === 'implode') {
72574      return 'start';
72575    } else if(toTheRight && direction === 'implode' ||
72576      !toTheRight && direction === 'explode') {
72577      return 'end';
72578    } else {
72579      return 'middle';
72580    }
72581  }
72582
72583  /**
72584   * Creates the pie chart
72585   *
72586   * @param options
72587   */
72588  function createChart(options) {
72589    var data = Chartist.normalizeData(this.data);
72590    var seriesGroups = [],
72591      labelsGroup,
72592      chartRect,
72593      radius,
72594      labelRadius,
72595      totalDataSum,
72596      startAngle = options.startAngle;
72597
72598    // Create SVG.js draw
72599    this.svg = Chartist.createSvg(this.container, options.width, options.height,options.donut ? options.classNames.chartDonut : options.classNames.chartPie);
72600    // Calculate charting rect
72601    chartRect = Chartist.createChartRect(this.svg, options, defaultOptions.padding);
72602    // Get biggest circle radius possible within chartRect
72603    radius = Math.min(chartRect.width() / 2, chartRect.height() / 2);
72604    // Calculate total of all series to get reference value or use total reference from optional options
72605    totalDataSum = options.total || data.normalized.series.reduce(function(previousValue, currentValue) {
72606      return previousValue + currentValue;
72607    }, 0);
72608
72609    var donutWidth = Chartist.quantity(options.donutWidth);
72610    if (donutWidth.unit === '%') {
72611      donutWidth.value *= radius / 100;
72612    }
72613
72614    // If this is a donut chart we need to adjust our radius to enable strokes to be drawn inside
72615    // Unfortunately this is not possible with the current SVG Spec
72616    // See this proposal for more details: http://lists.w3.org/Archives/Public/www-svg/2003Oct/0000.html
72617    radius -= options.donut && !options.donutSolid ? donutWidth.value / 2  : 0;
72618
72619    // If labelPosition is set to `outside` or a donut chart is drawn then the label position is at the radius,
72620    // if regular pie chart it's half of the radius
72621    if(options.labelPosition === 'outside' || options.donut && !options.donutSolid) {
72622      labelRadius = radius;
72623    } else if(options.labelPosition === 'center') {
72624      // If labelPosition is center we start with 0 and will later wait for the labelOffset
72625      labelRadius = 0;
72626    } else if(options.donutSolid) {
72627      labelRadius = radius - donutWidth.value / 2;
72628    } else {
72629      // Default option is 'inside' where we use half the radius so the label will be placed in the center of the pie
72630      // slice
72631      labelRadius = radius / 2;
72632    }
72633    // Add the offset to the labelRadius where a negative offset means closed to the center of the chart
72634    labelRadius += options.labelOffset;
72635
72636    // Calculate end angle based on total sum and current data value and offset with padding
72637    var center = {
72638      x: chartRect.x1 + chartRect.width() / 2,
72639      y: chartRect.y2 + chartRect.height() / 2
72640    };
72641
72642    // Check if there is only one non-zero value in the series array.
72643    var hasSingleValInSeries = data.raw.series.filter(function(val) {
72644      return val.hasOwnProperty('value') ? val.value !== 0 : val !== 0;
72645    }).length === 1;
72646
72647    // Creating the series groups
72648    data.raw.series.forEach(function(series, index) {
72649      seriesGroups[index] = this.svg.elem('g', null, null);
72650    }.bind(this));
72651    //if we need to show labels we create the label group now
72652    if(options.showLabel) {
72653      labelsGroup = this.svg.elem('g', null, null);
72654    }
72655
72656    // Draw the series
72657    // initialize series groups
72658    data.raw.series.forEach(function(series, index) {
72659      // If current value is zero and we are ignoring empty values then skip to next value
72660      if (data.normalized.series[index] === 0 && options.ignoreEmptyValues) return;
72661
72662      // If the series is an object and contains a name or meta data we add a custom attribute
72663      seriesGroups[index].attr({
72664        'ct:series-name': series.name
72665      });
72666
72667      // Use series class from series data or if not set generate one
72668      seriesGroups[index].addClass([
72669        options.classNames.series,
72670        (series.className || options.classNames.series + '-' + Chartist.alphaNumerate(index))
72671      ].join(' '));
72672
72673      // If the whole dataset is 0 endAngle should be zero. Can't divide by 0.
72674      var endAngle = (totalDataSum > 0 ? startAngle + data.normalized.series[index] / totalDataSum * 360 : 0);
72675
72676      // Use slight offset so there are no transparent hairline issues
72677      var overlappigStartAngle = Math.max(0, startAngle - (index === 0 || hasSingleValInSeries ? 0 : 0.2));
72678
72679      // If we need to draw the arc for all 360 degrees we need to add a hack where we close the circle
72680      // with Z and use 359.99 degrees
72681      if(endAngle - overlappigStartAngle >= 359.99) {
72682        endAngle = overlappigStartAngle + 359.99;
72683      }
72684
72685      var start = Chartist.polarToCartesian(center.x, center.y, radius, overlappigStartAngle),
72686        end = Chartist.polarToCartesian(center.x, center.y, radius, endAngle);
72687
72688      var innerStart,
72689        innerEnd,
72690        donutSolidRadius;
72691
72692      // Create a new path element for the pie chart. If this isn't a donut chart we should close the path for a correct stroke
72693      var path = new Chartist.Svg.Path(!options.donut || options.donutSolid)
72694        .move(end.x, end.y)
72695        .arc(radius, radius, 0, endAngle - startAngle > 180, 0, start.x, start.y);
72696
72697      // If regular pie chart (no donut) we add a line to the center of the circle for completing the pie
72698      if(!options.donut) {
72699        path.line(center.x, center.y);
72700      } else if (options.donutSolid) {
72701        donutSolidRadius = radius - donutWidth.value;
72702        innerStart = Chartist.polarToCartesian(center.x, center.y, donutSolidRadius, startAngle - (index === 0 || hasSingleValInSeries ? 0 : 0.2));
72703        innerEnd = Chartist.polarToCartesian(center.x, center.y, donutSolidRadius, endAngle);
72704        path.line(innerStart.x, innerStart.y);
72705        path.arc(donutSolidRadius, donutSolidRadius, 0, endAngle - startAngle  > 180, 1, innerEnd.x, innerEnd.y);
72706      }
72707
72708      // Create the SVG path
72709      // If this is a donut chart we add the donut class, otherwise just a regular slice
72710      var pathClassName = options.classNames.slicePie;
72711      if (options.donut) {
72712        pathClassName = options.classNames.sliceDonut;
72713        if (options.donutSolid) {
72714          pathClassName = options.classNames.sliceDonutSolid;
72715        }
72716      }
72717      var pathElement = seriesGroups[index].elem('path', {
72718        d: path.stringify()
72719      }, pathClassName);
72720
72721      // Adding the pie series value to the path
72722      pathElement.attr({
72723        'ct:value': data.normalized.series[index],
72724        'ct:meta': Chartist.serialize(series.meta)
72725      });
72726
72727      // If this is a donut, we add the stroke-width as style attribute
72728      if(options.donut && !options.donutSolid) {
72729        pathElement._node.style.strokeWidth = donutWidth.value + 'px';
72730      }
72731
72732      // Fire off draw event
72733      this.eventEmitter.emit('draw', {
72734        type: 'slice',
72735        value: data.normalized.series[index],
72736        totalDataSum: totalDataSum,
72737        index: index,
72738        meta: series.meta,
72739        series: series,
72740        group: seriesGroups[index],
72741        element: pathElement,
72742        path: path.clone(),
72743        center: center,
72744        radius: radius,
72745        startAngle: startAngle,
72746        endAngle: endAngle
72747      });
72748
72749      // If we need to show labels we need to add the label for this slice now
72750      if(options.showLabel) {
72751        var labelPosition;
72752        if(data.raw.series.length === 1) {
72753          // If we have only 1 series, we can position the label in the center of the pie
72754          labelPosition = {
72755            x: center.x,
72756            y: center.y
72757          };
72758        } else {
72759          // Position at the labelRadius distance from center and between start and end angle
72760          labelPosition = Chartist.polarToCartesian(
72761            center.x,
72762            center.y,
72763            labelRadius,
72764            startAngle + (endAngle - startAngle) / 2
72765          );
72766        }
72767
72768        var rawValue;
72769        if(data.normalized.labels && !Chartist.isFalseyButZero(data.normalized.labels[index])) {
72770          rawValue = data.normalized.labels[index];
72771        } else {
72772          rawValue = data.normalized.series[index];
72773        }
72774
72775        var interpolatedValue = options.labelInterpolationFnc(rawValue, index);
72776
72777        if(interpolatedValue || interpolatedValue === 0) {
72778          var labelElement = labelsGroup.elem('text', {
72779            dx: labelPosition.x,
72780            dy: labelPosition.y,
72781            'text-anchor': determineAnchorPosition(center, labelPosition, options.labelDirection)
72782          }, options.classNames.label).text('' + interpolatedValue);
72783
72784          // Fire off draw event
72785          this.eventEmitter.emit('draw', {
72786            type: 'label',
72787            index: index,
72788            group: labelsGroup,
72789            element: labelElement,
72790            text: '' + interpolatedValue,
72791            x: labelPosition.x,
72792            y: labelPosition.y
72793          });
72794        }
72795      }
72796
72797      // Set next startAngle to current endAngle.
72798      // (except for last slice)
72799      startAngle = endAngle;
72800    }.bind(this));
72801
72802    this.eventEmitter.emit('created', {
72803      chartRect: chartRect,
72804      svg: this.svg,
72805      options: options
72806    });
72807  }
72808
72809  /**
72810   * This method creates a new pie chart and returns an object that can be used to redraw the chart.
72811   *
72812   * @memberof Chartist.Pie
72813   * @param {String|Node} query A selector query string or directly a DOM element
72814   * @param {Object} data The data object in the pie chart needs to have a series property with a one dimensional data array. The values will be normalized against each other and don't necessarily need to be in percentage. The series property can also be an array of value objects that contain a value property and a className property to override the CSS class name for the series group.
72815   * @param {Object} [options] The options object with options that override the default options. Check the examples for a detailed list.
72816   * @param {Array} [responsiveOptions] Specify an array of responsive option arrays which are a media query and options object pair => [[mediaQueryString, optionsObject],[more...]]
72817   * @return {Object} An object with a version and an update method to manually redraw the chart
72818   *
72819   * @example
72820   * // Simple pie chart example with four series
72821   * new Chartist.Pie('.ct-chart', {
72822   *   series: [10, 2, 4, 3]
72823   * });
72824   *
72825   * @example
72826   * // Drawing a donut chart
72827   * new Chartist.Pie('.ct-chart', {
72828   *   series: [10, 2, 4, 3]
72829   * }, {
72830   *   donut: true
72831   * });
72832   *
72833   * @example
72834   * // Using donut, startAngle and total to draw a gauge chart
72835   * new Chartist.Pie('.ct-chart', {
72836   *   series: [20, 10, 30, 40]
72837   * }, {
72838   *   donut: true,
72839   *   donutWidth: 20,
72840   *   startAngle: 270,
72841   *   total: 200
72842   * });
72843   *
72844   * @example
72845   * // Drawing a pie chart with padding and labels that are outside the pie
72846   * new Chartist.Pie('.ct-chart', {
72847   *   series: [20, 10, 30, 40]
72848   * }, {
72849   *   chartPadding: 30,
72850   *   labelOffset: 50,
72851   *   labelDirection: 'explode'
72852   * });
72853   *
72854   * @example
72855   * // Overriding the class names for individual series as well as a name and meta data.
72856   * // The name will be written as ct:series-name attribute and the meta data will be serialized and written
72857   * // to a ct:meta attribute.
72858   * new Chartist.Pie('.ct-chart', {
72859   *   series: [{
72860   *     value: 20,
72861   *     name: 'Series 1',
72862   *     className: 'my-custom-class-one',
72863   *     meta: 'Meta One'
72864   *   }, {
72865   *     value: 10,
72866   *     name: 'Series 2',
72867   *     className: 'my-custom-class-two',
72868   *     meta: 'Meta Two'
72869   *   }, {
72870   *     value: 70,
72871   *     name: 'Series 3',
72872   *     className: 'my-custom-class-three',
72873   *     meta: 'Meta Three'
72874   *   }]
72875   * });
72876   */
72877  function Pie(query, data, options, responsiveOptions) {
72878    Chartist.Pie.super.constructor.call(this,
72879      query,
72880      data,
72881      defaultOptions,
72882      Chartist.extend({}, defaultOptions, options),
72883      responsiveOptions);
72884  }
72885
72886  // Creating pie chart type in Chartist namespace
72887  Chartist.Pie = Chartist.Base.extend({
72888    constructor: Pie,
72889    createChart: createChart,
72890    determineAnchorPosition: determineAnchorPosition
72891  });
72892
72893}(window, document, Chartist));
72894
72895return Chartist;
72896
72897}));
72898
72899/*!
72900 * Chart.js
72901 * http://chartjs.org/
72902 * Version: 2.7.3
72903 *
72904 * Copyright 2018 Chart.js Contributors
72905 * Released under the MIT license
72906 * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
72907 */
72908(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Chart = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
72909/* MIT license */
72910var colorNames = require(5);
72911
72912module.exports = {
72913   getRgba: getRgba,
72914   getHsla: getHsla,
72915   getRgb: getRgb,
72916   getHsl: getHsl,
72917   getHwb: getHwb,
72918   getAlpha: getAlpha,
72919
72920   hexString: hexString,
72921   rgbString: rgbString,
72922   rgbaString: rgbaString,
72923   percentString: percentString,
72924   percentaString: percentaString,
72925   hslString: hslString,
72926   hslaString: hslaString,
72927   hwbString: hwbString,
72928   keyword: keyword
72929}
72930
72931function getRgba(string) {
72932   if (!string) {
72933      return;
72934   }
72935   var abbr =  /^#([a-fA-F0-9]{3})$/i,
72936       hex =  /^#([a-fA-F0-9]{6})$/i,
72937       rgba = /^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,
72938       per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,
72939       keyword = /(\w+)/;
72940
72941   var rgb = [0, 0, 0],
72942       a = 1,
72943       match = string.match(abbr);
72944   if (match) {
72945      match = match[1];
72946      for (var i = 0; i < rgb.length; i++) {
72947         rgb[i] = parseInt(match[i] + match[i], 16);
72948      }
72949   }
72950   else if (match = string.match(hex)) {
72951      match = match[1];
72952      for (var i = 0; i < rgb.length; i++) {
72953         rgb[i] = parseInt(match.slice(i * 2, i * 2 + 2), 16);
72954      }
72955   }
72956   else if (match = string.match(rgba)) {
72957      for (var i = 0; i < rgb.length; i++) {
72958         rgb[i] = parseInt(match[i + 1]);
72959      }
72960      a = parseFloat(match[4]);
72961   }
72962   else if (match = string.match(per)) {
72963      for (var i = 0; i < rgb.length; i++) {
72964         rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55);
72965      }
72966      a = parseFloat(match[4]);
72967   }
72968   else if (match = string.match(keyword)) {
72969      if (match[1] == "transparent") {
72970         return [0, 0, 0, 0];
72971      }
72972      rgb = colorNames[match[1]];
72973      if (!rgb) {
72974         return;
72975      }
72976   }
72977
72978   for (var i = 0; i < rgb.length; i++) {
72979      rgb[i] = scale(rgb[i], 0, 255);
72980   }
72981   if (!a && a != 0) {
72982      a = 1;
72983   }
72984   else {
72985      a = scale(a, 0, 1);
72986   }
72987   rgb[3] = a;
72988   return rgb;
72989}
72990
72991function getHsla(string) {
72992   if (!string) {
72993      return;
72994   }
72995   var hsl = /^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/;
72996   var match = string.match(hsl);
72997   if (match) {
72998      var alpha = parseFloat(match[4]);
72999      var h = scale(parseInt(match[1]), 0, 360),
73000          s = scale(parseFloat(match[2]), 0, 100),
73001          l = scale(parseFloat(match[3]), 0, 100),
73002          a = scale(isNaN(alpha) ? 1 : alpha, 0, 1);
73003      return [h, s, l, a];
73004   }
73005}
73006
73007function getHwb(string) {
73008   if (!string) {
73009      return;
73010   }
73011   var hwb = /^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/;
73012   var match = string.match(hwb);
73013   if (match) {
73014    var alpha = parseFloat(match[4]);
73015      var h = scale(parseInt(match[1]), 0, 360),
73016          w = scale(parseFloat(match[2]), 0, 100),
73017          b = scale(parseFloat(match[3]), 0, 100),
73018          a = scale(isNaN(alpha) ? 1 : alpha, 0, 1);
73019      return [h, w, b, a];
73020   }
73021}
73022
73023function getRgb(string) {
73024   var rgba = getRgba(string);
73025   return rgba && rgba.slice(0, 3);
73026}
73027
73028function getHsl(string) {
73029  var hsla = getHsla(string);
73030  return hsla && hsla.slice(0, 3);
73031}
73032
73033function getAlpha(string) {
73034   var vals = getRgba(string);
73035   if (vals) {
73036      return vals[3];
73037   }
73038   else if (vals = getHsla(string)) {
73039      return vals[3];
73040   }
73041   else if (vals = getHwb(string)) {
73042      return vals[3];
73043   }
73044}
73045
73046// generators
73047function hexString(rgb) {
73048   return "#" + hexDouble(rgb[0]) + hexDouble(rgb[1])
73049              + hexDouble(rgb[2]);
73050}
73051
73052function rgbString(rgba, alpha) {
vendor: 14,231 bytes, lines 73053-73657
73053   if (alpha < 1 || (rgba[3] && rgba[3] < 1)) {
73054      return rgbaString(rgba, alpha);
73055   }
73056   return "rgb(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + ")";
73057}
73058
73059function rgbaString(rgba, alpha) {
73060   if (alpha === undefined) {
73061      alpha = (rgba[3] !== undefined ? rgba[3] : 1);
73062   }
73063   return "rgba(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2]
73064           + ", " + alpha + ")";
73065}
73066
73067function percentString(rgba, alpha) {
73068   if (alpha < 1 || (rgba[3] && rgba[3] < 1)) {
73069      return percentaString(rgba, alpha);
73070   }
73071   var r = Math.round(rgba[0]/255 * 100),
73072       g = Math.round(rgba[1]/255 * 100),
73073       b = Math.round(rgba[2]/255 * 100);
73074
73075   return "rgb(" + r + "%, " + g + "%, " + b + "%)";
73076}
73077
73078function percentaString(rgba, alpha) {
73079   var r = Math.round(rgba[0]/255 * 100),
73080       g = Math.round(rgba[1]/255 * 100),
73081       b = Math.round(rgba[2]/255 * 100);
73082   return "rgba(" + r + "%, " + g + "%, " + b + "%, " + (alpha || rgba[3] || 1) + ")";
73083}
73084
73085function hslString(hsla, alpha) {
73086   if (alpha < 1 || (hsla[3] && hsla[3] < 1)) {
73087      return hslaString(hsla, alpha);
73088   }
73089   return "hsl(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%)";
73090}
73091
73092function hslaString(hsla, alpha) {
73093   if (alpha === undefined) {
73094      alpha = (hsla[3] !== undefined ? hsla[3] : 1);
73095   }
73096   return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, "
73097           + alpha + ")";
73098}
73099
73100// hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax
73101// (hwb have alpha optional & 1 is default value)
73102function hwbString(hwb, alpha) {
73103   if (alpha === undefined) {
73104      alpha = (hwb[3] !== undefined ? hwb[3] : 1);
73105   }
73106   return "hwb(" + hwb[0] + ", " + hwb[1] + "%, " + hwb[2] + "%"
73107           + (alpha !== undefined && alpha !== 1 ? ", " + alpha : "") + ")";
73108}
73109
73110function keyword(rgb) {
73111  return reverseNames[rgb.slice(0, 3)];
73112}
73113
73114// helpers
73115function scale(num, min, max) {
73116   return Math.min(Math.max(min, num), max);
73117}
73118
73119function hexDouble(num) {
73120  var str = num.toString(16).toUpperCase();
73121  return (str.length < 2) ? "0" + str : str;
73122}
73123
73124
73125//create a list of reverse color names
73126var reverseNames = {};
73127for (var name in colorNames) {
73128   reverseNames[colorNames[name]] = name;
73129}
73130
73131},{"5":5}],2:[function(require,module,exports){
73132/* MIT license */
73133var convert = require(4);
73134var string = require(1);
73135
73136var Color = function (obj) {
73137	if (obj instanceof Color) {
73138		return obj;
73139	}
73140	if (!(this instanceof Color)) {
73141		return new Color(obj);
73142	}
73143
73144	this.valid = false;
73145	this.values = {
73146		rgb: [0, 0, 0],
73147		hsl: [0, 0, 0],
73148		hsv: [0, 0, 0],
73149		hwb: [0, 0, 0],
73150		cmyk: [0, 0, 0, 0],
73151		alpha: 1
73152	};
73153
73154	// parse Color() argument
73155	var vals;
73156	if (typeof obj === 'string') {
73157		vals = string.getRgba(obj);
73158		if (vals) {
73159			this.setValues('rgb', vals);
73160		} else if (vals = string.getHsla(obj)) {
73161			this.setValues('hsl', vals);
73162		} else if (vals = string.getHwb(obj)) {
73163			this.setValues('hwb', vals);
73164		}
73165	} else if (typeof obj === 'object') {
73166		vals = obj;
73167		if (vals.r !== undefined || vals.red !== undefined) {
73168			this.setValues('rgb', vals);
73169		} else if (vals.l !== undefined || vals.lightness !== undefined) {
73170			this.setValues('hsl', vals);
73171		} else if (vals.v !== undefined || vals.value !== undefined) {
73172			this.setValues('hsv', vals);
73173		} else if (vals.w !== undefined || vals.whiteness !== undefined) {
73174			this.setValues('hwb', vals);
73175		} else if (vals.c !== undefined || vals.cyan !== undefined) {
73176			this.setValues('cmyk', vals);
73177		}
73178	}
73179};
73180
73181Color.prototype = {
73182	isValid: function () {
73183		return this.valid;
73184	},
73185	rgb: function () {
73186		return this.setSpace('rgb', arguments);
73187	},
73188	hsl: function () {
73189		return this.setSpace('hsl', arguments);
73190	},
73191	hsv: function () {
73192		return this.setSpace('hsv', arguments);
73193	},
73194	hwb: function () {
73195		return this.setSpace('hwb', arguments);
73196	},
73197	cmyk: function () {
73198		return this.setSpace('cmyk', arguments);
73199	},
73200
73201	rgbArray: function () {
73202		return this.values.rgb;
73203	},
73204	hslArray: function () {
73205		return this.values.hsl;
73206	},
73207	hsvArray: function () {
73208		return this.values.hsv;
73209	},
73210	hwbArray: function () {
73211		var values = this.values;
73212		if (values.alpha !== 1) {
73213			return values.hwb.concat([values.alpha]);
73214		}
73215		return values.hwb;
73216	},
73217	cmykArray: function () {
73218		return this.values.cmyk;
73219	},
73220	rgbaArray: function () {
73221		var values = this.values;
73222		return values.rgb.concat([values.alpha]);
73223	},
73224	hslaArray: function () {
73225		var values = this.values;
73226		return values.hsl.concat([values.alpha]);
73227	},
73228	alpha: function (val) {
73229		if (val === undefined) {
73230			return this.values.alpha;
73231		}
73232		this.setValues('alpha', val);
73233		return this;
73234	},
73235
73236	red: function (val) {
73237		return this.setChannel('rgb', 0, val);
73238	},
73239	green: function (val) {
73240		return this.setChannel('rgb', 1, val);
73241	},
73242	blue: function (val) {
73243		return this.setChannel('rgb', 2, val);
73244	},
73245	hue: function (val) {
73246		if (val) {
73247			val %= 360;
73248			val = val < 0 ? 360 + val : val;
73249		}
73250		return this.setChannel('hsl', 0, val);
73251	},
73252	saturation: function (val) {
73253		return this.setChannel('hsl', 1, val);
73254	},
73255	lightness: function (val) {
73256		return this.setChannel('hsl', 2, val);
73257	},
73258	saturationv: function (val) {
73259		return this.setChannel('hsv', 1, val);
73260	},
73261	whiteness: function (val) {
73262		return this.setChannel('hwb', 1, val);
73263	},
73264	blackness: function (val) {
73265		return this.setChannel('hwb', 2, val);
73266	},
73267	value: function (val) {
73268		return this.setChannel('hsv', 2, val);
73269	},
73270	cyan: function (val) {
73271		return this.setChannel('cmyk', 0, val);
73272	},
73273	magenta: function (val) {
73274		return this.setChannel('cmyk', 1, val);
73275	},
73276	yellow: function (val) {
73277		return this.setChannel('cmyk', 2, val);
73278	},
73279	black: function (val) {
73280		return this.setChannel('cmyk', 3, val);
73281	},
73282
73283	hexString: function () {
73284		return string.hexString(this.values.rgb);
73285	},
73286	rgbString: function () {
73287		return string.rgbString(this.values.rgb, this.values.alpha);
73288	},
73289	rgbaString: function () {
73290		return string.rgbaString(this.values.rgb, this.values.alpha);
73291	},
73292	percentString: function () {
73293		return string.percentString(this.values.rgb, this.values.alpha);
73294	},
73295	hslString: function () {
73296		return string.hslString(this.values.hsl, this.values.alpha);
73297	},
73298	hslaString: function () {
73299		return string.hslaString(this.values.hsl, this.values.alpha);
73300	},
73301	hwbString: function () {
73302		return string.hwbString(this.values.hwb, this.values.alpha);
73303	},
73304	keyword: function () {
73305		return string.keyword(this.values.rgb, this.values.alpha);
73306	},
73307
73308	rgbNumber: function () {
73309		var rgb = this.values.rgb;
73310		return (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
73311	},
73312
73313	luminosity: function () {
73314		// http://www.w3.org/TR/WCAG20/#relativeluminancedef
73315		var rgb = this.values.rgb;
73316		var lum = [];
73317		for (var i = 0; i < rgb.length; i++) {
73318			var chan = rgb[i] / 255;
73319			lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4);
73320		}
73321		return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2];
73322	},
73323
73324	contrast: function (color2) {
73325		// http://www.w3.org/TR/WCAG20/#contrast-ratiodef
73326		var lum1 = this.luminosity();
73327		var lum2 = color2.luminosity();
73328		if (lum1 > lum2) {
73329			return (lum1 + 0.05) / (lum2 + 0.05);
73330		}
73331		return (lum2 + 0.05) / (lum1 + 0.05);
73332	},
73333
73334	level: function (color2) {
73335		var contrastRatio = this.contrast(color2);
73336		if (contrastRatio >= 7.1) {
73337			return 'AAA';
73338		}
73339
73340		return (contrastRatio >= 4.5) ? 'AA' : '';
73341	},
73342
73343	dark: function () {
73344		// YIQ equation from http://24ways.org/2010/calculating-color-contrast
73345		var rgb = this.values.rgb;
73346		var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000;
73347		return yiq < 128;
73348	},
73349
73350	light: function () {
73351		return !this.dark();
73352	},
73353
73354	negate: function () {
73355		var rgb = [];
73356		for (var i = 0; i < 3; i++) {
73357			rgb[i] = 255 - this.values.rgb[i];
73358		}
73359		this.setValues('rgb', rgb);
73360		return this;
73361	},
73362
73363	lighten: function (ratio) {
73364		var hsl = this.values.hsl;
73365		hsl[2] += hsl[2] * ratio;
73366		this.setValues('hsl', hsl);
73367		return this;
73368	},
73369
73370	darken: function (ratio) {
73371		var hsl = this.values.hsl;
73372		hsl[2] -= hsl[2] * ratio;
73373		this.setValues('hsl', hsl);
73374		return this;
73375	},
73376
73377	saturate: function (ratio) {
73378		var hsl = this.values.hsl;
73379		hsl[1] += hsl[1] * ratio;
73380		this.setValues('hsl', hsl);
73381		return this;
73382	},
73383
73384	desaturate: function (ratio) {
73385		var hsl = this.values.hsl;
73386		hsl[1] -= hsl[1] * ratio;
73387		this.setValues('hsl', hsl);
73388		return this;
73389	},
73390
73391	whiten: function (ratio) {
73392		var hwb = this.values.hwb;
73393		hwb[1] += hwb[1] * ratio;
73394		this.setValues('hwb', hwb);
73395		return this;
73396	},
73397
73398	blacken: function (ratio) {
73399		var hwb = this.values.hwb;
73400		hwb[2] += hwb[2] * ratio;
73401		this.setValues('hwb', hwb);
73402		return this;
73403	},
73404
73405	greyscale: function () {
73406		var rgb = this.values.rgb;
73407		// http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
73408		var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11;
73409		this.setValues('rgb', [val, val, val]);
73410		return this;
73411	},
73412
73413	clearer: function (ratio) {
73414		var alpha = this.values.alpha;
73415		this.setValues('alpha', alpha - (alpha * ratio));
73416		return this;
73417	},
73418
73419	opaquer: function (ratio) {
73420		var alpha = this.values.alpha;
73421		this.setValues('alpha', alpha + (alpha * ratio));
73422		return this;
73423	},
73424
73425	rotate: function (degrees) {
73426		var hsl = this.values.hsl;
73427		var hue = (hsl[0] + degrees) % 360;
73428		hsl[0] = hue < 0 ? 360 + hue : hue;
73429		this.setValues('hsl', hsl);
73430		return this;
73431	},
73432
73433	/**
73434	 * Ported from sass implementation in C
73435	 * https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209
73436	 */
73437	mix: function (mixinColor, weight) {
73438		var color1 = this;
73439		var color2 = mixinColor;
73440		var p = weight === undefined ? 0.5 : weight;
73441
73442		var w = 2 * p - 1;
73443		var a = color1.alpha() - color2.alpha();
73444
73445		var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0;
73446		var w2 = 1 - w1;
73447
73448		return this
73449			.rgb(
73450				w1 * color1.red() + w2 * color2.red(),
73451				w1 * color1.green() + w2 * color2.green(),
73452				w1 * color1.blue() + w2 * color2.blue()
73453			)
73454			.alpha(color1.alpha() * p + color2.alpha() * (1 - p));
73455	},
73456
73457	toJSON: function () {
73458		return this.rgb();
73459	},
73460
73461	clone: function () {
73462		// NOTE(SB): using node-clone creates a dependency to Buffer when using browserify,
73463		// making the final build way to big to embed in Chart.js. So let's do it manually,
73464		// assuming that values to clone are 1 dimension arrays containing only numbers,
73465		// except 'alpha' which is a number.
73466		var result = new Color();
73467		var source = this.values;
73468		var target = result.values;
73469		var value, type;
73470
73471		for (var prop in source) {
73472			if (source.hasOwnProperty(prop)) {
73473				value = source[prop];
73474				type = ({}).toString.call(value);
73475				if (type === '[object Array]') {
73476					target[prop] = value.slice(0);
73477				} else if (type === '[object Number]') {
73478					target[prop] = value;
73479				} else {
73480					console.error('unexpected color value:', value);
73481				}
73482			}
73483		}
73484
73485		return result;
73486	}
73487};
73488
73489Color.prototype.spaces = {
73490	rgb: ['red', 'green', 'blue'],
73491	hsl: ['hue', 'saturation', 'lightness'],
73492	hsv: ['hue', 'saturation', 'value'],
73493	hwb: ['hue', 'whiteness', 'blackness'],
73494	cmyk: ['cyan', 'magenta', 'yellow', 'black']
73495};
73496
73497Color.prototype.maxes = {
73498	rgb: [255, 255, 255],
73499	hsl: [360, 100, 100],
73500	hsv: [360, 100, 100],
73501	hwb: [360, 100, 100],
73502	cmyk: [100, 100, 100, 100]
73503};
73504
73505Color.prototype.getValues = function (space) {
73506	var values = this.values;
73507	var vals = {};
73508
73509	for (var i = 0; i < space.length; i++) {
73510		vals[space.charAt(i)] = values[space][i];
73511	}
73512
73513	if (values.alpha !== 1) {
73514		vals.a = values.alpha;
73515	}
73516
73517	// {r: 255, g: 255, b: 255, a: 0.4}
73518	return vals;
73519};
73520
73521Color.prototype.setValues = function (space, vals) {
73522	var values = this.values;
73523	var spaces = this.spaces;
73524	var maxes = this.maxes;
73525	var alpha = 1;
73526	var i;
73527
73528	this.valid = true;
73529
73530	if (space === 'alpha') {
73531		alpha = vals;
73532	} else if (vals.length) {
73533		// [10, 10, 10]
73534		values[space] = vals.slice(0, space.length);
73535		alpha = vals[space.length];
73536	} else if (vals[space.charAt(0)] !== undefined) {
73537		// {r: 10, g: 10, b: 10}
73538		for (i = 0; i < space.length; i++) {
73539			values[space][i] = vals[space.charAt(i)];
73540		}
73541
73542		alpha = vals.a;
73543	} else if (vals[spaces[space][0]] !== undefined) {
73544		// {red: 10, green: 10, blue: 10}
73545		var chans = spaces[space];
73546
73547		for (i = 0; i < space.length; i++) {
73548			values[space][i] = vals[chans[i]];
73549		}
73550
73551		alpha = vals.alpha;
73552	}
73553
73554	values.alpha = Math.max(0, Math.min(1, (alpha === undefined ? values.alpha : alpha)));
73555
73556	if (space === 'alpha') {
73557		return false;
73558	}
73559
73560	var capped;
73561
73562	// cap values of the space prior converting all values
73563	for (i = 0; i < space.length; i++) {
73564		capped = Math.max(0, Math.min(maxes[space][i], values[space][i]));
73565		values[space][i] = Math.round(capped);
73566	}
73567
73568	// convert to all the other color spaces
73569	for (var sname in spaces) {
73570		if (sname !== space) {
73571			values[sname] = convert[space][sname](values[space]);
73572		}
73573	}
73574
73575	return true;
73576};
73577
73578Color.prototype.setSpace = function (space, args) {
73579	var vals = args[0];
73580
73581	if (vals === undefined) {
73582		// color.rgb()
73583		return this.getValues(space);
73584	}
73585
73586	// color.rgb(10, 10, 10)
73587	if (typeof vals === 'number') {
73588		vals = Array.prototype.slice.call(args);
73589	}
73590
73591	this.setValues(space, vals);
73592	return this;
73593};
73594
73595Color.prototype.setChannel = function (space, index, val) {
73596	var svalues = this.values[space];
73597	if (val === undefined) {
73598		// color.red()
73599		return svalues[index];
73600	} else if (val === svalues[index]) {
73601		// color.red(color.red())
73602		return this;
73603	}
73604
73605	// color.red(100)
73606	svalues[index] = val;
73607	this.setValues(space, svalues);
73608
73609	return this;
73610};
73611
73612if (typeof window !== 'undefined') {
73613	window.Color = Color;
73614}
73615
73616module.exports = Color;
73617
73618},{"1":1,"4":4}],3:[function(require,module,exports){
73619/* MIT license */
73620
73621module.exports = {
73622  rgb2hsl: rgb2hsl,
73623  rgb2hsv: rgb2hsv,
73624  rgb2hwb: rgb2hwb,
73625  rgb2cmyk: rgb2cmyk,
73626  rgb2keyword: rgb2keyword,
73627  rgb2xyz: rgb2xyz,
73628  rgb2lab: rgb2lab,
73629  rgb2lch: rgb2lch,
73630
73631  hsl2rgb: hsl2rgb,
73632  hsl2hsv: hsl2hsv,
73633  hsl2hwb: hsl2hwb,
73634  hsl2cmyk: hsl2cmyk,
73635  hsl2keyword: hsl2keyword,
73636
73637  hsv2rgb: hsv2rgb,
73638  hsv2hsl: hsv2hsl,
73639  hsv2hwb: hsv2hwb,
73640  hsv2cmyk: hsv2cmyk,
73641  hsv2keyword: hsv2keyword,
73642
73643  hwb2rgb: hwb2rgb,
73644  hwb2hsl: hwb2hsl,
73645  hwb2hsv: hwb2hsv,
73646  hwb2cmyk: hwb2cmyk,
73647  hwb2keyword: hwb2keyword,
73648
73649  cmyk2rgb: cmyk2rgb,
73650  cmyk2hsl: cmyk2hsl,
73651  cmyk2hsv: cmyk2hsv,
73652  cmyk2hwb: cmyk2hwb,
73653  cmyk2keyword: cmyk2keyword,
73654
73655  keyword2rgb: keyword2rgb,
73656  keyword2hsl: keyword2hsl,
73657  keyword2hsv: keyword2hsv,
73658  keyword2hwb: keyword2hwb,
73659  keyword2cmyk: keyword2cmyk,
73660  keyword2lab: keyword2lab,
73661  keyword2xyz: keyword2xyz,
73662
73663  xyz2rgb: xyz2rgb,
73664  xyz2lab: xyz2lab,
73665  xyz2lch: xyz2lch,
73666
73667  lab2xyz: lab2xyz,
73668  lab2rgb: lab2rgb,
73669  lab2lch: lab2lch,
73670
73671  lch2lab: lch2lab,
73672  lch2xyz: lch2xyz,
73673  lch2rgb: lch2rgb
73674}
73675
73676
73677function rgb2hsl(rgb) {
73678  var r = rgb[0]/255,
73679      g = rgb[1]/255,
73680      b = rgb[2]/255,
73681      min = Math.min(r, g, b),
73682      max = Math.max(r, g, b),
73683      delta = max - min,
73684      h, s, l;
73685
73686  if (max == min)
73687    h = 0;
73688  else if (r == max)
73689    h = (g - b) / delta;
73690  else if (g == max)
73691    h = 2 + (b - r) / delta;
73692  else if (b == max)
73693    h = 4 + (r - g)/ delta;
73694
73695  h = Math.min(h * 60, 360);
73696
73697  if (h < 0)
73698    h += 360;
73699
73700  l = (min + max) / 2;
73701
73702  if (max == min)
73703    s = 0;
73704  else if (l <= 0.5)
73705    s = delta / (max + min);
73706  else
73707    s = delta / (2 - max - min);
73708
73709  return [h, s * 100, l * 100];
73710}
73711
73712function rgb2hsv(rgb) {
73713  var r = rgb[0],
73714      g = rgb[1],
73715      b = rgb[2],
73716      min = Math.min(r, g, b),
73717      max = Math.max(r, g, b),
73718      delta = max - min,
73719      h, s, v;
73720
73721  if (max == 0)
73722    s = 0;
73723  else
73724    s = (delta/max * 1000)/10;
73725
73726  if (max == min)
73727    h = 0;
73728  else if (r == max)
73729    h = (g - b) / delta;
73730  else if (g == max)
73731    h = 2 + (b - r) / delta;
73732  else if (b == max)
73733    h = 4 + (r - g) / delta;
73734
73735  h = Math.min(h * 60, 360);
73736
73737  if (h < 0)
73738    h += 360;
73739
73740  v = ((max / 255) * 1000) / 10;
73741
73742  return [h, s, v];
73743}
73744
73745function rgb2hwb(rgb) {
73746  var r = rgb[0],
73747      g = rgb[1],
73748      b = rgb[2],
73749      h = rgb2hsl(rgb)[0],
73750      w = 1/255 * Math.min(r, Math.min(g, b)),
73751      b = 1 - 1/255 * Math.max(r, Math.max(g, b));
73752
73753  return [h, w * 100, b * 100];
73754}
73755
73756function rgb2cmyk(rgb) {
73757  var r = rgb[0] / 255,
73758      g = rgb[1] / 255,
73759      b = rgb[2] / 255,
73760      c, m, y, k;
73761
73762  k = Math.min(1 - r, 1 - g, 1 - b);
73763  c = (1 - r - k) / (1 - k) || 0;
73764  m = (1 - g - k) / (1 - k) || 0;
73765  y = (1 - b - k) / (1 - k) || 0;
73766  return [c * 100, m * 100, y * 100, k * 100];
73767}
73768
73769function rgb2keyword(rgb) {
73770  return reverseKeywords[JSON.stringify(rgb)];
73771}
73772
73773function rgb2xyz(rgb) {
73774  var r = rgb[0] / 255,
73775      g = rgb[1] / 255,
73776      b = rgb[2] / 255;
73777
73778  // assume sRGB
73779  r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92);
73780  g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92);
73781  b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92);
73782
73783  var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);
73784  var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);
73785  var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);
73786
73787  return [x * 100, y *100, z * 100];
73788}
73789
73790function rgb2lab(rgb) {
73791  var xyz = rgb2xyz(rgb),
73792        x = xyz[0],
73793        y = xyz[1],
73794        z = xyz[2],
73795        l, a, b;
73796
73797  x /= 95.047;
73798  y /= 100;
73799  z /= 108.883;
73800
73801  x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116);
73802  y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116);
73803  z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116);
73804
73805  l = (116 * y) - 16;
73806  a = 500 * (x - y);
73807  b = 200 * (y - z);
73808
73809  return [l, a, b];
73810}
73811
73812function rgb2lch(args) {
73813  return lab2lch(rgb2lab(args));
73814}
73815
73816function hsl2rgb(hsl) {
73817  var h = hsl[0] / 360,
73818      s = hsl[1] / 100,
73819      l = hsl[2] / 100,
73820      t1, t2, t3, rgb, val;
73821
73822  if (s == 0) {
73823    val = l * 255;
73824    return [val, val, val];
73825  }
73826
73827  if (l < 0.5)
73828    t2 = l * (1 + s);
73829  else
73830    t2 = l + s - l * s;
73831  t1 = 2 * l - t2;
73832
73833  rgb = [0, 0, 0];
73834  for (var i = 0; i < 3; i++) {
73835    t3 = h + 1 / 3 * - (i - 1);
73836    t3 < 0 && t3++;
73837    t3 > 1 && t3--;
73838
73839    if (6 * t3 < 1)
73840      val = t1 + (t2 - t1) * 6 * t3;
73841    else if (2 * t3 < 1)
73842      val = t2;
73843    else if (3 * t3 < 2)
73844      val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
73845    else
73846      val = t1;
73847
73848    rgb[i] = val * 255;
73849  }
73850
73851  return rgb;
73852}
73853
73854function hsl2hsv(hsl) {
73855  var h = hsl[0],
73856      s = hsl[1] / 100,
73857      l = hsl[2] / 100,
73858      sv, v;
73859
73860  if(l === 0) {
73861      // no need to do calc on black
73862      // also avoids divide by 0 error
73863      return [0, 0, 0];
73864  }
73865
73866  l *= 2;
73867  s *= (l <= 1) ? l : 2 - l;
73868  v = (l + s) / 2;
73869  sv = (2 * s) / (l + s);
73870  return [h, sv * 100, v * 100];
73871}
73872
73873function hsl2hwb(args) {
73874  return rgb2hwb(hsl2rgb(args));
73875}
73876
73877function hsl2cmyk(args) {
73878  return rgb2cmyk(hsl2rgb(args));
73879}
73880
73881function hsl2keyword(args) {
73882  return rgb2keyword(hsl2rgb(args));
73883}
73884
73885
73886function hsv2rgb(hsv) {
73887  var h = hsv[0] / 60,
73888      s = hsv[1] / 100,
73889      v = hsv[2] / 100,
73890      hi = Math.floor(h) % 6;
73891
73892  var f = h - Math.floor(h),
73893      p = 255 * v * (1 - s),
73894      q = 255 * v * (1 - (s * f)),
73895      t = 255 * v * (1 - (s * (1 - f))),
73896      v = 255 * v;
73897
73898  switch(hi) {
73899    case 0:
73900      return [v, t, p];
73901    case 1:
73902      return [q, v, p];
73903    case 2:
73904      return [p, v, t];
73905    case 3:
73906      return [p, q, v];
73907    case 4:
73908      return [t, p, v];
73909    case 5:
73910      return [v, p, q];
73911  }
73912}
73913
73914function hsv2hsl(hsv) {
73915  var h = hsv[0],
73916      s = hsv[1] / 100,
73917      v = hsv[2] / 100,
73918      sl, l;
73919
73920  l = (2 - s) * v;
73921  sl = s * v;
73922  sl /= (l <= 1) ? l : 2 - l;
73923  sl = sl || 0;
73924  l /= 2;
73925  return [h, sl * 100, l * 100];
73926}
73927
73928function hsv2hwb(args) {
73929  return rgb2hwb(hsv2rgb(args))
73930}
73931
73932function hsv2cmyk(args) {
73933  return rgb2cmyk(hsv2rgb(args));
73934}
73935
73936function hsv2keyword(args) {
73937  return rgb2keyword(hsv2rgb(args));
73938}
73939
73940// http://dev.w3.org/csswg/css-color/#hwb-to-rgb
73941function hwb2rgb(hwb) {
73942  var h = hwb[0] / 360,
73943      wh = hwb[1] / 100,
73944      bl = hwb[2] / 100,
73945      ratio = wh + bl,
73946      i, v, f, n;
73947
73948  // wh + bl cant be > 1
73949  if (ratio > 1) {
73950    wh /= ratio;
73951    bl /= ratio;
73952  }
73953
73954  i = Math.floor(6 * h);
73955  v = 1 - bl;
73956  f = 6 * h - i;
73957  if ((i & 0x01) != 0) {
73958    f = 1 - f;
73959  }
73960  n = wh + f * (v - wh);  // linear interpolation
73961
73962  switch (i) {
73963    default:
73964    case 6:
73965    case 0: r = v; g = n; b = wh; break;
73966    case 1: r = n; g = v; b = wh; break;
73967    case 2: r = wh; g = v; b = n; break;
73968    case 3: r = wh; g = n; b = v; break;
73969    case 4: r = n; g = wh; b = v; break;
73970    case 5: r = v; g = wh; b = n; break;
73971  }
73972
73973  return [r * 255, g * 255, b * 255];
73974}
73975
73976function hwb2hsl(args) {
73977  return rgb2hsl(hwb2rgb(args));
73978}
73979
73980function hwb2hsv(args) {
73981  return rgb2hsv(hwb2rgb(args));
73982}
73983
73984function hwb2cmyk(args) {
73985  return rgb2cmyk(hwb2rgb(args));
73986}
73987
73988function hwb2keyword(args) {
73989  return rgb2keyword(hwb2rgb(args));
73990}
73991
73992function cmyk2rgb(cmyk) {
73993  var c = cmyk[0] / 100,
73994      m = cmyk[1] / 100,
73995      y = cmyk[2] / 100,
73996      k = cmyk[3] / 100,
73997      r, g, b;
73998
73999  r = 1 - Math.min(1, c * (1 - k) + k);
74000  g = 1 - Math.min(1, m * (1 - k) + k);
74001  b = 1 - Math.min(1, y * (1 - k) + k);
74002  return [r * 255, g * 255, b * 255];
74003}
74004
74005function cmyk2hsl(args) {
74006  return rgb2hsl(cmyk2rgb(args));
74007}
74008
74009function cmyk2hsv(args) {
74010  return rgb2hsv(cmyk2rgb(args));
74011}
74012
74013function cmyk2hwb(args) {
74014  return rgb2hwb(cmyk2rgb(args));
74015}
74016
74017function cmyk2keyword(args) {
74018  return rgb2keyword(cmyk2rgb(args));
74019}
74020
74021
74022function xyz2rgb(xyz) {
74023  var x = xyz[0] / 100,
74024      y = xyz[1] / 100,
74025      z = xyz[2] / 100,
74026      r, g, b;
74027
74028  r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);
74029  g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);
74030  b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);
74031
74032  // assume sRGB
74033  r = r > 0.0031308 ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055)
74034    : r = (r * 12.92);
74035
74036  g = g > 0.0031308 ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055)
74037    : g = (g * 12.92);
74038
74039  b = b > 0.0031308 ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055)
74040    : b = (b * 12.92);
74041
74042  r = Math.min(Math.max(0, r), 1);
74043  g = Math.min(Math.max(0, g), 1);
74044  b = Math.min(Math.max(0, b), 1);
74045
74046  return [r * 255, g * 255, b * 255];
74047}
74048
74049function xyz2lab(xyz) {
74050  var x = xyz[0],
74051      y = xyz[1],
74052      z = xyz[2],
74053      l, a, b;
74054
74055  x /= 95.047;
74056  y /= 100;
74057  z /= 108.883;
74058
74059  x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116);
74060  y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116);
74061  z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116);
74062
74063  l = (116 * y) - 16;
74064  a = 500 * (x - y);
74065  b = 200 * (y - z);
74066
74067  return [l, a, b];
74068}
74069
74070function xyz2lch(args) {
74071  return lab2lch(xyz2lab(args));
74072}
74073
74074function lab2xyz(lab) {
74075  var l = lab[0],
74076      a = lab[1],
74077      b = lab[2],
74078      x, y, z, y2;
74079
74080  if (l <= 8) {
74081    y = (l * 100) / 903.3;
74082    y2 = (7.787 * (y / 100)) + (16 / 116);
74083  } else {
74084    y = 100 * Math.pow((l + 16) / 116, 3);
74085    y2 = Math.pow(y / 100, 1/3);
74086  }
74087
74088  x = x / 95.047 <= 0.008856 ? x = (95.047 * ((a / 500) + y2 - (16 / 116))) / 7.787 : 95.047 * Math.pow((a / 500) + y2, 3);
74089
74090  z = z / 108.883 <= 0.008859 ? z = (108.883 * (y2 - (b / 200) - (16 / 116))) / 7.787 : 108.883 * Math.pow(y2 - (b / 200), 3);
74091
74092  return [x, y, z];
74093}
74094
74095function lab2lch(lab) {
74096  var l = lab[0],
74097      a = lab[1],
74098      b = lab[2],
74099      hr, h, c;
74100
74101  hr = Math.atan2(b, a);
74102  h = hr * 360 / 2 / Math.PI;
74103  if (h < 0) {
74104    h += 360;
74105  }
74106  c = Math.sqrt(a * a + b * b);
74107  return [l, c, h];
74108}
74109
74110function lab2rgb(args) {
74111  return xyz2rgb(lab2xyz(args));
74112}
74113
74114function lch2lab(lch) {
74115  var l = lch[0],
74116      c = lch[1],
74117      h = lch[2],
74118      a, b, hr;
74119
74120  hr = h / 360 * 2 * Math.PI;
74121  a = c * Math.cos(hr);
74122  b = c * Math.sin(hr);
74123  return [l, a, b];
74124}
74125
74126function lch2xyz(args) {
74127  return lab2xyz(lch2lab(args));
74128}
74129
74130function lch2rgb(args) {
74131  return lab2rgb(lch2lab(args));
74132}
74133
74134function keyword2rgb(keyword) {
74135  return cssKeywords[keyword];
74136}
74137
74138function keyword2hsl(args) {
74139  return rgb2hsl(keyword2rgb(args));
74140}
74141
74142function keyword2hsv(args) {
74143  return rgb2hsv(keyword2rgb(args));
74144}
74145
74146function keyword2hwb(args) {
74147  return rgb2hwb(keyword2rgb(args));
74148}
74149
74150function keyword2cmyk(args) {
74151  return rgb2cmyk(keyword2rgb(args));
74152}
74153
74154function keyword2lab(args) {
74155  return rgb2lab(keyword2rgb(args));
74156}
74157
74158function keyword2xyz(args) {
74159  return rgb2xyz(keyword2rgb(args));
74160}
74161
74162var cssKeywords = {
74163  aliceblue:  [240,248,255],
74164  antiquewhite: [250,235,215],
74165  aqua: [0,255,255],
74166  aquamarine: [127,255,212],
74167  azure:  [240,255,255],
74168  beige:  [245,245,220],
74169  bisque: [255,228,196],
74170  black:  [0,0,0],
74171  blanchedalmond: [255,235,205],
74172  blue: [0,0,255],
74173  blueviolet: [138,43,226],
74174  brown:  [165,42,42],
74175  burlywood:  [222,184,135],
74176  cadetblue:  [95,158,160],
74177  chartreuse: [127,255,0],
74178  chocolate:  [210,105,30],
74179  coral:  [255,127,80],
74180  cornflowerblue: [100,149,237],
74181  cornsilk: [255,248,220],
74182  crimson:  [220,20,60],
74183  cyan: [0,255,255],
74184  darkblue: [0,0,139],
74185  darkcyan: [0,139,139],
74186  darkgoldenrod:  [184,134,11],
74187  darkgray: [169,169,169],
74188  darkgreen:  [0,100,0],
74189  darkgrey: [169,169,169],
74190  darkkhaki:  [189,183,107],
74191  darkmagenta:  [139,0,139],
74192  darkolivegreen: [85,107,47],
74193  darkorange: [255,140,0],
74194  darkorchid: [153,50,204],
74195  darkred:  [139,0,0],
74196  darksalmon: [233,150,122],
74197  darkseagreen: [143,188,143],
74198  darkslateblue:  [72,61,139],
74199  darkslategray:  [47,79,79],
74200  darkslategrey:  [47,79,79],
74201  darkturquoise:  [0,206,209],
74202  darkviolet: [148,0,211],
74203  deeppink: [255,20,147],
74204  deepskyblue:  [0,191,255],
74205  dimgray:  [105,105,105],
74206  dimgrey:  [105,105,105],
74207  dodgerblue: [30,144,255],
74208  firebrick:  [178,34,34],
74209  floralwhite:  [255,250,240],
74210  forestgreen:  [34,139,34],
74211  fuchsia:  [255,0,255],
74212  gainsboro:  [220,220,220],
74213  ghostwhite: [248,248,255],
74214  gold: [255,215,0],
74215  goldenrod:  [218,165,32],
74216  gray: [128,128,128],
74217  green:  [0,128,0],
74218  greenyellow:  [173,255,47],
74219  grey: [128,128,128],
74220  honeydew: [240,255,240],
74221  hotpink:  [255,105,180],
74222  indianred:  [205,92,92],
74223  indigo: [75,0,130],
74224  ivory:  [255,255,240],
74225  khaki:  [240,230,140],
74226  lavender: [230,230,250],
74227  lavenderblush:  [255,240,245],
74228  lawngreen:  [124,252,0],
74229  lemonchiffon: [255,250,205],
74230  lightblue:  [173,216,230],
74231  lightcoral: [240,128,128],
74232  lightcyan:  [224,255,255],
74233  lightgoldenrodyellow: [250,250,210],
74234  lightgray:  [211,211,211],
74235  lightgreen: [144,238,144],
74236  lightgrey:  [211,211,211],
74237  lightpink:  [255,182,193],
74238  lightsalmon:  [255,160,122],
74239  lightseagreen:  [32,178,170],
74240  lightskyblue: [135,206,250],
74241  lightslategray: [119,136,153],
74242  lightslategrey: [119,136,153],
74243  lightsteelblue: [176,196,222],
74244  lightyellow:  [255,255,224],
74245  lime: [0,255,0],
74246  limegreen:  [50,205,50],
74247  linen:  [250,240,230],
74248  magenta:  [255,0,255],
74249  maroon: [128,0,0],
74250  mediumaquamarine: [102,205,170],
74251  mediumblue: [0,0,205],
74252  mediumorchid: [186,85,211],
74253  mediumpurple: [147,112,219],
74254  mediumseagreen: [60,179,113],
74255  mediumslateblue:  [123,104,238],
74256  mediumspringgreen:  [0,250,154],
74257  mediumturquoise:  [72,209,204],
74258  mediumvioletred:  [199,21,133],
74259  midnightblue: [25,25,112],
74260  mintcream:  [245,255,250],
74261  mistyrose:  [255,228,225],
74262  moccasin: [255,228,181],
74263  navajowhite:  [255,222,173],
74264  navy: [0,0,128],
74265  oldlace:  [253,245,230],
74266  olive:  [128,128,0],
74267  olivedrab:  [107,142,35],
74268  orange: [255,165,0],
74269  orangered:  [255,69,0],
74270  orchid: [218,112,214],
74271  palegoldenrod:  [238,232,170],
74272  palegreen:  [152,251,152],
74273  paleturquoise:  [175,238,238],
74274  palevioletred:  [219,112,147],
74275  papayawhip: [255,239,213],
74276  peachpuff:  [255,218,185],
74277  peru: [205,133,63],
74278  pink: [255,192,203],
74279  plum: [221,160,221],
74280  powderblue: [176,224,230],
74281  purple: [128,0,128],
74282  rebeccapurple: [102, 51, 153],
74283  red:  [255,0,0],
74284  rosybrown:  [188,143,143],
74285  royalblue:  [65,105,225],
74286  saddlebrown:  [139,69,19],
74287  salmon: [250,128,114],
74288  sandybrown: [244,164,96],
74289  seagreen: [46,139,87],
74290  seashell: [255,245,238],
74291  sienna: [160,82,45],
74292  silver: [192,192,192],
74293  skyblue:  [135,206,235],
74294  slateblue:  [106,90,205],
74295  slategray:  [112,128,144],
74296  slategrey:  [112,128,144],
74297  snow: [255,250,250],
74298  springgreen:  [0,255,127],
74299  steelblue:  [70,130,180],
74300  tan:  [210,180,140],
74301  teal: [0,128,128],
74302  thistle:  [216,191,216],
74303  tomato: [255,99,71],
74304  turquoise:  [64,224,208],
74305  violet: [238,130,238],
74306  wheat:  [245,222,179],
74307  white:  [255,255,255],
74308  whitesmoke: [245,245,245],
74309  yellow: [255,255,0],
74310  yellowgreen:  [154,205,50]
74311};
74312
74313var reverseKeywords = {};
74314for (var key in cssKeywords) {
74315  reverseKeywords[JSON.stringify(cssKeywords[key])] = key;
74316}
74317
74318},{}],4:[function(require,module,exports){
74319var conversions = require(3);
74320
74321var convert = function() {
74322   return new Converter();
74323}
74324
74325for (var func in conversions) {
74326  // export Raw versions
74327  convert[func + "Raw"] =  (function(func) {
74328    // accept array or plain args
74329    return function(arg) {
74330      if (typeof arg == "number")
74331        arg = Array.prototype.slice.call(arguments);
74332      return conversions[func](arg);
74333    }
74334  })(func);
74335
74336  var pair = /(\w+)2(\w+)/.exec(func),
74337      from = pair[1],
74338      to = pair[2];
74339
74340  // export rgb2hsl and ["rgb"]["hsl"]
74341  convert[from] = convert[from] || {};
74342
74343  convert[from][to] = convert[func] = (function(func) { 
74344    return function(arg) {
74345      if (typeof arg == "number")
74346        arg = Array.prototype.slice.call(arguments);
74347      
74348      var val = conversions[func](arg);
74349      if (typeof val == "string" || val === undefined)
74350        return val; // keyword
74351
74352      for (var i = 0; i < val.length; i++)
74353        val[i] = Math.round(val[i]);
74354      return val;
74355    }
74356  })(func);
74357}
74358
74359
74360/* Converter does lazy conversion and caching */
74361var Converter = function() {
74362   this.convs = {};
74363};
74364
74365/* Either get the values for a space or
74366  set the values for a space, depending on args */
74367Converter.prototype.routeSpace = function(space, args) {
74368   var values = args[0];
74369   if (values === undefined) {
74370      // color.rgb()
74371      return this.getValues(space);
74372   }
74373   // color.rgb(10, 10, 10)
74374   if (typeof values == "number") {
74375      values = Array.prototype.slice.call(args);        
74376   }
74377
74378   return this.setValues(space, values);
74379};
74380  
74381/* Set the values for a space, invalidating cache */
74382Converter.prototype.setValues = function(space, values) {
74383   this.space = space;
74384   this.convs = {};
74385   this.convs[space] = values;
74386   return this;
74387};
74388
74389/* Get the values for a space. If there's already
74390  a conversion for the space, fetch it, otherwise
74391  compute it */
74392Converter.prototype.getValues = function(space) {
74393   var vals = this.convs[space];
74394   if (!vals) {
74395      var fspace = this.space,
74396          from = this.convs[fspace];
74397      vals = convert[fspace][space](from);
74398
74399      this.convs[space] = vals;
74400   }
74401  return vals;
74402};
74403
74404["rgb", "hsl", "hsv", "cmyk", "keyword"].forEach(function(space) {
74405   Converter.prototype[space] = function(vals) {
74406      return this.routeSpace(space, arguments);
74407   }
74408});
74409
74410module.exports = convert;
74411},{"3":3}],5:[function(require,module,exports){
74412'use strict'
74413
74414module.exports = {
74415	"aliceblue": [240, 248, 255],
74416	"antiquewhite": [250, 235, 215],
74417	"aqua": [0, 255, 255],
74418	"aquamarine": [127, 255, 212],
74419	"azure": [240, 255, 255],
74420	"beige": [245, 245, 220],
74421	"bisque": [255, 228, 196],
74422	"black": [0, 0, 0],
74423	"blanchedalmond": [255, 235, 205],
74424	"blue": [0, 0, 255],
74425	"blueviolet": [138, 43, 226],
74426	"brown": [165, 42, 42],
74427	"burlywood": [222, 184, 135],
74428	"cadetblue": [95, 158, 160],
74429	"chartreuse": [127, 255, 0],
74430	"chocolate": [210, 105, 30],
74431	"coral": [255, 127, 80],
74432	"cornflowerblue": [100, 149, 237],
74433	"cornsilk": [255, 248, 220],
74434	"crimson": [220, 20, 60],
74435	"cyan": [0, 255, 255],
74436	"darkblue": [0, 0, 139],
74437	"darkcyan": [0, 139, 139],
74438	"darkgoldenrod": [184, 134, 11],
74439	"darkgray": [169, 169, 169],
74440	"darkgreen": [0, 100, 0],
74441	"darkgrey": [169, 169, 169],
74442	"darkkhaki": [189, 183, 107],
74443	"darkmagenta": [139, 0, 139],
74444	"darkolivegreen": [85, 107, 47],
74445	"darkorange": [255, 140, 0],
74446	"darkorchid": [153, 50, 204],
74447	"darkred": [139, 0, 0],
74448	"darksalmon": [233, 150, 122],
74449	"darkseagreen": [143, 188, 143],
74450	"darkslateblue": [72, 61, 139],
74451	"darkslategray": [47, 79, 79],
74452	"darkslategrey": [47, 79, 79],
74453	"darkturquoise": [0, 206, 209],
74454	"darkviolet": [148, 0, 211],
74455	"deeppink": [255, 20, 147],
74456	"deepskyblue": [0, 191, 255],
74457	"dimgray": [105, 105, 105],
74458	"dimgrey": [105, 105, 105],
74459	"dodgerblue": [30, 144, 255],
74460	"firebrick": [178, 34, 34],
74461	"floralwhite": [255, 250, 240],
74462	"forestgreen": [34, 139, 34],
74463	"fuchsia": [255, 0, 255],
74464	"gainsboro": [220, 220, 220],
74465	"ghostwhite": [248, 248, 255],
74466	"gold": [255, 215, 0],
74467	"goldenrod": [218, 165, 32],
74468	"gray": [128, 128, 128],
74469	"green": [0, 128, 0],
74470	"greenyellow": [173, 255, 47],
74471	"grey": [128, 128, 128],
74472	"honeydew": [240, 255, 240],
74473	"hotpink": [255, 105, 180],
74474	"indianred": [205, 92, 92],
74475	"indigo": [75, 0, 130],
74476	"ivory": [255, 255, 240],
74477	"khaki": [240, 230, 140],
74478	"lavender": [230, 230, 250],
74479	"lavenderblush": [255, 240, 245],
74480	"lawngreen": [124, 252, 0],
74481	"lemonchiffon": [255, 250, 205],
74482	"lightblue": [173, 216, 230],
74483	"lightcoral": [240, 128, 128],
74484	"lightcyan": [224, 255, 255],
74485	"lightgoldenrodyellow": [250, 250, 210],
74486	"lightgray": [211, 211, 211],
74487	"lightgreen": [144, 238, 144],
74488	"lightgrey": [211, 211, 211],
74489	"lightpink": [255, 182, 193],
74490	"lightsalmon": [255, 160, 122],
74491	"lightseagreen": [32, 178, 170],
74492	"lightskyblue": [135, 206, 250],
74493	"lightslategray": [119, 136, 153],
74494	"lightslategrey": [119, 136, 153],
74495	"lightsteelblue": [176, 196, 222],
74496	"lightyellow": [255, 255, 224],
74497	"lime": [0, 255, 0],
74498	"limegreen": [50, 205, 50],
74499	"linen": [250, 240, 230],
74500	"magenta": [255, 0, 255],
74501	"maroon": [128, 0, 0],
74502	"mediumaquamarine": [102, 205, 170],
74503	"mediumblue": [0, 0, 205],
74504	"mediumorchid": [186, 85, 211],
74505	"mediumpurple": [147, 112, 219],
74506	"mediumseagreen": [60, 179, 113],
74507	"mediumslateblue": [123, 104, 238],
74508	"mediumspringgreen": [0, 250, 154],
74509	"mediumturquoise": [72, 209, 204],
74510	"mediumvioletred": [199, 21, 133],
74511	"midnightblue": [25, 25, 112],
74512	"mintcream": [245, 255, 250],
74513	"mistyrose": [255, 228, 225],
74514	"moccasin": [255, 228, 181],
74515	"navajowhite": [255, 222, 173],
74516	"navy": [0, 0, 128],
74517	"oldlace": [253, 245, 230],
74518	"olive": [128, 128, 0],
74519	"olivedrab": [107, 142, 35],
74520	"orange": [255, 165, 0],
74521	"orangered": [255, 69, 0],
74522	"orchid": [218, 112, 214],
74523	"palegoldenrod": [238, 232, 170],
74524	"palegreen": [152, 251, 152],
74525	"paleturquoise": [175, 238, 238],
74526	"palevioletred": [219, 112, 147],
74527	"papayawhip": [255, 239, 213],
74528	"peachpuff": [255, 218, 185],
74529	"peru": [205, 133, 63],
74530	"pink": [255, 192, 203],
74531	"plum": [221, 160, 221],
74532	"powderblue": [176, 224, 230],
74533	"purple": [128, 0, 128],
74534	"rebeccapurple": [102, 51, 153],
74535	"red": [255, 0, 0],
74536	"rosybrown": [188, 143, 143],
74537	"royalblue": [65, 105, 225],
74538	"saddlebrown": [139, 69, 19],
74539	"salmon": [250, 128, 114],
74540	"sandybrown": [244, 164, 96],
74541	"seagreen": [46, 139, 87],
74542	"seashell": [255, 245, 238],
74543	"sienna": [160, 82, 45],
74544	"silver": [192, 192, 192],
74545	"skyblue": [135, 206, 235],
74546	"slateblue": [106, 90, 205],
74547	"slategray": [112, 128, 144],
74548	"slategrey": [112, 128, 144],
74549	"snow": [255, 250, 250],
74550	"springgreen": [0, 255, 127],
74551	"steelblue": [70, 130, 180],
74552	"tan": [210, 180, 140],
74553	"teal": [0, 128, 128],
74554	"thistle": [216, 191, 216],
74555	"tomato": [255, 99, 71],
74556	"turquoise": [64, 224, 208],
74557	"violet": [238, 130, 238],
74558	"wheat": [245, 222, 179],
74559	"white": [255, 255, 255],
74560	"whitesmoke": [245, 245, 245],
74561	"yellow": [255, 255, 0],
74562	"yellowgreen": [154, 205, 50]
74563};
74564
74565},{}],6:[function(require,module,exports){
74566//! moment.js
74567
74568;(function (global, factory) {
74569    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
74570    typeof define === 'function' && define.amd ? define(factory) :
74571    global.moment = factory()
74572}(this, (function () { 'use strict';
74573
74574    var hookCallback;
74575
74576    function hooks () {
74577        return hookCallback.apply(null, arguments);
74578    }
74579
74580    // This is done to register the method called with moment()
74581    // without creating circular dependencies.
74582    function setHookCallback (callback) {
74583        hookCallback = callback;
74584    }
74585
74586    function isArray(input) {
74587        return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
74588    }
74589
74590    function isObject(input) {
74591        // IE8 will treat undefined and null as object if it wasn't for
74592        // input != null
74593        return input != null && Object.prototype.toString.call(input) === '[object Object]';
74594    }
74595
74596    function isObjectEmpty(obj) {
74597        if (Object.getOwnPropertyNames) {
74598            return (Object.getOwnPropertyNames(obj).length === 0);
74599        } else {
74600            var k;
74601            for (k in obj) {
74602                if (obj.hasOwnProperty(k)) {
74603                    return false;
vendor: 137,222 bytes, lines 74604-78842
74604                }
74605            }
74606            return true;
74607        }
74608    }
74609
74610    function isUndefined(input) {
74611        return input === void 0;
74612    }
74613
74614    function isNumber(input) {
74615        return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
74616    }
74617
74618    function isDate(input) {
74619        return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
74620    }
74621
74622    function map(arr, fn) {
74623        var res = [], i;
74624        for (i = 0; i < arr.length; ++i) {
74625            res.push(fn(arr[i], i));
74626        }
74627        return res;
74628    }
74629
74630    function hasOwnProp(a, b) {
74631        return Object.prototype.hasOwnProperty.call(a, b);
74632    }
74633
74634    function extend(a, b) {
74635        for (var i in b) {
74636            if (hasOwnProp(b, i)) {
74637                a[i] = b[i];
74638            }
74639        }
74640
74641        if (hasOwnProp(b, 'toString')) {
74642            a.toString = b.toString;
74643        }
74644
74645        if (hasOwnProp(b, 'valueOf')) {
74646            a.valueOf = b.valueOf;
74647        }
74648
74649        return a;
74650    }
74651
74652    function createUTC (input, format, locale, strict) {
74653        return createLocalOrUTC(input, format, locale, strict, true).utc();
74654    }
74655
74656    function defaultParsingFlags() {
74657        // We need to deep clone this object.
74658        return {
74659            empty           : false,
74660            unusedTokens    : [],
74661            unusedInput     : [],
74662            overflow        : -2,
74663            charsLeftOver   : 0,
74664            nullInput       : false,
74665            invalidMonth    : null,
74666            invalidFormat   : false,
74667            userInvalidated : false,
74668            iso             : false,
74669            parsedDateParts : [],
74670            meridiem        : null,
74671            rfc2822         : false,
74672            weekdayMismatch : false
74673        };
74674    }
74675
74676    function getParsingFlags(m) {
74677        if (m._pf == null) {
74678            m._pf = defaultParsingFlags();
74679        }
74680        return m._pf;
74681    }
74682
74683    var some;
74684    if (Array.prototype.some) {
74685        some = Array.prototype.some;
74686    } else {
74687        some = function (fun) {
74688            var t = Object(this);
74689            var len = t.length >>> 0;
74690
74691            for (var i = 0; i < len; i++) {
74692                if (i in t && fun.call(this, t[i], i, t)) {
74693                    return true;
74694                }
74695            }
74696
74697            return false;
74698        };
74699    }
74700
74701    function isValid(m) {
74702        if (m._isValid == null) {
74703            var flags = getParsingFlags(m);
74704            var parsedParts = some.call(flags.parsedDateParts, function (i) {
74705                return i != null;
74706            });
74707            var isNowValid = !isNaN(m._d.getTime()) &&
74708                flags.overflow < 0 &&
74709                !flags.empty &&
74710                !flags.invalidMonth &&
74711                !flags.invalidWeekday &&
74712                !flags.weekdayMismatch &&
74713                !flags.nullInput &&
74714                !flags.invalidFormat &&
74715                !flags.userInvalidated &&
74716                (!flags.meridiem || (flags.meridiem && parsedParts));
74717
74718            if (m._strict) {
74719                isNowValid = isNowValid &&
74720                    flags.charsLeftOver === 0 &&
74721                    flags.unusedTokens.length === 0 &&
74722                    flags.bigHour === undefined;
74723            }
74724
74725            if (Object.isFrozen == null || !Object.isFrozen(m)) {
74726                m._isValid = isNowValid;
74727            }
74728            else {
74729                return isNowValid;
74730            }
74731        }
74732        return m._isValid;
74733    }
74734
74735    function createInvalid (flags) {
74736        var m = createUTC(NaN);
74737        if (flags != null) {
74738            extend(getParsingFlags(m), flags);
74739        }
74740        else {
74741            getParsingFlags(m).userInvalidated = true;
74742        }
74743
74744        return m;
74745    }
74746
74747    // Plugins that add properties should also add the key here (null value),
74748    // so we can properly clone ourselves.
74749    var momentProperties = hooks.momentProperties = [];
74750
74751    function copyConfig(to, from) {
74752        var i, prop, val;
74753
74754        if (!isUndefined(from._isAMomentObject)) {
74755            to._isAMomentObject = from._isAMomentObject;
74756        }
74757        if (!isUndefined(from._i)) {
74758            to._i = from._i;
74759        }
74760        if (!isUndefined(from._f)) {
74761            to._f = from._f;
74762        }
74763        if (!isUndefined(from._l)) {
74764            to._l = from._l;
74765        }
74766        if (!isUndefined(from._strict)) {
74767            to._strict = from._strict;
74768        }
74769        if (!isUndefined(from._tzm)) {
74770            to._tzm = from._tzm;
74771        }
74772        if (!isUndefined(from._isUTC)) {
74773            to._isUTC = from._isUTC;
74774        }
74775        if (!isUndefined(from._offset)) {
74776            to._offset = from._offset;
74777        }
74778        if (!isUndefined(from._pf)) {
74779            to._pf = getParsingFlags(from);
74780        }
74781        if (!isUndefined(from._locale)) {
74782            to._locale = from._locale;
74783        }
74784
74785        if (momentProperties.length > 0) {
74786            for (i = 0; i < momentProperties.length; i++) {
74787                prop = momentProperties[i];
74788                val = from[prop];
74789                if (!isUndefined(val)) {
74790                    to[prop] = val;
74791                }
74792            }
74793        }
74794
74795        return to;
74796    }
74797
74798    var updateInProgress = false;
74799
74800    // Moment prototype object
74801    function Moment(config) {
74802        copyConfig(this, config);
74803        this._d = new Date(config._d != null ? config._d.getTime() : NaN);
74804        if (!this.isValid()) {
74805            this._d = new Date(NaN);
74806        }
74807        // Prevent infinite loop in case updateOffset creates new moment
74808        // objects.
74809        if (updateInProgress === false) {
74810            updateInProgress = true;
74811            hooks.updateOffset(this);
74812            updateInProgress = false;
74813        }
74814    }
74815
74816    function isMoment (obj) {
74817        return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
74818    }
74819
74820    function absFloor (number) {
74821        if (number < 0) {
74822            // -0 -> 0
74823            return Math.ceil(number) || 0;
74824        } else {
74825            return Math.floor(number);
74826        }
74827    }
74828
74829    function toInt(argumentForCoercion) {
74830        var coercedNumber = +argumentForCoercion,
74831            value = 0;
74832
74833        if (coercedNumber !== 0 && isFinite(coercedNumber)) {
74834            value = absFloor(coercedNumber);
74835        }
74836
74837        return value;
74838    }
74839
74840    // compare two arrays, return the number of differences
74841    function compareArrays(array1, array2, dontConvert) {
74842        var len = Math.min(array1.length, array2.length),
74843            lengthDiff = Math.abs(array1.length - array2.length),
74844            diffs = 0,
74845            i;
74846        for (i = 0; i < len; i++) {
74847            if ((dontConvert && array1[i] !== array2[i]) ||
74848                (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
74849                diffs++;
74850            }
74851        }
74852        return diffs + lengthDiff;
74853    }
74854
74855    function warn(msg) {
74856        if (hooks.suppressDeprecationWarnings === false &&
74857                (typeof console !==  'undefined') && console.warn) {
74858            console.warn('Deprecation warning: ' + msg);
74859        }
74860    }
74861
74862    function deprecate(msg, fn) {
74863        var firstTime = true;
74864
74865        return extend(function () {
74866            if (hooks.deprecationHandler != null) {
74867                hooks.deprecationHandler(null, msg);
74868            }
74869            if (firstTime) {
74870                var args = [];
74871                var arg;
74872                for (var i = 0; i < arguments.length; i++) {
74873                    arg = '';
74874                    if (typeof arguments[i] === 'object') {
74875                        arg += '\n[' + i + '] ';
74876                        for (var key in arguments[0]) {
74877                            arg += key + ': ' + arguments[0][key] + ', ';
74878                        }
74879                        arg = arg.slice(0, -2); // Remove trailing comma and space
74880                    } else {
74881                        arg = arguments[i];
74882                    }
74883                    args.push(arg);
74884                }
74885                warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
74886                firstTime = false;
74887            }
74888            return fn.apply(this, arguments);
74889        }, fn);
74890    }
74891
74892    var deprecations = {};
74893
74894    function deprecateSimple(name, msg) {
74895        if (hooks.deprecationHandler != null) {
74896            hooks.deprecationHandler(name, msg);
74897        }
74898        if (!deprecations[name]) {
74899            warn(msg);
74900            deprecations[name] = true;
74901        }
74902    }
74903
74904    hooks.suppressDeprecationWarnings = false;
74905    hooks.deprecationHandler = null;
74906
74907    function isFunction(input) {
74908        return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
74909    }
74910
74911    function set (config) {
74912        var prop, i;
74913        for (i in config) {
74914            prop = config[i];
74915            if (isFunction(prop)) {
74916                this[i] = prop;
74917            } else {
74918                this['_' + i] = prop;
74919            }
74920        }
74921        this._config = config;
74922        // Lenient ordinal parsing accepts just a number in addition to
74923        // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
74924        // TODO: Remove "ordinalParse" fallback in next major release.
74925        this._dayOfMonthOrdinalParseLenient = new RegExp(
74926            (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +
74927                '|' + (/\d{1,2}/).source);
74928    }
74929
74930    function mergeConfigs(parentConfig, childConfig) {
74931        var res = extend({}, parentConfig), prop;
74932        for (prop in childConfig) {
74933            if (hasOwnProp(childConfig, prop)) {
74934                if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
74935                    res[prop] = {};
74936                    extend(res[prop], parentConfig[prop]);
74937                    extend(res[prop], childConfig[prop]);
74938                } else if (childConfig[prop] != null) {
74939                    res[prop] = childConfig[prop];
74940                } else {
74941                    delete res[prop];
74942                }
74943            }
74944        }
74945        for (prop in parentConfig) {
74946            if (hasOwnProp(parentConfig, prop) &&
74947                    !hasOwnProp(childConfig, prop) &&
74948                    isObject(parentConfig[prop])) {
74949                // make sure changes to properties don't modify parent config
74950                res[prop] = extend({}, res[prop]);
74951            }
74952        }
74953        return res;
74954    }
74955
74956    function Locale(config) {
74957        if (config != null) {
74958            this.set(config);
74959        }
74960    }
74961
74962    var keys;
74963
74964    if (Object.keys) {
74965        keys = Object.keys;
74966    } else {
74967        keys = function (obj) {
74968            var i, res = [];
74969            for (i in obj) {
74970                if (hasOwnProp(obj, i)) {
74971                    res.push(i);
74972                }
74973            }
74974            return res;
74975        };
74976    }
74977
74978    var defaultCalendar = {
74979        sameDay : '[Today at] LT',
74980        nextDay : '[Tomorrow at] LT',
74981        nextWeek : 'dddd [at] LT',
74982        lastDay : '[Yesterday at] LT',
74983        lastWeek : '[Last] dddd [at] LT',
74984        sameElse : 'L'
74985    };
74986
74987    function calendar (key, mom, now) {
74988        var output = this._calendar[key] || this._calendar['sameElse'];
74989        return isFunction(output) ? output.call(mom, now) : output;
74990    }
74991
74992    var defaultLongDateFormat = {
74993        LTS  : 'h:mm:ss A',
74994        LT   : 'h:mm A',
74995        L    : 'MM/DD/YYYY',
74996        LL   : 'MMMM D, YYYY',
74997        LLL  : 'MMMM D, YYYY h:mm A',
74998        LLLL : 'dddd, MMMM D, YYYY h:mm A'
74999    };
75000
75001    function longDateFormat (key) {
75002        var format = this._longDateFormat[key],
75003            formatUpper = this._longDateFormat[key.toUpperCase()];
75004
75005        if (format || !formatUpper) {
75006            return format;
75007        }
75008
75009        this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
75010            return val.slice(1);
75011        });
75012
75013        return this._longDateFormat[key];
75014    }
75015
75016    var defaultInvalidDate = 'Invalid date';
75017
75018    function invalidDate () {
75019        return this._invalidDate;
75020    }
75021
75022    var defaultOrdinal = '%d';
75023    var defaultDayOfMonthOrdinalParse = /\d{1,2}/;
75024
75025    function ordinal (number) {
75026        return this._ordinal.replace('%d', number);
75027    }
75028
75029    var defaultRelativeTime = {
75030        future : 'in %s',
75031        past   : '%s ago',
75032        s  : 'a few seconds',
75033        ss : '%d seconds',
75034        m  : 'a minute',
75035        mm : '%d minutes',
75036        h  : 'an hour',
75037        hh : '%d hours',
75038        d  : 'a day',
75039        dd : '%d days',
75040        M  : 'a month',
75041        MM : '%d months',
75042        y  : 'a year',
75043        yy : '%d years'
75044    };
75045
75046    function relativeTime (number, withoutSuffix, string, isFuture) {
75047        var output = this._relativeTime[string];
75048        return (isFunction(output)) ?
75049            output(number, withoutSuffix, string, isFuture) :
75050            output.replace(/%d/i, number);
75051    }
75052
75053    function pastFuture (diff, output) {
75054        var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
75055        return isFunction(format) ? format(output) : format.replace(/%s/i, output);
75056    }
75057
75058    var aliases = {};
75059
75060    function addUnitAlias (unit, shorthand) {
75061        var lowerCase = unit.toLowerCase();
75062        aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
75063    }
75064
75065    function normalizeUnits(units) {
75066        return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
75067    }
75068
75069    function normalizeObjectUnits(inputObject) {
75070        var normalizedInput = {},
75071            normalizedProp,
75072            prop;
75073
75074        for (prop in inputObject) {
75075            if (hasOwnProp(inputObject, prop)) {
75076                normalizedProp = normalizeUnits(prop);
75077                if (normalizedProp) {
75078                    normalizedInput[normalizedProp] = inputObject[prop];
75079                }
75080            }
75081        }
75082
75083        return normalizedInput;
75084    }
75085
75086    var priorities = {};
75087
75088    function addUnitPriority(unit, priority) {
75089        priorities[unit] = priority;
75090    }
75091
75092    function getPrioritizedUnits(unitsObj) {
75093        var units = [];
75094        for (var u in unitsObj) {
75095            units.push({unit: u, priority: priorities[u]});
75096        }
75097        units.sort(function (a, b) {
75098            return a.priority - b.priority;
75099        });
75100        return units;
75101    }
75102
75103    function zeroFill(number, targetLength, forceSign) {
75104        var absNumber = '' + Math.abs(number),
75105            zerosToFill = targetLength - absNumber.length,
75106            sign = number >= 0;
75107        return (sign ? (forceSign ? '+' : '') : '-') +
75108            Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
75109    }
75110
75111    var 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;
75112
75113    var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
75114
75115    var formatFunctions = {};
75116
75117    var formatTokenFunctions = {};
75118
75119    // token:    'M'
75120    // padded:   ['MM', 2]
75121    // ordinal:  'Mo'
75122    // callback: function () { this.month() + 1 }
75123    function addFormatToken (token, padded, ordinal, callback) {
75124        var func = callback;
75125        if (typeof callback === 'string') {
75126            func = function () {
75127                return this[callback]();
75128            };
75129        }
75130        if (token) {
75131            formatTokenFunctions[token] = func;
75132        }
75133        if (padded) {
75134            formatTokenFunctions[padded[0]] = function () {
75135                return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
75136            };
75137        }
75138        if (ordinal) {
75139            formatTokenFunctions[ordinal] = function () {
75140                return this.localeData().ordinal(func.apply(this, arguments), token);
75141            };
75142        }
75143    }
75144
75145    function removeFormattingTokens(input) {
75146        if (input.match(/\[[\s\S]/)) {
75147            return input.replace(/^\[|\]$/g, '');
75148        }
75149        return input.replace(/\\/g, '');
75150    }
75151
75152    function makeFormatFunction(format) {
75153        var array = format.match(formattingTokens), i, length;
75154
75155        for (i = 0, length = array.length; i < length; i++) {
75156            if (formatTokenFunctions[array[i]]) {
75157                array[i] = formatTokenFunctions[array[i]];
75158            } else {
75159                array[i] = removeFormattingTokens(array[i]);
75160            }
75161        }
75162
75163        return function (mom) {
75164            var output = '', i;
75165            for (i = 0; i < length; i++) {
75166                output += isFunction(array[i]) ? array[i].call(mom, format) : array[i];
75167            }
75168            return output;
75169        };
75170    }
75171
75172    // format date using native date object
75173    function formatMoment(m, format) {
75174        if (!m.isValid()) {
75175            return m.localeData().invalidDate();
75176        }
75177
75178        format = expandFormat(format, m.localeData());
75179        formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
75180
75181        return formatFunctions[format](m);
75182    }
75183
75184    function expandFormat(format, locale) {
75185        var i = 5;
75186
75187        function replaceLongDateFormatTokens(input) {
75188            return locale.longDateFormat(input) || input;
75189        }
75190
75191        localFormattingTokens.lastIndex = 0;
75192        while (i >= 0 && localFormattingTokens.test(format)) {
75193            format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
75194            localFormattingTokens.lastIndex = 0;
75195            i -= 1;
75196        }
75197
75198        return format;
75199    }
75200
75201    var match1         = /\d/;            //       0 - 9
75202    var match2         = /\d\d/;          //      00 - 99
75203    var match3         = /\d{3}/;         //     000 - 999
75204    var match4         = /\d{4}/;         //    0000 - 9999
75205    var match6         = /[+-]?\d{6}/;    // -999999 - 999999
75206    var match1to2      = /\d\d?/;         //       0 - 99
75207    var match3to4      = /\d\d\d\d?/;     //     999 - 9999
75208    var match5to6      = /\d\d\d\d\d\d?/; //   99999 - 999999
75209    var match1to3      = /\d{1,3}/;       //       0 - 999
75210    var match1to4      = /\d{1,4}/;       //       0 - 9999
75211    var match1to6      = /[+-]?\d{1,6}/;  // -999999 - 999999
75212
75213    var matchUnsigned  = /\d+/;           //       0 - inf
75214    var matchSigned    = /[+-]?\d+/;      //    -inf - inf
75215
75216    var matchOffset    = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
75217    var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
75218
75219    var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
75220
75221    // any word (or two) characters or numbers including two/three word month in arabic.
75222    // includes scottish gaelic two word and hyphenated months
75223    var 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;
75224
75225    var regexes = {};
75226
75227    function addRegexToken (token, regex, strictRegex) {
75228        regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
75229            return (isStrict && strictRegex) ? strictRegex : regex;
75230        };
75231    }
75232
75233    function getParseRegexForToken (token, config) {
75234        if (!hasOwnProp(regexes, token)) {
75235            return new RegExp(unescapeFormat(token));
75236        }
75237
75238        return regexes[token](config._strict, config._locale);
75239    }
75240
75241    // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
75242    function unescapeFormat(s) {
75243        return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
75244            return p1 || p2 || p3 || p4;
75245        }));
75246    }
75247
75248    function regexEscape(s) {
75249        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
75250    }
75251
75252    var tokens = {};
75253
75254    function addParseToken (token, callback) {
75255        var i, func = callback;
75256        if (typeof token === 'string') {
75257            token = [token];
75258        }
75259        if (isNumber(callback)) {
75260            func = function (input, array) {
75261                array[callback] = toInt(input);
75262            };
75263        }
75264        for (i = 0; i < token.length; i++) {
75265            tokens[token[i]] = func;
75266        }
75267    }
75268
75269    function addWeekParseToken (token, callback) {
75270        addParseToken(token, function (input, array, config, token) {
75271            config._w = config._w || {};
75272            callback(input, config._w, config, token);
75273        });
75274    }
75275
75276    function addTimeToArrayFromToken(token, input, config) {
75277        if (input != null && hasOwnProp(tokens, token)) {
75278            tokens[token](input, config._a, config, token);
75279        }
75280    }
75281
75282    var YEAR = 0;
75283    var MONTH = 1;
75284    var DATE = 2;
75285    var HOUR = 3;
75286    var MINUTE = 4;
75287    var SECOND = 5;
75288    var MILLISECOND = 6;
75289    var WEEK = 7;
75290    var WEEKDAY = 8;
75291
75292    // FORMATTING
75293
75294    addFormatToken('Y', 0, 0, function () {
75295        var y = this.year();
75296        return y <= 9999 ? '' + y : '+' + y;
75297    });
75298
75299    addFormatToken(0, ['YY', 2], 0, function () {
75300        return this.year() % 100;
75301    });
75302
75303    addFormatToken(0, ['YYYY',   4],       0, 'year');
75304    addFormatToken(0, ['YYYYY',  5],       0, 'year');
75305    addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
75306
75307    // ALIASES
75308
75309    addUnitAlias('year', 'y');
75310
75311    // PRIORITIES
75312
75313    addUnitPriority('year', 1);
75314
75315    // PARSING
75316
75317    addRegexToken('Y',      matchSigned);
75318    addRegexToken('YY',     match1to2, match2);
75319    addRegexToken('YYYY',   match1to4, match4);
75320    addRegexToken('YYYYY',  match1to6, match6);
75321    addRegexToken('YYYYYY', match1to6, match6);
75322
75323    addParseToken(['YYYYY', 'YYYYYY'], YEAR);
75324    addParseToken('YYYY', function (input, array) {
75325        array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
75326    });
75327    addParseToken('YY', function (input, array) {
75328        array[YEAR] = hooks.parseTwoDigitYear(input);
75329    });
75330    addParseToken('Y', function (input, array) {
75331        array[YEAR] = parseInt(input, 10);
75332    });
75333
75334    // HELPERS
75335
75336    function daysInYear(year) {
75337        return isLeapYear(year) ? 366 : 365;
75338    }
75339
75340    function isLeapYear(year) {
75341        return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
75342    }
75343
75344    // HOOKS
75345
75346    hooks.parseTwoDigitYear = function (input) {
75347        return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
75348    };
75349
75350    // MOMENTS
75351
75352    var getSetYear = makeGetSet('FullYear', true);
75353
75354    function getIsLeapYear () {
75355        return isLeapYear(this.year());
75356    }
75357
75358    function makeGetSet (unit, keepTime) {
75359        return function (value) {
75360            if (value != null) {
75361                set$1(this, unit, value);
75362                hooks.updateOffset(this, keepTime);
75363                return this;
75364            } else {
75365                return get(this, unit);
75366            }
75367        };
75368    }
75369
75370    function get (mom, unit) {
75371        return mom.isValid() ?
75372            mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
75373    }
75374
75375    function set$1 (mom, unit, value) {
75376        if (mom.isValid() && !isNaN(value)) {
75377            if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) {
75378                mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month()));
75379            }
75380            else {
75381                mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
75382            }
75383        }
75384    }
75385
75386    // MOMENTS
75387
75388    function stringGet (units) {
75389        units = normalizeUnits(units);
75390        if (isFunction(this[units])) {
75391            return this[units]();
75392        }
75393        return this;
75394    }
75395
75396
75397    function stringSet (units, value) {
75398        if (typeof units === 'object') {
75399            units = normalizeObjectUnits(units);
75400            var prioritized = getPrioritizedUnits(units);
75401            for (var i = 0; i < prioritized.length; i++) {
75402                this[prioritized[i].unit](units[prioritized[i].unit]);
75403            }
75404        } else {
75405            units = normalizeUnits(units);
75406            if (isFunction(this[units])) {
75407                return this[units](value);
75408            }
75409        }
75410        return this;
75411    }
75412
75413    function mod(n, x) {
75414        return ((n % x) + x) % x;
75415    }
75416
75417    var indexOf;
75418
75419    if (Array.prototype.indexOf) {
75420        indexOf = Array.prototype.indexOf;
75421    } else {
75422        indexOf = function (o) {
75423            // I know
75424            var i;
75425            for (i = 0; i < this.length; ++i) {
75426                if (this[i] === o) {
75427                    return i;
75428                }
75429            }
75430            return -1;
75431        };
75432    }
75433
75434    function daysInMonth(year, month) {
75435        if (isNaN(year) || isNaN(month)) {
75436            return NaN;
75437        }
75438        var modMonth = mod(month, 12);
75439        year += (month - modMonth) / 12;
75440        return modMonth === 1 ? (isLeapYear(year) ? 29 : 28) : (31 - modMonth % 7 % 2);
75441    }
75442
75443    // FORMATTING
75444
75445    addFormatToken('M', ['MM', 2], 'Mo', function () {
75446        return this.month() + 1;
75447    });
75448
75449    addFormatToken('MMM', 0, 0, function (format) {
75450        return this.localeData().monthsShort(this, format);
75451    });
75452
75453    addFormatToken('MMMM', 0, 0, function (format) {
75454        return this.localeData().months(this, format);
75455    });
75456
75457    // ALIASES
75458
75459    addUnitAlias('month', 'M');
75460
75461    // PRIORITY
75462
75463    addUnitPriority('month', 8);
75464
75465    // PARSING
75466
75467    addRegexToken('M',    match1to2);
75468    addRegexToken('MM',   match1to2, match2);
75469    addRegexToken('MMM',  function (isStrict, locale) {
75470        return locale.monthsShortRegex(isStrict);
75471    });
75472    addRegexToken('MMMM', function (isStrict, locale) {
75473        return locale.monthsRegex(isStrict);
75474    });
75475
75476    addParseToken(['M', 'MM'], function (input, array) {
75477        array[MONTH] = toInt(input) - 1;
75478    });
75479
75480    addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
75481        var month = config._locale.monthsParse(input, token, config._strict);
75482        // if we didn't find a month name, mark the date as invalid.
75483        if (month != null) {
75484            array[MONTH] = month;
75485        } else {
75486            getParsingFlags(config).invalidMonth = input;
75487        }
75488    });
75489
75490    // LOCALES
75491
75492    var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
75493    var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
75494    function localeMonths (m, format) {
75495        if (!m) {
75496            return isArray(this._months) ? this._months :
75497                this._months['standalone'];
75498        }
75499        return isArray(this._months) ? this._months[m.month()] :
75500            this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
75501    }
75502
75503    var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
75504    function localeMonthsShort (m, format) {
75505        if (!m) {
75506            return isArray(this._monthsShort) ? this._monthsShort :
75507                this._monthsShort['standalone'];
75508        }
75509        return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
75510            this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
75511    }
75512
75513    function handleStrictParse(monthName, format, strict) {
75514        var i, ii, mom, llc = monthName.toLocaleLowerCase();
75515        if (!this._monthsParse) {
75516            // this is not used
75517            this._monthsParse = [];
75518            this._longMonthsParse = [];
75519            this._shortMonthsParse = [];
75520            for (i = 0; i < 12; ++i) {
75521                mom = createUTC([2000, i]);
75522                this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
75523                this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
75524            }
75525        }
75526
75527        if (strict) {
75528            if (format === 'MMM') {
75529                ii = indexOf.call(this._shortMonthsParse, llc);
75530                return ii !== -1 ? ii : null;
75531            } else {
75532                ii = indexOf.call(this._longMonthsParse, llc);
75533                return ii !== -1 ? ii : null;
75534            }
75535        } else {
75536            if (format === 'MMM') {
75537                ii = indexOf.call(this._shortMonthsParse, llc);
75538                if (ii !== -1) {
75539                    return ii;
75540                }
75541                ii = indexOf.call(this._longMonthsParse, llc);
75542                return ii !== -1 ? ii : null;
75543            } else {
75544                ii = indexOf.call(this._longMonthsParse, llc);
75545                if (ii !== -1) {
75546                    return ii;
75547                }
75548                ii = indexOf.call(this._shortMonthsParse, llc);
75549                return ii !== -1 ? ii : null;
75550            }
75551        }
75552    }
75553
75554    function localeMonthsParse (monthName, format, strict) {
75555        var i, mom, regex;
75556
75557        if (this._monthsParseExact) {
75558            return handleStrictParse.call(this, monthName, format, strict);
75559        }
75560
75561        if (!this._monthsParse) {
75562            this._monthsParse = [];
75563            this._longMonthsParse = [];
75564            this._shortMonthsParse = [];
75565        }
75566
75567        // TODO: add sorting
75568        // Sorting makes sure if one month (or abbr) is a prefix of another
75569        // see sorting in computeMonthsParse
75570        for (i = 0; i < 12; i++) {
75571            // make the regex if we don't have it already
75572            mom = createUTC([2000, i]);
75573            if (strict && !this._longMonthsParse[i]) {
75574                this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
75575                this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
75576            }
75577            if (!strict && !this._monthsParse[i]) {
75578                regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
75579                this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
75580            }
75581            // test the regex
75582            if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
75583                return i;
75584            } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
75585                return i;
75586            } else if (!strict && this._monthsParse[i].test(monthName)) {
75587                return i;
75588            }
75589        }
75590    }
75591
75592    // MOMENTS
75593
75594    function setMonth (mom, value) {
75595        var dayOfMonth;
75596
75597        if (!mom.isValid()) {
75598            // No op
75599            return mom;
75600        }
75601
75602        if (typeof value === 'string') {
75603            if (/^\d+$/.test(value)) {
75604                value = toInt(value);
75605            } else {
75606                value = mom.localeData().monthsParse(value);
75607                // TODO: Another silent failure?
75608                if (!isNumber(value)) {
75609                    return mom;
75610                }
75611            }
75612        }
75613
75614        dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
75615        mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
75616        return mom;
75617    }
75618
75619    function getSetMonth (value) {
75620        if (value != null) {
75621            setMonth(this, value);
75622            hooks.updateOffset(this, true);
75623            return this;
75624        } else {
75625            return get(this, 'Month');
75626        }
75627    }
75628
75629    function getDaysInMonth () {
75630        return daysInMonth(this.year(), this.month());
75631    }
75632
75633    var defaultMonthsShortRegex = matchWord;
75634    function monthsShortRegex (isStrict) {
75635        if (this._monthsParseExact) {
75636            if (!hasOwnProp(this, '_monthsRegex')) {
75637                computeMonthsParse.call(this);
75638            }
75639            if (isStrict) {
75640                return this._monthsShortStrictRegex;
75641            } else {
75642                return this._monthsShortRegex;
75643            }
75644        } else {
75645            if (!hasOwnProp(this, '_monthsShortRegex')) {
75646                this._monthsShortRegex = defaultMonthsShortRegex;
75647            }
75648            return this._monthsShortStrictRegex && isStrict ?
75649                this._monthsShortStrictRegex : this._monthsShortRegex;
75650        }
75651    }
75652
75653    var defaultMonthsRegex = matchWord;
75654    function monthsRegex (isStrict) {
75655        if (this._monthsParseExact) {
75656            if (!hasOwnProp(this, '_monthsRegex')) {
75657                computeMonthsParse.call(this);
75658            }
75659            if (isStrict) {
75660                return this._monthsStrictRegex;
75661            } else {
75662                return this._monthsRegex;
75663            }
75664        } else {
75665            if (!hasOwnProp(this, '_monthsRegex')) {
75666                this._monthsRegex = defaultMonthsRegex;
75667            }
75668            return this._monthsStrictRegex && isStrict ?
75669                this._monthsStrictRegex : this._monthsRegex;
75670        }
75671    }
75672
75673    function computeMonthsParse () {
75674        function cmpLenRev(a, b) {
75675            return b.length - a.length;
75676        }
75677
75678        var shortPieces = [], longPieces = [], mixedPieces = [],
75679            i, mom;
75680        for (i = 0; i < 12; i++) {
75681            // make the regex if we don't have it already
75682            mom = createUTC([2000, i]);
75683            shortPieces.push(this.monthsShort(mom, ''));
75684            longPieces.push(this.months(mom, ''));
75685            mixedPieces.push(this.months(mom, ''));
75686            mixedPieces.push(this.monthsShort(mom, ''));
75687        }
75688        // Sorting makes sure if one month (or abbr) is a prefix of another it
75689        // will match the longer piece.
75690        shortPieces.sort(cmpLenRev);
75691        longPieces.sort(cmpLenRev);
75692        mixedPieces.sort(cmpLenRev);
75693        for (i = 0; i < 12; i++) {
75694            shortPieces[i] = regexEscape(shortPieces[i]);
75695            longPieces[i] = regexEscape(longPieces[i]);
75696        }
75697        for (i = 0; i < 24; i++) {
75698            mixedPieces[i] = regexEscape(mixedPieces[i]);
75699        }
75700
75701        this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
75702        this._monthsShortRegex = this._monthsRegex;
75703        this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
75704        this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
75705    }
75706
75707    function createDate (y, m, d, h, M, s, ms) {
75708        // can't just apply() to create a date:
75709        // https://stackoverflow.com/q/181348
75710        var date = new Date(y, m, d, h, M, s, ms);
75711
75712        // the date constructor remaps years 0-99 to 1900-1999
75713        if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
75714            date.setFullYear(y);
75715        }
75716        return date;
75717    }
75718
75719    function createUTCDate (y) {
75720        var date = new Date(Date.UTC.apply(null, arguments));
75721
75722        // the Date.UTC function remaps years 0-99 to 1900-1999
75723        if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
75724            date.setUTCFullYear(y);
75725        }
75726        return date;
75727    }
75728
75729    // start-of-first-week - start-of-year
75730    function firstWeekOffset(year, dow, doy) {
75731        var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
75732            fwd = 7 + dow - doy,
75733            // first-week day local weekday -- which local weekday is fwd
75734            fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
75735
75736        return -fwdlw + fwd - 1;
75737    }
75738
75739    // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
75740    function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
75741        var localWeekday = (7 + weekday - dow) % 7,
75742            weekOffset = firstWeekOffset(year, dow, doy),
75743            dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
75744            resYear, resDayOfYear;
75745
75746        if (dayOfYear <= 0) {
75747            resYear = year - 1;
75748            resDayOfYear = daysInYear(resYear) + dayOfYear;
75749        } else if (dayOfYear > daysInYear(year)) {
75750            resYear = year + 1;
75751            resDayOfYear = dayOfYear - daysInYear(year);
75752        } else {
75753            resYear = year;
75754            resDayOfYear = dayOfYear;
75755        }
75756
75757        return {
75758            year: resYear,
75759            dayOfYear: resDayOfYear
75760        };
75761    }
75762
75763    function weekOfYear(mom, dow, doy) {
75764        var weekOffset = firstWeekOffset(mom.year(), dow, doy),
75765            week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
75766            resWeek, resYear;
75767
75768        if (week < 1) {
75769            resYear = mom.year() - 1;
75770            resWeek = week + weeksInYear(resYear, dow, doy);
75771        } else if (week > weeksInYear(mom.year(), dow, doy)) {
75772            resWeek = week - weeksInYear(mom.year(), dow, doy);
75773            resYear = mom.year() + 1;
75774        } else {
75775            resYear = mom.year();
75776            resWeek = week;
75777        }
75778
75779        return {
75780            week: resWeek,
75781            year: resYear
75782        };
75783    }
75784
75785    function weeksInYear(year, dow, doy) {
75786        var weekOffset = firstWeekOffset(year, dow, doy),
75787            weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
75788        return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
75789    }
75790
75791    // FORMATTING
75792
75793    addFormatToken('w', ['ww', 2], 'wo', 'week');
75794    addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
75795
75796    // ALIASES
75797
75798    addUnitAlias('week', 'w');
75799    addUnitAlias('isoWeek', 'W');
75800
75801    // PRIORITIES
75802
75803    addUnitPriority('week', 5);
75804    addUnitPriority('isoWeek', 5);
75805
75806    // PARSING
75807
75808    addRegexToken('w',  match1to2);
75809    addRegexToken('ww', match1to2, match2);
75810    addRegexToken('W',  match1to2);
75811    addRegexToken('WW', match1to2, match2);
75812
75813    addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
75814        week[token.substr(0, 1)] = toInt(input);
75815    });
75816
75817    // HELPERS
75818
75819    // LOCALES
75820
75821    function localeWeek (mom) {
75822        return weekOfYear(mom, this._week.dow, this._week.doy).week;
75823    }
75824
75825    var defaultLocaleWeek = {
75826        dow : 0, // Sunday is the first day of the week.
75827        doy : 6  // The week that contains Jan 1st is the first week of the year.
75828    };
75829
75830    function localeFirstDayOfWeek () {
75831        return this._week.dow;
75832    }
75833
75834    function localeFirstDayOfYear () {
75835        return this._week.doy;
75836    }
75837
75838    // MOMENTS
75839
75840    function getSetWeek (input) {
75841        var week = this.localeData().week(this);
75842        return input == null ? week : this.add((input - week) * 7, 'd');
75843    }
75844
75845    function getSetISOWeek (input) {
75846        var week = weekOfYear(this, 1, 4).week;
75847        return input == null ? week : this.add((input - week) * 7, 'd');
75848    }
75849
75850    // FORMATTING
75851
75852    addFormatToken('d', 0, 'do', 'day');
75853
75854    addFormatToken('dd', 0, 0, function (format) {
75855        return this.localeData().weekdaysMin(this, format);
75856    });
75857
75858    addFormatToken('ddd', 0, 0, function (format) {
75859        return this.localeData().weekdaysShort(this, format);
75860    });
75861
75862    addFormatToken('dddd', 0, 0, function (format) {
75863        return this.localeData().weekdays(this, format);
75864    });
75865
75866    addFormatToken('e', 0, 0, 'weekday');
75867    addFormatToken('E', 0, 0, 'isoWeekday');
75868
75869    // ALIASES
75870
75871    addUnitAlias('day', 'd');
75872    addUnitAlias('weekday', 'e');
75873    addUnitAlias('isoWeekday', 'E');
75874
75875    // PRIORITY
75876    addUnitPriority('day', 11);
75877    addUnitPriority('weekday', 11);
75878    addUnitPriority('isoWeekday', 11);
75879
75880    // PARSING
75881
75882    addRegexToken('d',    match1to2);
75883    addRegexToken('e',    match1to2);
75884    addRegexToken('E',    match1to2);
75885    addRegexToken('dd',   function (isStrict, locale) {
75886        return locale.weekdaysMinRegex(isStrict);
75887    });
75888    addRegexToken('ddd',   function (isStrict, locale) {
75889        return locale.weekdaysShortRegex(isStrict);
75890    });
75891    addRegexToken('dddd',   function (isStrict, locale) {
75892        return locale.weekdaysRegex(isStrict);
75893    });
75894
75895    addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
75896        var weekday = config._locale.weekdaysParse(input, token, config._strict);
75897        // if we didn't get a weekday name, mark the date as invalid
75898        if (weekday != null) {
75899            week.d = weekday;
75900        } else {
75901            getParsingFlags(config).invalidWeekday = input;
75902        }
75903    });
75904
75905    addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
75906        week[token] = toInt(input);
75907    });
75908
75909    // HELPERS
75910
75911    function parseWeekday(input, locale) {
75912        if (typeof input !== 'string') {
75913            return input;
75914        }
75915
75916        if (!isNaN(input)) {
75917            return parseInt(input, 10);
75918        }
75919
75920        input = locale.weekdaysParse(input);
75921        if (typeof input === 'number') {
75922            return input;
75923        }
75924
75925        return null;
75926    }
75927
75928    function parseIsoWeekday(input, locale) {
75929        if (typeof input === 'string') {
75930            return locale.weekdaysParse(input) % 7 || 7;
75931        }
75932        return isNaN(input) ? null : input;
75933    }
75934
75935    // LOCALES
75936
75937    var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
75938    function localeWeekdays (m, format) {
75939        if (!m) {
75940            return isArray(this._weekdays) ? this._weekdays :
75941                this._weekdays['standalone'];
75942        }
75943        return isArray(this._weekdays) ? this._weekdays[m.day()] :
75944            this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
75945    }
75946
75947    var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
75948    function localeWeekdaysShort (m) {
75949        return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
75950    }
75951
75952    var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
75953    function localeWeekdaysMin (m) {
75954        return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
75955    }
75956
75957    function handleStrictParse$1(weekdayName, format, strict) {
75958        var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
75959        if (!this._weekdaysParse) {
75960            this._weekdaysParse = [];
75961            this._shortWeekdaysParse = [];
75962            this._minWeekdaysParse = [];
75963
75964            for (i = 0; i < 7; ++i) {
75965                mom = createUTC([2000, 1]).day(i);
75966                this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
75967                this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
75968                this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
75969            }
75970        }
75971
75972        if (strict) {
75973            if (format === 'dddd') {
75974                ii = indexOf.call(this._weekdaysParse, llc);
75975                return ii !== -1 ? ii : null;
75976            } else if (format === 'ddd') {
75977                ii = indexOf.call(this._shortWeekdaysParse, llc);
75978                return ii !== -1 ? ii : null;
75979            } else {
75980                ii = indexOf.call(this._minWeekdaysParse, llc);
75981                return ii !== -1 ? ii : null;
75982            }
75983        } else {
75984            if (format === 'dddd') {
75985                ii = indexOf.call(this._weekdaysParse, llc);
75986                if (ii !== -1) {
75987                    return ii;
75988                }
75989                ii = indexOf.call(this._shortWeekdaysParse, llc);
75990                if (ii !== -1) {
75991                    return ii;
75992                }
75993                ii = indexOf.call(this._minWeekdaysParse, llc);
75994                return ii !== -1 ? ii : null;
75995            } else if (format === 'ddd') {
75996                ii = indexOf.call(this._shortWeekdaysParse, llc);
75997                if (ii !== -1) {
75998                    return ii;
75999                }
76000                ii = indexOf.call(this._weekdaysParse, llc);
76001                if (ii !== -1) {
76002                    return ii;
76003                }
76004                ii = indexOf.call(this._minWeekdaysParse, llc);
76005                return ii !== -1 ? ii : null;
76006            } else {
76007                ii = indexOf.call(this._minWeekdaysParse, llc);
76008                if (ii !== -1) {
76009                    return ii;
76010                }
76011                ii = indexOf.call(this._weekdaysParse, llc);
76012                if (ii !== -1) {
76013                    return ii;
76014                }
76015                ii = indexOf.call(this._shortWeekdaysParse, llc);
76016                return ii !== -1 ? ii : null;
76017            }
76018        }
76019    }
76020
76021    function localeWeekdaysParse (weekdayName, format, strict) {
76022        var i, mom, regex;
76023
76024        if (this._weekdaysParseExact) {
76025            return handleStrictParse$1.call(this, weekdayName, format, strict);
76026        }
76027
76028        if (!this._weekdaysParse) {
76029            this._weekdaysParse = [];
76030            this._minWeekdaysParse = [];
76031            this._shortWeekdaysParse = [];
76032            this._fullWeekdaysParse = [];
76033        }
76034
76035        for (i = 0; i < 7; i++) {
76036            // make the regex if we don't have it already
76037
76038            mom = createUTC([2000, 1]).day(i);
76039            if (strict && !this._fullWeekdaysParse[i]) {
76040                this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\\.?') + '$', 'i');
76041                this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$', 'i');
76042                this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$', 'i');
76043            }
76044            if (!this._weekdaysParse[i]) {
76045                regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
76046                this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
76047            }
76048            // test the regex
76049            if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
76050                return i;
76051            } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
76052                return i;
76053            } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
76054                return i;
76055            } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
76056                return i;
76057            }
76058        }
76059    }
76060
76061    // MOMENTS
76062
76063    function getSetDayOfWeek (input) {
76064        if (!this.isValid()) {
76065            return input != null ? this : NaN;
76066        }
76067        var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
76068        if (input != null) {
76069            input = parseWeekday(input, this.localeData());
76070            return this.add(input - day, 'd');
76071        } else {
76072            return day;
76073        }
76074    }
76075
76076    function getSetLocaleDayOfWeek (input) {
76077        if (!this.isValid()) {
76078            return input != null ? this : NaN;
76079        }
76080        var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
76081        return input == null ? weekday : this.add(input - weekday, 'd');
76082    }
76083
76084    function getSetISODayOfWeek (input) {
76085        if (!this.isValid()) {
76086            return input != null ? this : NaN;
76087        }
76088
76089        // behaves the same as moment#day except
76090        // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
76091        // as a setter, sunday should belong to the previous week.
76092
76093        if (input != null) {
76094            var weekday = parseIsoWeekday(input, this.localeData());
76095            return this.day(this.day() % 7 ? weekday : weekday - 7);
76096        } else {
76097            return this.day() || 7;
76098        }
76099    }
76100
76101    var defaultWeekdaysRegex = matchWord;
76102    function weekdaysRegex (isStrict) {
76103        if (this._weekdaysParseExact) {
76104            if (!hasOwnProp(this, '_weekdaysRegex')) {
76105                computeWeekdaysParse.call(this);
76106            }
76107            if (isStrict) {
76108                return this._weekdaysStrictRegex;
76109            } else {
76110                return this._weekdaysRegex;
76111            }
76112        } else {
76113            if (!hasOwnProp(this, '_weekdaysRegex')) {
76114                this._weekdaysRegex = defaultWeekdaysRegex;
76115            }
76116            return this._weekdaysStrictRegex && isStrict ?
76117                this._weekdaysStrictRegex : this._weekdaysRegex;
76118        }
76119    }
76120
76121    var defaultWeekdaysShortRegex = matchWord;
76122    function weekdaysShortRegex (isStrict) {
76123        if (this._weekdaysParseExact) {
76124            if (!hasOwnProp(this, '_weekdaysRegex')) {
76125                computeWeekdaysParse.call(this);
76126            }
76127            if (isStrict) {
76128                return this._weekdaysShortStrictRegex;
76129            } else {
76130                return this._weekdaysShortRegex;
76131            }
76132        } else {
76133            if (!hasOwnProp(this, '_weekdaysShortRegex')) {
76134                this._weekdaysShortRegex = defaultWeekdaysShortRegex;
76135            }
76136            return this._weekdaysShortStrictRegex && isStrict ?
76137                this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
76138        }
76139    }
76140
76141    var defaultWeekdaysMinRegex = matchWord;
76142    function weekdaysMinRegex (isStrict) {
76143        if (this._weekdaysParseExact) {
76144            if (!hasOwnProp(this, '_weekdaysRegex')) {
76145                computeWeekdaysParse.call(this);
76146            }
76147            if (isStrict) {
76148                return this._weekdaysMinStrictRegex;
76149            } else {
76150                return this._weekdaysMinRegex;
76151            }
76152        } else {
76153            if (!hasOwnProp(this, '_weekdaysMinRegex')) {
76154                this._weekdaysMinRegex = defaultWeekdaysMinRegex;
76155            }
76156            return this._weekdaysMinStrictRegex && isStrict ?
76157                this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
76158        }
76159    }
76160
76161
76162    function computeWeekdaysParse () {
76163        function cmpLenRev(a, b) {
76164            return b.length - a.length;
76165        }
76166
76167        var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
76168            i, mom, minp, shortp, longp;
76169        for (i = 0; i < 7; i++) {
76170            // make the regex if we don't have it already
76171            mom = createUTC([2000, 1]).day(i);
76172            minp = this.weekdaysMin(mom, '');
76173            shortp = this.weekdaysShort(mom, '');
76174            longp = this.weekdays(mom, '');
76175            minPieces.push(minp);
76176            shortPieces.push(shortp);
76177            longPieces.push(longp);
76178            mixedPieces.push(minp);
76179            mixedPieces.push(shortp);
76180            mixedPieces.push(longp);
76181        }
76182        // Sorting makes sure if one weekday (or abbr) is a prefix of another it
76183        // will match the longer piece.
76184        minPieces.sort(cmpLenRev);
76185        shortPieces.sort(cmpLenRev);
76186        longPieces.sort(cmpLenRev);
76187        mixedPieces.sort(cmpLenRev);
76188        for (i = 0; i < 7; i++) {
76189            shortPieces[i] = regexEscape(shortPieces[i]);
76190            longPieces[i] = regexEscape(longPieces[i]);
76191            mixedPieces[i] = regexEscape(mixedPieces[i]);
76192        }
76193
76194        this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
76195        this._weekdaysShortRegex = this._weekdaysRegex;
76196        this._weekdaysMinRegex = this._weekdaysRegex;
76197
76198        this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
76199        this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
76200        this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
76201    }
76202
76203    // FORMATTING
76204
76205    function hFormat() {
76206        return this.hours() % 12 || 12;
76207    }
76208
76209    function kFormat() {
76210        return this.hours() || 24;
76211    }
76212
76213    addFormatToken('H', ['HH', 2], 0, 'hour');
76214    addFormatToken('h', ['hh', 2], 0, hFormat);
76215    addFormatToken('k', ['kk', 2], 0, kFormat);
76216
76217    addFormatToken('hmm', 0, 0, function () {
76218        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
76219    });
76220
76221    addFormatToken('hmmss', 0, 0, function () {
76222        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
76223            zeroFill(this.seconds(), 2);
76224    });
76225
76226    addFormatToken('Hmm', 0, 0, function () {
76227        return '' + this.hours() + zeroFill(this.minutes(), 2);
76228    });
76229
76230    addFormatToken('Hmmss', 0, 0, function () {
76231        return '' + this.hours() + zeroFill(this.minutes(), 2) +
76232            zeroFill(this.seconds(), 2);
76233    });
76234
76235    function meridiem (token, lowercase) {
76236        addFormatToken(token, 0, 0, function () {
76237            return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
76238        });
76239    }
76240
76241    meridiem('a', true);
76242    meridiem('A', false);
76243
76244    // ALIASES
76245
76246    addUnitAlias('hour', 'h');
76247
76248    // PRIORITY
76249    addUnitPriority('hour', 13);
76250
76251    // PARSING
76252
76253    function matchMeridiem (isStrict, locale) {
76254        return locale._meridiemParse;
76255    }
76256
76257    addRegexToken('a',  matchMeridiem);
76258    addRegexToken('A',  matchMeridiem);
76259    addRegexToken('H',  match1to2);
76260    addRegexToken('h',  match1to2);
76261    addRegexToken('k',  match1to2);
76262    addRegexToken('HH', match1to2, match2);
76263    addRegexToken('hh', match1to2, match2);
76264    addRegexToken('kk', match1to2, match2);
76265
76266    addRegexToken('hmm', match3to4);
76267    addRegexToken('hmmss', match5to6);
76268    addRegexToken('Hmm', match3to4);
76269    addRegexToken('Hmmss', match5to6);
76270
76271    addParseToken(['H', 'HH'], HOUR);
76272    addParseToken(['k', 'kk'], function (input, array, config) {
76273        var kInput = toInt(input);
76274        array[HOUR] = kInput === 24 ? 0 : kInput;
76275    });
76276    addParseToken(['a', 'A'], function (input, array, config) {
76277        config._isPm = config._locale.isPM(input);
76278        config._meridiem = input;
76279    });
76280    addParseToken(['h', 'hh'], function (input, array, config) {
76281        array[HOUR] = toInt(input);
76282        getParsingFlags(config).bigHour = true;
76283    });
76284    addParseToken('hmm', function (input, array, config) {
76285        var pos = input.length - 2;
76286        array[HOUR] = toInt(input.substr(0, pos));
76287        array[MINUTE] = toInt(input.substr(pos));
76288        getParsingFlags(config).bigHour = true;
76289    });
76290    addParseToken('hmmss', function (input, array, config) {
76291        var pos1 = input.length - 4;
76292        var pos2 = input.length - 2;
76293        array[HOUR] = toInt(input.substr(0, pos1));
76294        array[MINUTE] = toInt(input.substr(pos1, 2));
76295        array[SECOND] = toInt(input.substr(pos2));
76296        getParsingFlags(config).bigHour = true;
76297    });
76298    addParseToken('Hmm', function (input, array, config) {
76299        var pos = input.length - 2;
76300        array[HOUR] = toInt(input.substr(0, pos));
76301        array[MINUTE] = toInt(input.substr(pos));
76302    });
76303    addParseToken('Hmmss', function (input, array, config) {
76304        var pos1 = input.length - 4;
76305        var pos2 = input.length - 2;
76306        array[HOUR] = toInt(input.substr(0, pos1));
76307        array[MINUTE] = toInt(input.substr(pos1, 2));
76308        array[SECOND] = toInt(input.substr(pos2));
76309    });
76310
76311    // LOCALES
76312
76313    function localeIsPM (input) {
76314        // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
76315        // Using charAt should be more compatible.
76316        return ((input + '').toLowerCase().charAt(0) === 'p');
76317    }
76318
76319    var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
76320    function localeMeridiem (hours, minutes, isLower) {
76321        if (hours > 11) {
76322            return isLower ? 'pm' : 'PM';
76323        } else {
76324            return isLower ? 'am' : 'AM';
76325        }
76326    }
76327
76328
76329    // MOMENTS
76330
76331    // Setting the hour should keep the time, because the user explicitly
76332    // specified which hour they want. So trying to maintain the same hour (in
76333    // a new timezone) makes sense. Adding/subtracting hours does not follow
76334    // this rule.
76335    var getSetHour = makeGetSet('Hours', true);
76336
76337    var baseConfig = {
76338        calendar: defaultCalendar,
76339        longDateFormat: defaultLongDateFormat,
76340        invalidDate: defaultInvalidDate,
76341        ordinal: defaultOrdinal,
76342        dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
76343        relativeTime: defaultRelativeTime,
76344
76345        months: defaultLocaleMonths,
76346        monthsShort: defaultLocaleMonthsShort,
76347
76348        week: defaultLocaleWeek,
76349
76350        weekdays: defaultLocaleWeekdays,
76351        weekdaysMin: defaultLocaleWeekdaysMin,
76352        weekdaysShort: defaultLocaleWeekdaysShort,
76353
76354        meridiemParse: defaultLocaleMeridiemParse
76355    };
76356
76357    // internal storage for locale config files
76358    var locales = {};
76359    var localeFamilies = {};
76360    var globalLocale;
76361
76362    function normalizeLocale(key) {
76363        return key ? key.toLowerCase().replace('_', '-') : key;
76364    }
76365
76366    // pick the locale from the array
76367    // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
76368    // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
76369    function chooseLocale(names) {
76370        var i = 0, j, next, locale, split;
76371
76372        while (i < names.length) {
76373            split = normalizeLocale(names[i]).split('-');
76374            j = split.length;
76375            next = normalizeLocale(names[i + 1]);
76376            next = next ? next.split('-') : null;
76377            while (j > 0) {
76378                locale = loadLocale(split.slice(0, j).join('-'));
76379                if (locale) {
76380                    return locale;
76381                }
76382                if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
76383                    //the next array item is better than a shallower substring of this one
76384                    break;
76385                }
76386                j--;
76387            }
76388            i++;
76389        }
76390        return globalLocale;
76391    }
76392
76393    function loadLocale(name) {
76394        var oldLocale = null;
76395        // TODO: Find a better way to register and load all the locales in Node
76396        if (!locales[name] && (typeof module !== 'undefined') &&
76397                module && module.exports) {
76398            try {
76399                oldLocale = globalLocale._abbr;
76400                var aliasedRequire = require;
76401                aliasedRequire('./locale/' + name);
76402                getSetGlobalLocale(oldLocale);
76403            } catch (e) {}
76404        }
76405        return locales[name];
76406    }
76407
76408    // This function will load locale and then set the global locale.  If
76409    // no arguments are passed in, it will simply return the current global
76410    // locale key.
76411    function getSetGlobalLocale (key, values) {
76412        var data;
76413        if (key) {
76414            if (isUndefined(values)) {
76415                data = getLocale(key);
76416            }
76417            else {
76418                data = defineLocale(key, values);
76419            }
76420
76421            if (data) {
76422                // moment.duration._locale = moment._locale = data;
76423                globalLocale = data;
76424            }
76425            else {
76426                if ((typeof console !==  'undefined') && console.warn) {
76427                    //warn user if arguments are passed but the locale could not be set
76428                    console.warn('Locale ' + key +  ' not found. Did you forget to load it?');
76429                }
76430            }
76431        }
76432
76433        return globalLocale._abbr;
76434    }
76435
76436    function defineLocale (name, config) {
76437        if (config !== null) {
76438            var locale, parentConfig = baseConfig;
76439            config.abbr = name;
76440            if (locales[name] != null) {
76441                deprecateSimple('defineLocaleOverride',
76442                        'use moment.updateLocale(localeName, config) to change ' +
76443                        'an existing locale. moment.defineLocale(localeName, ' +
76444                        'config) should only be used for creating a new locale ' +
76445                        'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
76446                parentConfig = locales[name]._config;
76447            } else if (config.parentLocale != null) {
76448                if (locales[config.parentLocale] != null) {
76449                    parentConfig = locales[config.parentLocale]._config;
76450                } else {
76451                    locale = loadLocale(config.parentLocale);
76452                    if (locale != null) {
76453                        parentConfig = locale._config;
76454                    } else {
76455                        if (!localeFamilies[config.parentLocale]) {
76456                            localeFamilies[config.parentLocale] = [];
76457                        }
76458                        localeFamilies[config.parentLocale].push({
76459                            name: name,
76460                            config: config
76461                        });
76462                        return null;
76463                    }
76464                }
76465            }
76466            locales[name] = new Locale(mergeConfigs(parentConfig, config));
76467
76468            if (localeFamilies[name]) {
76469                localeFamilies[name].forEach(function (x) {
76470                    defineLocale(x.name, x.config);
76471                });
76472            }
76473
76474            // backwards compat for now: also set the locale
76475            // make sure we set the locale AFTER all child locales have been
76476            // created, so we won't end up with the child locale set.
76477            getSetGlobalLocale(name);
76478
76479
76480            return locales[name];
76481        } else {
76482            // useful for testing
76483            delete locales[name];
76484            return null;
76485        }
76486    }
76487
76488    function updateLocale(name, config) {
76489        if (config != null) {
76490            var locale, tmpLocale, parentConfig = baseConfig;
76491            // MERGE
76492            tmpLocale = loadLocale(name);
76493            if (tmpLocale != null) {
76494                parentConfig = tmpLocale._config;
76495            }
76496            config = mergeConfigs(parentConfig, config);
76497            locale = new Locale(config);
76498            locale.parentLocale = locales[name];
76499            locales[name] = locale;
76500
76501            // backwards compat for now: also set the locale
76502            getSetGlobalLocale(name);
76503        } else {
76504            // pass null for config to unupdate, useful for tests
76505            if (locales[name] != null) {
76506                if (locales[name].parentLocale != null) {
76507                    locales[name] = locales[name].parentLocale;
76508                } else if (locales[name] != null) {
76509                    delete locales[name];
76510                }
76511            }
76512        }
76513        return locales[name];
76514    }
76515
76516    // returns locale data
76517    function getLocale (key) {
76518        var locale;
76519
76520        if (key && key._locale && key._locale._abbr) {
76521            key = key._locale._abbr;
76522        }
76523
76524        if (!key) {
76525            return globalLocale;
76526        }
76527
76528        if (!isArray(key)) {
76529            //short-circuit everything else
76530            locale = loadLocale(key);
76531            if (locale) {
76532                return locale;
76533            }
76534            key = [key];
76535        }
76536
76537        return chooseLocale(key);
76538    }
76539
76540    function listLocales() {
76541        return keys(locales);
76542    }
76543
76544    function checkOverflow (m) {
76545        var overflow;
76546        var a = m._a;
76547
76548        if (a && getParsingFlags(m).overflow === -2) {
76549            overflow =
76550                a[MONTH]       < 0 || a[MONTH]       > 11  ? MONTH :
76551                a[DATE]        < 1 || a[DATE]        > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
76552                a[HOUR]        < 0 || a[HOUR]        > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
76553                a[MINUTE]      < 0 || a[MINUTE]      > 59  ? MINUTE :
76554                a[SECOND]      < 0 || a[SECOND]      > 59  ? SECOND :
76555                a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
76556                -1;
76557
76558            if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
76559                overflow = DATE;
76560            }
76561            if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
76562                overflow = WEEK;
76563            }
76564            if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
76565                overflow = WEEKDAY;
76566            }
76567
76568            getParsingFlags(m).overflow = overflow;
76569        }
76570
76571        return m;
76572    }
76573
76574    // Pick the first defined of two or three arguments.
76575    function defaults(a, b, c) {
76576        if (a != null) {
76577            return a;
76578        }
76579        if (b != null) {
76580            return b;
76581        }
76582        return c;
76583    }
76584
76585    function currentDateArray(config) {
76586        // hooks is actually the exported moment object
76587        var nowValue = new Date(hooks.now());
76588        if (config._useUTC) {
76589            return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
76590        }
76591        return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
76592    }
76593
76594    // convert an array to a date.
76595    // the array should mirror the parameters below
76596    // note: all values past the year are optional and will default to the lowest possible value.
76597    // [year, month, day , hour, minute, second, millisecond]
76598    function configFromArray (config) {
76599        var i, date, input = [], currentDate, expectedWeekday, yearToUse;
76600
76601        if (config._d) {
76602            return;
76603        }
76604
76605        currentDate = currentDateArray(config);
76606
76607        //compute day of the year from weeks and weekdays
76608        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
76609            dayOfYearFromWeekInfo(config);
76610        }
76611
76612        //if the day of the year is set, figure out what it is
76613        if (config._dayOfYear != null) {
76614            yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
76615
76616            if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
76617                getParsingFlags(config)._overflowDayOfYear = true;
76618            }
76619
76620            date = createUTCDate(yearToUse, 0, config._dayOfYear);
76621            config._a[MONTH] = date.getUTCMonth();
76622            config._a[DATE] = date.getUTCDate();
76623        }
76624
76625        // Default to current date.
76626        // * if no year, month, day of month are given, default to today
76627        // * if day of month is given, default month and year
76628        // * if month is given, default only year
76629        // * if year is given, don't default anything
76630        for (i = 0; i < 3 && config._a[i] == null; ++i) {
76631            config._a[i] = input[i] = currentDate[i];
76632        }
76633
76634        // Zero out whatever was not defaulted, including time
76635        for (; i < 7; i++) {
76636            config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
76637        }
76638
76639        // Check for 24:00:00.000
76640        if (config._a[HOUR] === 24 &&
76641                config._a[MINUTE] === 0 &&
76642                config._a[SECOND] === 0 &&
76643                config._a[MILLISECOND] === 0) {
76644            config._nextDay = true;
76645            config._a[HOUR] = 0;
76646        }
76647
76648        config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
76649        expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay();
76650
76651        // Apply timezone offset from input. The actual utcOffset can be changed
76652        // with parseZone.
76653        if (config._tzm != null) {
76654            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
76655        }
76656
76657        if (config._nextDay) {
76658            config._a[HOUR] = 24;
76659        }
76660
76661        // check for mismatching day of week
76662        if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== expectedWeekday) {
76663            getParsingFlags(config).weekdayMismatch = true;
76664        }
76665    }
76666
76667    function dayOfYearFromWeekInfo(config) {
76668        var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
76669
76670        w = config._w;
76671        if (w.GG != null || w.W != null || w.E != null) {
76672            dow = 1;
76673            doy = 4;
76674
76675            // TODO: We need to take the current isoWeekYear, but that depends on
76676            // how we interpret now (local, utc, fixed offset). So create
76677            // a now version of current config (take local/utc/offset flags, and
76678            // create now).
76679            weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
76680            week = defaults(w.W, 1);
76681            weekday = defaults(w.E, 1);
76682            if (weekday < 1 || weekday > 7) {
76683                weekdayOverflow = true;
76684            }
76685        } else {
76686            dow = config._locale._week.dow;
76687            doy = config._locale._week.doy;
76688
76689            var curWeek = weekOfYear(createLocal(), dow, doy);
76690
76691            weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);
76692
76693            // Default to current week.
76694            week = defaults(w.w, curWeek.week);
76695
76696            if (w.d != null) {
76697                // weekday -- low day numbers are considered next week
76698                weekday = w.d;
76699                if (weekday < 0 || weekday > 6) {
76700                    weekdayOverflow = true;
76701                }
76702            } else if (w.e != null) {
76703                // local weekday -- counting starts from begining of week
76704                weekday = w.e + dow;
76705                if (w.e < 0 || w.e > 6) {
76706                    weekdayOverflow = true;
76707                }
76708            } else {
76709                // default to begining of week
76710                weekday = dow;
76711            }
76712        }
76713        if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
76714            getParsingFlags(config)._overflowWeeks = true;
76715        } else if (weekdayOverflow != null) {
76716            getParsingFlags(config)._overflowWeekday = true;
76717        } else {
76718            temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
76719            config._a[YEAR] = temp.year;
76720            config._dayOfYear = temp.dayOfYear;
76721        }
76722    }
76723
76724    // iso 8601 regex
76725    // 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)
76726    var 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)?)?$/;
76727    var 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)?)?$/;
76728
76729    var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
76730
76731    var isoDates = [
76732        ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
76733        ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
76734        ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
76735        ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
76736        ['YYYY-DDD', /\d{4}-\d{3}/],
76737        ['YYYY-MM', /\d{4}-\d\d/, false],
76738        ['YYYYYYMMDD', /[+-]\d{10}/],
76739        ['YYYYMMDD', /\d{8}/],
76740        // YYYYMM is NOT allowed by the standard
76741        ['GGGG[W]WWE', /\d{4}W\d{3}/],
76742        ['GGGG[W]WW', /\d{4}W\d{2}/, false],
76743        ['YYYYDDD', /\d{7}/]
76744    ];
76745
76746    // iso time formats and regexes
76747    var isoTimes = [
76748        ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
76749        ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
76750        ['HH:mm:ss', /\d\d:\d\d:\d\d/],
76751        ['HH:mm', /\d\d:\d\d/],
76752        ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
76753        ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
76754        ['HHmmss', /\d\d\d\d\d\d/],
76755        ['HHmm', /\d\d\d\d/],
76756        ['HH', /\d\d/]
76757    ];
76758
76759    var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
76760
76761    // date from iso format
76762    function configFromISO(config) {
76763        var i, l,
76764            string = config._i,
76765            match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
76766            allowTime, dateFormat, timeFormat, tzFormat;
76767
76768        if (match) {
76769            getParsingFlags(config).iso = true;
76770
76771            for (i = 0, l = isoDates.length; i < l; i++) {
76772                if (isoDates[i][1].exec(match[1])) {
76773                    dateFormat = isoDates[i][0];
76774                    allowTime = isoDates[i][2] !== false;
76775                    break;
76776                }
76777            }
76778            if (dateFormat == null) {
76779                config._isValid = false;
76780                return;
76781            }
76782            if (match[3]) {
76783                for (i = 0, l = isoTimes.length; i < l; i++) {
76784                    if (isoTimes[i][1].exec(match[3])) {
76785                        // match[2] should be 'T' or space
76786                        timeFormat = (match[2] || ' ') + isoTimes[i][0];
76787                        break;
76788                    }
76789                }
76790                if (timeFormat == null) {
76791                    config._isValid = false;
76792                    return;
76793                }
76794            }
76795            if (!allowTime && timeFormat != null) {
76796                config._isValid = false;
76797                return;
76798            }
76799            if (match[4]) {
76800                if (tzRegex.exec(match[4])) {
76801                    tzFormat = 'Z';
76802                } else {
76803                    config._isValid = false;
76804                    return;
76805                }
76806            }
76807            config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
76808            configFromStringAndFormat(config);
76809        } else {
76810            config._isValid = false;
76811        }
76812    }
76813
76814    // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
76815    var 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}))$/;
76816
76817    function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
76818        var result = [
76819            untruncateYear(yearStr),
76820            defaultLocaleMonthsShort.indexOf(monthStr),
76821            parseInt(dayStr, 10),
76822            parseInt(hourStr, 10),
76823            parseInt(minuteStr, 10)
76824        ];
76825
76826        if (secondStr) {
76827            result.push(parseInt(secondStr, 10));
76828        }
76829
76830        return result;
76831    }
76832
76833    function untruncateYear(yearStr) {
76834        var year = parseInt(yearStr, 10);
76835        if (year <= 49) {
76836            return 2000 + year;
76837        } else if (year <= 999) {
76838            return 1900 + year;
76839        }
76840        return year;
76841    }
76842
76843    function preprocessRFC2822(s) {
76844        // Remove comments and folding whitespace and replace multiple-spaces with a single space
76845        return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
76846    }
76847
76848    function checkWeekday(weekdayStr, parsedInput, config) {
76849        if (weekdayStr) {
76850            // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check.
76851            var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
76852                weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay();
76853            if (weekdayProvided !== weekdayActual) {
76854                getParsingFlags(config).weekdayMismatch = true;
76855                config._isValid = false;
76856                return false;
76857            }
76858        }
76859        return true;
76860    }
76861
76862    var obsOffsets = {
76863        UT: 0,
76864        GMT: 0,
76865        EDT: -4 * 60,
76866        EST: -5 * 60,
76867        CDT: -5 * 60,
76868        CST: -6 * 60,
76869        MDT: -6 * 60,
76870        MST: -7 * 60,
76871        PDT: -7 * 60,
76872        PST: -8 * 60
76873    };
76874
76875    function calculateOffset(obsOffset, militaryOffset, numOffset) {
76876        if (obsOffset) {
76877            return obsOffsets[obsOffset];
76878        } else if (militaryOffset) {
76879            // the only allowed military tz is Z
76880            return 0;
76881        } else {
76882            var hm = parseInt(numOffset, 10);
76883            var m = hm % 100, h = (hm - m) / 100;
76884            return h * 60 + m;
76885        }
76886    }
76887
76888    // date and time from ref 2822 format
76889    function configFromRFC2822(config) {
76890        var match = rfc2822.exec(preprocessRFC2822(config._i));
76891        if (match) {
76892            var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]);
76893            if (!checkWeekday(match[1], parsedArray, config)) {
76894                return;
76895            }
76896
76897            config._a = parsedArray;
76898            config._tzm = calculateOffset(match[8], match[9], match[10]);
76899
76900            config._d = createUTCDate.apply(null, config._a);
76901            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
76902
76903            getParsingFlags(config).rfc2822 = true;
76904        } else {
76905            config._isValid = false;
76906        }
76907    }
76908
76909    // date from iso format or fallback
76910    function configFromString(config) {
76911        var matched = aspNetJsonRegex.exec(config._i);
76912
76913        if (matched !== null) {
76914            config._d = new Date(+matched[1]);
76915            return;
76916        }
76917
76918        configFromISO(config);
76919        if (config._isValid === false) {
76920            delete config._isValid;
76921        } else {
76922            return;
76923        }
76924
76925        configFromRFC2822(config);
76926        if (config._isValid === false) {
76927            delete config._isValid;
76928        } else {
76929            return;
76930        }
76931
76932        // Final attempt, use Input Fallback
76933        hooks.createFromInputFallback(config);
76934    }
76935
76936    hooks.createFromInputFallback = deprecate(
76937        'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
76938        'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
76939        'discouraged and will be removed in an upcoming major release. Please refer to ' +
76940        'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
76941        function (config) {
76942            config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
76943        }
76944    );
76945
76946    // constant that refers to the ISO standard
76947    hooks.ISO_8601 = function () {};
76948
76949    // constant that refers to the RFC 2822 form
76950    hooks.RFC_2822 = function () {};
76951
76952    // date from string and format string
76953    function configFromStringAndFormat(config) {
76954        // TODO: Move this to another part of the creation flow to prevent circular deps
76955        if (config._f === hooks.ISO_8601) {
76956            configFromISO(config);
76957            return;
76958        }
76959        if (config._f === hooks.RFC_2822) {
76960            configFromRFC2822(config);
76961            return;
76962        }
76963        config._a = [];
76964        getParsingFlags(config).empty = true;
76965
76966        // This array is used to make a Date, either with `new Date` or `Date.UTC`
76967        var string = '' + config._i,
76968            i, parsedInput, tokens, token, skipped,
76969            stringLength = string.length,
76970            totalParsedInputLength = 0;
76971
76972        tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
76973
76974        for (i = 0; i < tokens.length; i++) {
76975            token = tokens[i];
76976            parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
76977            // console.log('token', token, 'parsedInput', parsedInput,
76978            //         'regex', getParseRegexForToken(token, config));
76979            if (parsedInput) {
76980                skipped = string.substr(0, string.indexOf(parsedInput));
76981                if (skipped.length > 0) {
76982                    getParsingFlags(config).unusedInput.push(skipped);
76983                }
76984                string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
76985                totalParsedInputLength += parsedInput.length;
76986            }
76987            // don't parse if it's not a known token
76988            if (formatTokenFunctions[token]) {
76989                if (parsedInput) {
76990                    getParsingFlags(config).empty = false;
76991                }
76992                else {
76993                    getParsingFlags(config).unusedTokens.push(token);
76994                }
76995                addTimeToArrayFromToken(token, parsedInput, config);
76996            }
76997            else if (config._strict && !parsedInput) {
76998                getParsingFlags(config).unusedTokens.push(token);
76999            }
77000        }
77001
77002        // add remaining unparsed input length to the string
77003        getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
77004        if (string.length > 0) {
77005            getParsingFlags(config).unusedInput.push(string);
77006        }
77007
77008        // clear _12h flag if hour is <= 12
77009        if (config._a[HOUR] <= 12 &&
77010            getParsingFlags(config).bigHour === true &&
77011            config._a[HOUR] > 0) {
77012            getParsingFlags(config).bigHour = undefined;
77013        }
77014
77015        getParsingFlags(config).parsedDateParts = config._a.slice(0);
77016        getParsingFlags(config).meridiem = config._meridiem;
77017        // handle meridiem
77018        config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
77019
77020        configFromArray(config);
77021        checkOverflow(config);
77022    }
77023
77024
77025    function meridiemFixWrap (locale, hour, meridiem) {
77026        var isPm;
77027
77028        if (meridiem == null) {
77029            // nothing to do
77030            return hour;
77031        }
77032        if (locale.meridiemHour != null) {
77033            return locale.meridiemHour(hour, meridiem);
77034        } else if (locale.isPM != null) {
77035            // Fallback
77036            isPm = locale.isPM(meridiem);
77037            if (isPm && hour < 12) {
77038                hour += 12;
77039            }
77040            if (!isPm && hour === 12) {
77041                hour = 0;
77042            }
77043            return hour;
77044        } else {
77045            // this is not supposed to happen
77046            return hour;
77047        }
77048    }
77049
77050    // date from string and array of format strings
77051    function configFromStringAndArray(config) {
77052        var tempConfig,
77053            bestMoment,
77054
77055            scoreToBeat,
77056            i,
77057            currentScore;
77058
77059        if (config._f.length === 0) {
77060            getParsingFlags(config).invalidFormat = true;
77061            config._d = new Date(NaN);
77062            return;
77063        }
77064
77065        for (i = 0; i < config._f.length; i++) {
77066            currentScore = 0;
77067            tempConfig = copyConfig({}, config);
77068            if (config._useUTC != null) {
77069                tempConfig._useUTC = config._useUTC;
77070            }
77071            tempConfig._f = config._f[i];
77072            configFromStringAndFormat(tempConfig);
77073
77074            if (!isValid(tempConfig)) {
77075                continue;
77076            }
77077
77078            // if there is any input that was not parsed add a penalty for that format
77079            currentScore += getParsingFlags(tempConfig).charsLeftOver;
77080
77081            //or tokens
77082            currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
77083
77084            getParsingFlags(tempConfig).score = currentScore;
77085
77086            if (scoreToBeat == null || currentScore < scoreToBeat) {
77087                scoreToBeat = currentScore;
77088                bestMoment = tempConfig;
77089            }
77090        }
77091
77092        extend(config, bestMoment || tempConfig);
77093    }
77094
77095    function configFromObject(config) {
77096        if (config._d) {
77097            return;
77098        }
77099
77100        var i = normalizeObjectUnits(config._i);
77101        config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
77102            return obj && parseInt(obj, 10);
77103        });
77104
77105        configFromArray(config);
77106    }
77107
77108    function createFromConfig (config) {
77109        var res = new Moment(checkOverflow(prepareConfig(config)));
77110        if (res._nextDay) {
77111            // Adding is smart enough around DST
77112            res.add(1, 'd');
77113            res._nextDay = undefined;
77114        }
77115
77116        return res;
77117    }
77118
77119    function prepareConfig (config) {
77120        var input = config._i,
77121            format = config._f;
77122
77123        config._locale = config._locale || getLocale(config._l);
77124
77125        if (input === null || (format === undefined && input === '')) {
77126            return createInvalid({nullInput: true});
77127        }
77128
77129        if (typeof input === 'string') {
77130            config._i = input = config._locale.preparse(input);
77131        }
77132
77133        if (isMoment(input)) {
77134            return new Moment(checkOverflow(input));
77135        } else if (isDate(input)) {
77136            config._d = input;
77137        } else if (isArray(format)) {
77138            configFromStringAndArray(config);
77139        } else if (format) {
77140            configFromStringAndFormat(config);
77141        }  else {
77142            configFromInput(config);
77143        }
77144
77145        if (!isValid(config)) {
77146            config._d = null;
77147        }
77148
77149        return config;
77150    }
77151
77152    function configFromInput(config) {
77153        var input = config._i;
77154        if (isUndefined(input)) {
77155            config._d = new Date(hooks.now());
77156        } else if (isDate(input)) {
77157            config._d = new Date(input.valueOf());
77158        } else if (typeof input === 'string') {
77159            configFromString(config);
77160        } else if (isArray(input)) {
77161            config._a = map(input.slice(0), function (obj) {
77162                return parseInt(obj, 10);
77163            });
77164            configFromArray(config);
77165        } else if (isObject(input)) {
77166            configFromObject(config);
77167        } else if (isNumber(input)) {
77168            // from milliseconds
77169            config._d = new Date(input);
77170        } else {
77171            hooks.createFromInputFallback(config);
77172        }
77173    }
77174
77175    function createLocalOrUTC (input, format, locale, strict, isUTC) {
77176        var c = {};
77177
77178        if (locale === true || locale === false) {
77179            strict = locale;
77180            locale = undefined;
77181        }
77182
77183        if ((isObject(input) && isObjectEmpty(input)) ||
77184                (isArray(input) && input.length === 0)) {
77185            input = undefined;
77186        }
77187        // object construction must be done this way.
77188        // https://github.com/moment/moment/issues/1423
77189        c._isAMomentObject = true;
77190        c._useUTC = c._isUTC = isUTC;
77191        c._l = locale;
77192        c._i = input;
77193        c._f = format;
77194        c._strict = strict;
77195
77196        return createFromConfig(c);
77197    }
77198
77199    function createLocal (input, format, locale, strict) {
77200        return createLocalOrUTC(input, format, locale, strict, false);
77201    }
77202
77203    var prototypeMin = deprecate(
77204        'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
77205        function () {
77206            var other = createLocal.apply(null, arguments);
77207            if (this.isValid() && other.isValid()) {
77208                return other < this ? this : other;
77209            } else {
77210                return createInvalid();
77211            }
77212        }
77213    );
77214
77215    var prototypeMax = deprecate(
77216        'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
77217        function () {
77218            var other = createLocal.apply(null, arguments);
77219            if (this.isValid() && other.isValid()) {
77220                return other > this ? this : other;
77221            } else {
77222                return createInvalid();
77223            }
77224        }
77225    );
77226
77227    // Pick a moment m from moments so that m[fn](other) is true for all
77228    // other. This relies on the function fn to be transitive.
77229    //
77230    // moments should either be an array of moment objects or an array, whose
77231    // first element is an array of moment objects.
77232    function pickBy(fn, moments) {
77233        var res, i;
77234        if (moments.length === 1 && isArray(moments[0])) {
77235            moments = moments[0];
77236        }
77237        if (!moments.length) {
77238            return createLocal();
77239        }
77240        res = moments[0];
77241        for (i = 1; i < moments.length; ++i) {
77242            if (!moments[i].isValid() || moments[i][fn](res)) {
77243                res = moments[i];
77244            }
77245        }
77246        return res;
77247    }
77248
77249    // TODO: Use [].sort instead?
77250    function min () {
77251        var args = [].slice.call(arguments, 0);
77252
77253        return pickBy('isBefore', args);
77254    }
77255
77256    function max () {
77257        var args = [].slice.call(arguments, 0);
77258
77259        return pickBy('isAfter', args);
77260    }
77261
77262    var now = function () {
77263        return Date.now ? Date.now() : +(new Date());
77264    };
77265
77266    var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
77267
77268    function isDurationValid(m) {
77269        for (var key in m) {
77270            if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
77271                return false;
77272            }
77273        }
77274
77275        var unitHasDecimal = false;
77276        for (var i = 0; i < ordering.length; ++i) {
77277            if (m[ordering[i]]) {
77278                if (unitHasDecimal) {
77279                    return false; // only allow non-integers for smallest unit
77280                }
77281                if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
77282                    unitHasDecimal = true;
77283                }
77284            }
77285        }
77286
77287        return true;
77288    }
77289
77290    function isValid$1() {
77291        return this._isValid;
77292    }
77293
77294    function createInvalid$1() {
77295        return createDuration(NaN);
77296    }
77297
77298    function Duration (duration) {
77299        var normalizedInput = normalizeObjectUnits(duration),
77300            years = normalizedInput.year || 0,
77301            quarters = normalizedInput.quarter || 0,
77302            months = normalizedInput.month || 0,
77303            weeks = normalizedInput.week || 0,
77304            days = normalizedInput.day || 0,
77305            hours = normalizedInput.hour || 0,
77306            minutes = normalizedInput.minute || 0,
77307            seconds = normalizedInput.second || 0,
77308            milliseconds = normalizedInput.millisecond || 0;
77309
77310        this._isValid = isDurationValid(normalizedInput);
77311
77312        // representation for dateAddRemove
77313        this._milliseconds = +milliseconds +
77314            seconds * 1e3 + // 1000
77315            minutes * 6e4 + // 1000 * 60
77316            hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
77317        // Because of dateAddRemove treats 24 hours as different from a
77318        // day when working around DST, we need to store them separately
77319        this._days = +days +
77320            weeks * 7;
77321        // It is impossible to translate months into days without knowing
77322        // which months you are are talking about, so we have to store
77323        // it separately.
77324        this._months = +months +
77325            quarters * 3 +
77326            years * 12;
77327
77328        this._data = {};
77329
77330        this._locale = getLocale();
77331
77332        this._bubble();
77333    }
77334
77335    function isDuration (obj) {
77336        return obj instanceof Duration;
77337    }
77338
77339    function absRound (number) {
77340        if (number < 0) {
77341            return Math.round(-1 * number) * -1;
77342        } else {
77343            return Math.round(number);
77344        }
77345    }
77346
77347    // FORMATTING
77348
77349    function offset (token, separator) {
77350        addFormatToken(token, 0, 0, function () {
77351            var offset = this.utcOffset();
77352            var sign = '+';
77353            if (offset < 0) {
77354                offset = -offset;
77355                sign = '-';
77356            }
77357            return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
77358        });
77359    }
77360
77361    offset('Z', ':');
77362    offset('ZZ', '');
77363
77364    // PARSING
77365
77366    addRegexToken('Z',  matchShortOffset);
77367    addRegexToken('ZZ', matchShortOffset);
77368    addParseToken(['Z', 'ZZ'], function (input, array, config) {
77369        config._useUTC = true;
77370        config._tzm = offsetFromString(matchShortOffset, input);
77371    });
77372
77373    // HELPERS
77374
77375    // timezone chunker
77376    // '+10:00' > ['10',  '00']
77377    // '-1530'  > ['-15', '30']
77378    var chunkOffset = /([\+\-]|\d\d)/gi;
77379
77380    function offsetFromString(matcher, string) {
77381        var matches = (string || '').match(matcher);
77382
77383        if (matches === null) {
77384            return null;
77385        }
77386
77387        var chunk   = matches[matches.length - 1] || [];
77388        var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
77389        var minutes = +(parts[1] * 60) + toInt(parts[2]);
77390
77391        return minutes === 0 ?
77392          0 :
77393          parts[0] === '+' ? minutes : -minutes;
77394    }
77395
77396    // Return a moment from input, that is local/utc/zone equivalent to model.
77397    function cloneWithOffset(input, model) {
77398        var res, diff;
77399        if (model._isUTC) {
77400            res = model.clone();
77401            diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();
77402            // Use low-level api, because this fn is low-level api.
77403            res._d.setTime(res._d.valueOf() + diff);
77404            hooks.updateOffset(res, false);
77405            return res;
77406        } else {
77407            return createLocal(input).local();
77408        }
77409    }
77410
77411    function getDateOffset (m) {
77412        // On Firefox.24 Date#getTimezoneOffset returns a floating point.
77413        // https://github.com/moment/moment/pull/1871
77414        return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
77415    }
77416
77417    // HOOKS
77418
77419    // This function will be called whenever a moment is mutated.
77420    // It is intended to keep the offset in sync with the timezone.
77421    hooks.updateOffset = function () {};
77422
77423    // MOMENTS
77424
77425    // keepLocalTime = true means only change the timezone, without
77426    // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
77427    // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
77428    // +0200, so we adjust the time as needed, to be valid.
77429    //
77430    // Keeping the time actually adds/subtracts (one hour)
77431    // from the actual represented time. That is why we call updateOffset
77432    // a second time. In case it wants us to change the offset again
77433    // _changeInProgress == true case, then we have to adjust, because
77434    // there is no such time in the given timezone.
77435    function getSetOffset (input, keepLocalTime, keepMinutes) {
77436        var offset = this._offset || 0,
77437            localAdjust;
77438        if (!this.isValid()) {
77439            return input != null ? this : NaN;
77440        }
77441        if (input != null) {
77442            if (typeof input === 'string') {
77443                input = offsetFromString(matchShortOffset, input);
77444                if (input === null) {
77445                    return this;
77446                }
77447            } else if (Math.abs(input) < 16 && !keepMinutes) {
77448                input = input * 60;
77449            }
77450            if (!this._isUTC && keepLocalTime) {
77451                localAdjust = getDateOffset(this);
77452            }
77453            this._offset = input;
77454            this._isUTC = true;
77455            if (localAdjust != null) {
77456                this.add(localAdjust, 'm');
77457            }
77458            if (offset !== input) {
77459                if (!keepLocalTime || this._changeInProgress) {
77460                    addSubtract(this, createDuration(input - offset, 'm'), 1, false);
77461                } else if (!this._changeInProgress) {
77462                    this._changeInProgress = true;
77463                    hooks.updateOffset(this, true);
77464                    this._changeInProgress = null;
77465                }
77466            }
77467            return this;
77468        } else {
77469            return this._isUTC ? offset : getDateOffset(this);
77470        }
77471    }
77472
77473    function getSetZone (input, keepLocalTime) {
77474        if (input != null) {
77475            if (typeof input !== 'string') {
77476                input = -input;
77477            }
77478
77479            this.utcOffset(input, keepLocalTime);
77480
77481            return this;
77482        } else {
77483            return -this.utcOffset();
77484        }
77485    }
77486
77487    function setOffsetToUTC (keepLocalTime) {
77488        return this.utcOffset(0, keepLocalTime);
77489    }
77490
77491    function setOffsetToLocal (keepLocalTime) {
77492        if (this._isUTC) {
77493            this.utcOffset(0, keepLocalTime);
77494            this._isUTC = false;
77495
77496            if (keepLocalTime) {
77497                this.subtract(getDateOffset(this), 'm');
77498            }
77499        }
77500        return this;
77501    }
77502
77503    function setOffsetToParsedOffset () {
77504        if (this._tzm != null) {
77505            this.utcOffset(this._tzm, false, true);
77506        } else if (typeof this._i === 'string') {
77507            var tZone = offsetFromString(matchOffset, this._i);
77508            if (tZone != null) {
77509                this.utcOffset(tZone);
77510            }
77511            else {
77512                this.utcOffset(0, true);
77513            }
77514        }
77515        return this;
77516    }
77517
77518    function hasAlignedHourOffset (input) {
77519        if (!this.isValid()) {
77520            return false;
77521        }
77522        input = input ? createLocal(input).utcOffset() : 0;
77523
77524        return (this.utcOffset() - input) % 60 === 0;
77525    }
77526
77527    function isDaylightSavingTime () {
77528        return (
77529            this.utcOffset() > this.clone().month(0).utcOffset() ||
77530            this.utcOffset() > this.clone().month(5).utcOffset()
77531        );
77532    }
77533
77534    function isDaylightSavingTimeShifted () {
77535        if (!isUndefined(this._isDSTShifted)) {
77536            return this._isDSTShifted;
77537        }
77538
77539        var c = {};
77540
77541        copyConfig(c, this);
77542        c = prepareConfig(c);
77543
77544        if (c._a) {
77545            var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
77546            this._isDSTShifted = this.isValid() &&
77547                compareArrays(c._a, other.toArray()) > 0;
77548        } else {
77549            this._isDSTShifted = false;
77550        }
77551
77552        return this._isDSTShifted;
77553    }
77554
77555    function isLocal () {
77556        return this.isValid() ? !this._isUTC : false;
77557    }
77558
77559    function isUtcOffset () {
77560        return this.isValid() ? this._isUTC : false;
77561    }
77562
77563    function isUtc () {
77564        return this.isValid() ? this._isUTC && this._offset === 0 : false;
77565    }
77566
77567    // ASP.NET json date format regex
77568    var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;
77569
77570    // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
77571    // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
77572    // and further modified to allow for strings containing both week and day
77573    var isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
77574
77575    function createDuration (input, key) {
77576        var duration = input,
77577            // matching against regexp is expensive, do it on demand
77578            match = null,
77579            sign,
77580            ret,
77581            diffRes;
77582
77583        if (isDuration(input)) {
77584            duration = {
77585                ms : input._milliseconds,
77586                d  : input._days,
77587                M  : input._months
77588            };
77589        } else if (isNumber(input)) {
77590            duration = {};
77591            if (key) {
77592                duration[key] = input;
77593            } else {
77594                duration.milliseconds = input;
77595            }
77596        } else if (!!(match = aspNetRegex.exec(input))) {
77597            sign = (match[1] === '-') ? -1 : 1;
77598            duration = {
77599                y  : 0,
77600                d  : toInt(match[DATE])                         * sign,
77601                h  : toInt(match[HOUR])                         * sign,
77602                m  : toInt(match[MINUTE])                       * sign,
77603                s  : toInt(match[SECOND])                       * sign,
77604                ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
77605            };
77606        } else if (!!(match = isoRegex.exec(input))) {
77607            sign = (match[1] === '-') ? -1 : (match[1] === '+') ? 1 : 1;
77608            duration = {
77609                y : parseIso(match[2], sign),
77610                M : parseIso(match[3], sign),
77611                w : parseIso(match[4], sign),
77612                d : parseIso(match[5], sign),
77613                h : parseIso(match[6], sign),
77614                m : parseIso(match[7], sign),
77615                s : parseIso(match[8], sign)
77616            };
77617        } else if (duration == null) {// checks for null or undefined
77618            duration = {};
77619        } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
77620            diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
77621
77622            duration = {};
77623            duration.ms = diffRes.milliseconds;
77624            duration.M = diffRes.months;
77625        }
77626
77627        ret = new Duration(duration);
77628
77629        if (isDuration(input) && hasOwnProp(input, '_locale')) {
77630            ret._locale = input._locale;
77631        }
77632
77633        return ret;
77634    }
77635
77636    createDuration.fn = Duration.prototype;
77637    createDuration.invalid = createInvalid$1;
77638
77639    function parseIso (inp, sign) {
77640        // We'd normally use ~~inp for this, but unfortunately it also
77641        // converts floats to ints.
77642        // inp may be undefined, so careful calling replace on it.
77643        var res = inp && parseFloat(inp.replace(',', '.'));
77644        // apply sign while we're at it
77645        return (isNaN(res) ? 0 : res) * sign;
77646    }
77647
77648    function positiveMomentsDifference(base, other) {
77649        var res = {milliseconds: 0, months: 0};
77650
77651        res.months = other.month() - base.month() +
77652            (other.year() - base.year()) * 12;
77653        if (base.clone().add(res.months, 'M').isAfter(other)) {
77654            --res.months;
77655        }
77656
77657        res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
77658
77659        return res;
77660    }
77661
77662    function momentsDifference(base, other) {
77663        var res;
77664        if (!(base.isValid() && other.isValid())) {
77665            return {milliseconds: 0, months: 0};
77666        }
77667
77668        other = cloneWithOffset(other, base);
77669        if (base.isBefore(other)) {
77670            res = positiveMomentsDifference(base, other);
77671        } else {
77672            res = positiveMomentsDifference(other, base);
77673            res.milliseconds = -res.milliseconds;
77674            res.months = -res.months;
77675        }
77676
77677        return res;
77678    }
77679
77680    // TODO: remove 'name' arg after deprecation is removed
77681    function createAdder(direction, name) {
77682        return function (val, period) {
77683            var dur, tmp;
77684            //invert the arguments, but complain about it
77685            if (period !== null && !isNaN(+period)) {
77686                deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' +
77687                'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
77688                tmp = val; val = period; period = tmp;
77689            }
77690
77691            val = typeof val === 'string' ? +val : val;
77692            dur = createDuration(val, period);
77693            addSubtract(this, dur, direction);
77694            return this;
77695        };
77696    }
77697
77698    function addSubtract (mom, duration, isAdding, updateOffset) {
77699        var milliseconds = duration._milliseconds,
77700            days = absRound(duration._days),
77701            months = absRound(duration._months);
77702
77703        if (!mom.isValid()) {
77704            // No op
77705            return;
77706        }
77707
77708        updateOffset = updateOffset == null ? true : updateOffset;
77709
77710        if (months) {
77711            setMonth(mom, get(mom, 'Month') + months * isAdding);
77712        }
77713        if (days) {
77714            set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
77715        }
77716        if (milliseconds) {
77717            mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
77718        }
77719        if (updateOffset) {
77720            hooks.updateOffset(mom, days || months);
77721        }
77722    }
77723
77724    var add      = createAdder(1, 'add');
77725    var subtract = createAdder(-1, 'subtract');
77726
77727    function getCalendarFormat(myMoment, now) {
77728        var diff = myMoment.diff(now, 'days', true);
77729        return diff < -6 ? 'sameElse' :
77730                diff < -1 ? 'lastWeek' :
77731                diff < 0 ? 'lastDay' :
77732                diff < 1 ? 'sameDay' :
77733                diff < 2 ? 'nextDay' :
77734                diff < 7 ? 'nextWeek' : 'sameElse';
77735    }
77736
77737    function calendar$1 (time, formats) {
77738        // We want to compare the start of today, vs this.
77739        // Getting start-of-today depends on whether we're local/utc/offset or not.
77740        var now = time || createLocal(),
77741            sod = cloneWithOffset(now, this).startOf('day'),
77742            format = hooks.calendarFormat(this, sod) || 'sameElse';
77743
77744        var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
77745
77746        return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
77747    }
77748
77749    function clone () {
77750        return new Moment(this);
77751    }
77752
77753    function isAfter (input, units) {
77754        var localInput = isMoment(input) ? input : createLocal(input);
77755        if (!(this.isValid() && localInput.isValid())) {
77756            return false;
77757        }
77758        units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
77759        if (units === 'millisecond') {
77760            return this.valueOf() > localInput.valueOf();
77761        } else {
77762            return localInput.valueOf() < this.clone().startOf(units).valueOf();
77763        }
77764    }
77765
77766    function isBefore (input, units) {
77767        var localInput = isMoment(input) ? input : createLocal(input);
77768        if (!(this.isValid() && localInput.isValid())) {
77769            return false;
77770        }
77771        units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
77772        if (units === 'millisecond') {
77773            return this.valueOf() < localInput.valueOf();
77774        } else {
77775            return this.clone().endOf(units).valueOf() < localInput.valueOf();
77776        }
77777    }
77778
77779    function isBetween (from, to, units, inclusivity) {
77780        inclusivity = inclusivity || '()';
77781        return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
77782            (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
77783    }
77784
77785    function isSame (input, units) {
77786        var localInput = isMoment(input) ? input : createLocal(input),
77787            inputMs;
77788        if (!(this.isValid() && localInput.isValid())) {
77789            return false;
77790        }
77791        units = normalizeUnits(units || 'millisecond');
77792        if (units === 'millisecond') {
77793            return this.valueOf() === localInput.valueOf();
77794        } else {
77795            inputMs = localInput.valueOf();
77796            return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
77797        }
77798    }
77799
77800    function isSameOrAfter (input, units) {
77801        return this.isSame(input, units) || this.isAfter(input,units);
77802    }
77803
77804    function isSameOrBefore (input, units) {
77805        return this.isSame(input, units) || this.isBefore(input,units);
77806    }
77807
77808    function diff (input, units, asFloat) {
77809        var that,
77810            zoneDelta,
77811            output;
77812
77813        if (!this.isValid()) {
77814            return NaN;
77815        }
77816
77817        that = cloneWithOffset(input, this);
77818
77819        if (!that.isValid()) {
77820            return NaN;
77821        }
77822
77823        zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
77824
77825        units = normalizeUnits(units);
77826
77827        switch (units) {
77828            case 'year': output = monthDiff(this, that) / 12; break;
77829            case 'month': output = monthDiff(this, that); break;
77830            case 'quarter': output = monthDiff(this, that) / 3; break;
77831            case 'second': output = (this - that) / 1e3; break; // 1000
77832            case 'minute': output = (this - that) / 6e4; break; // 1000 * 60
77833            case 'hour': output = (this - that) / 36e5; break; // 1000 * 60 * 60
77834            case 'day': output = (this - that - zoneDelta) / 864e5; break; // 1000 * 60 * 60 * 24, negate dst
77835            case 'week': output = (this - that - zoneDelta) / 6048e5; break; // 1000 * 60 * 60 * 24 * 7, negate dst
77836            default: output = this - that;
77837        }
77838
77839        return asFloat ? output : absFloor(output);
77840    }
77841
77842    function monthDiff (a, b) {
77843        // difference in months
77844        var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
77845            // b is in (anchor - 1 month, anchor + 1 month)
77846            anchor = a.clone().add(wholeMonthDiff, 'months'),
77847            anchor2, adjust;
77848
77849        if (b - anchor < 0) {
77850            anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
77851            // linear across the month
77852            adjust = (b - anchor) / (anchor - anchor2);
77853        } else {
77854            anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
77855            // linear across the month
77856            adjust = (b - anchor) / (anchor2 - anchor);
77857        }
77858
77859        //check for negative zero, return zero if negative zero
77860        return -(wholeMonthDiff + adjust) || 0;
77861    }
77862
77863    hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
77864    hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
77865
77866    function toString () {
77867        return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
77868    }
77869
77870    function toISOString(keepOffset) {
77871        if (!this.isValid()) {
77872            return null;
77873        }
77874        var utc = keepOffset !== true;
77875        var m = utc ? this.clone().utc() : this;
77876        if (m.year() < 0 || m.year() > 9999) {
77877            return formatMoment(m, utc ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ');
77878        }
77879        if (isFunction(Date.prototype.toISOString)) {
77880            // native implementation is ~50x faster, use it when we can
77881            if (utc) {
77882                return this.toDate().toISOString();
77883            } else {
77884                return new Date(this.valueOf() + this.utcOffset() * 60 * 1000).toISOString().replace('Z', formatMoment(m, 'Z'));
77885            }
77886        }
77887        return formatMoment(m, utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ');
77888    }
77889
77890    /**
77891     * Return a human readable representation of a moment that can
77892     * also be evaluated to get a new moment which is the same
77893     *
77894     * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
77895     */
77896    function inspect () {
77897        if (!this.isValid()) {
77898            return 'moment.invalid(/* ' + this._i + ' */)';
77899        }
77900        var func = 'moment';
77901        var zone = '';
77902        if (!this.isLocal()) {
77903            func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
77904            zone = 'Z';
77905        }
77906        var prefix = '[' + func + '("]';
77907        var year = (0 <= this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY';
77908        var datetime = '-MM-DD[T]HH:mm:ss.SSS';
77909        var suffix = zone + '[")]';
77910
77911        return this.format(prefix + year + datetime + suffix);
77912    }
77913
77914    function format (inputString) {
77915        if (!inputString) {
77916            inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
77917        }
77918        var output = formatMoment(this, inputString);
77919        return this.localeData().postformat(output);
77920    }
77921
77922    function from (time, withoutSuffix) {
77923        if (this.isValid() &&
77924                ((isMoment(time) && time.isValid()) ||
77925                 createLocal(time).isValid())) {
77926            return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
77927        } else {
77928            return this.localeData().invalidDate();
77929        }
77930    }
77931
77932    function fromNow (withoutSuffix) {
77933        return this.from(createLocal(), withoutSuffix);
77934    }
77935
77936    function to (time, withoutSuffix) {
77937        if (this.isValid() &&
77938                ((isMoment(time) && time.isValid()) ||
77939                 createLocal(time).isValid())) {
77940            return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
77941        } else {
77942            return this.localeData().invalidDate();
77943        }
77944    }
77945
77946    function toNow (withoutSuffix) {
77947        return this.to(createLocal(), withoutSuffix);
77948    }
77949
77950    // If passed a locale key, it will set the locale for this
77951    // instance.  Otherwise, it will return the locale configuration
77952    // variables for this instance.
77953    function locale (key) {
77954        var newLocaleData;
77955
77956        if (key === undefined) {
77957            return this._locale._abbr;
77958        } else {
77959            newLocaleData = getLocale(key);
77960            if (newLocaleData != null) {
77961                this._locale = newLocaleData;
77962            }
77963            return this;
77964        }
77965    }
77966
77967    var lang = deprecate(
77968        'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
77969        function (key) {
77970            if (key === undefined) {
77971                return this.localeData();
77972            } else {
77973                return this.locale(key);
77974            }
77975        }
77976    );
77977
77978    function localeData () {
77979        return this._locale;
77980    }
77981
77982    function startOf (units) {
77983        units = normalizeUnits(units);
77984        // the following switch intentionally omits break keywords
77985        // to utilize falling through the cases.
77986        switch (units) {
77987            case 'year':
77988                this.month(0);
77989                /* falls through */
77990            case 'quarter':
77991            case 'month':
77992                this.date(1);
77993                /* falls through */
77994            case 'week':
77995            case 'isoWeek':
77996            case 'day':
77997            case 'date':
77998                this.hours(0);
77999                /* falls through */
78000            case 'hour':
78001                this.minutes(0);
78002                /* falls through */
78003            case 'minute':
78004                this.seconds(0);
78005                /* falls through */
78006            case 'second':
78007                this.milliseconds(0);
78008        }
78009
78010        // weeks are a special case
78011        if (units === 'week') {
78012            this.weekday(0);
78013        }
78014        if (units === 'isoWeek') {
78015            this.isoWeekday(1);
78016        }
78017
78018        // quarters are also special
78019        if (units === 'quarter') {
78020            this.month(Math.floor(this.month() / 3) * 3);
78021        }
78022
78023        return this;
78024    }
78025
78026    function endOf (units) {
78027        units = normalizeUnits(units);
78028        if (units === undefined || units === 'millisecond') {
78029            return this;
78030        }
78031
78032        // 'date' is an alias for 'day', so it should be considered as such.
78033        if (units === 'date') {
78034            units = 'day';
78035        }
78036
78037        return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
78038    }
78039
78040    function valueOf () {
78041        return this._d.valueOf() - ((this._offset || 0) * 60000);
78042    }
78043
78044    function unix () {
78045        return Math.floor(this.valueOf() / 1000);
78046    }
78047
78048    function toDate () {
78049        return new Date(this.valueOf());
78050    }
78051
78052    function toArray () {
78053        var m = this;
78054        return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
78055    }
78056
78057    function toObject () {
78058        var m = this;
78059        return {
78060            years: m.year(),
78061            months: m.month(),
78062            date: m.date(),
78063            hours: m.hours(),
78064            minutes: m.minutes(),
78065            seconds: m.seconds(),
78066            milliseconds: m.milliseconds()
78067        };
78068    }
78069
78070    function toJSON () {
78071        // new Date(NaN).toJSON() === null
78072        return this.isValid() ? this.toISOString() : null;
78073    }
78074
78075    function isValid$2 () {
78076        return isValid(this);
78077    }
78078
78079    function parsingFlags () {
78080        return extend({}, getParsingFlags(this));
78081    }
78082
78083    function invalidAt () {
78084        return getParsingFlags(this).overflow;
78085    }
78086
78087    function creationData() {
78088        return {
78089            input: this._i,
78090            format: this._f,
78091            locale: this._locale,
78092            isUTC: this._isUTC,
78093            strict: this._strict
78094        };
78095    }
78096
78097    // FORMATTING
78098
78099    addFormatToken(0, ['gg', 2], 0, function () {
78100        return this.weekYear() % 100;
78101    });
78102
78103    addFormatToken(0, ['GG', 2], 0, function () {
78104        return this.isoWeekYear() % 100;
78105    });
78106
78107    function addWeekYearFormatToken (token, getter) {
78108        addFormatToken(0, [token, token.length], 0, getter);
78109    }
78110
78111    addWeekYearFormatToken('gggg',     'weekYear');
78112    addWeekYearFormatToken('ggggg',    'weekYear');
78113    addWeekYearFormatToken('GGGG',  'isoWeekYear');
78114    addWeekYearFormatToken('GGGGG', 'isoWeekYear');
78115
78116    // ALIASES
78117
78118    addUnitAlias('weekYear', 'gg');
78119    addUnitAlias('isoWeekYear', 'GG');
78120
78121    // PRIORITY
78122
78123    addUnitPriority('weekYear', 1);
78124    addUnitPriority('isoWeekYear', 1);
78125
78126
78127    // PARSING
78128
78129    addRegexToken('G',      matchSigned);
78130    addRegexToken('g',      matchSigned);
78131    addRegexToken('GG',     match1to2, match2);
78132    addRegexToken('gg',     match1to2, match2);
78133    addRegexToken('GGGG',   match1to4, match4);
78134    addRegexToken('gggg',   match1to4, match4);
78135    addRegexToken('GGGGG',  match1to6, match6);
78136    addRegexToken('ggggg',  match1to6, match6);
78137
78138    addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
78139        week[token.substr(0, 2)] = toInt(input);
78140    });
78141
78142    addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
78143        week[token] = hooks.parseTwoDigitYear(input);
78144    });
78145
78146    // MOMENTS
78147
78148    function getSetWeekYear (input) {
78149        return getSetWeekYearHelper.call(this,
78150                input,
78151                this.week(),
78152                this.weekday(),
78153                this.localeData()._week.dow,
78154                this.localeData()._week.doy);
78155    }
78156
78157    function getSetISOWeekYear (input) {
78158        return getSetWeekYearHelper.call(this,
78159                input, this.isoWeek(), this.isoWeekday(), 1, 4);
78160    }
78161
78162    function getISOWeeksInYear () {
78163        return weeksInYear(this.year(), 1, 4);
78164    }
78165
78166    function getWeeksInYear () {
78167        var weekInfo = this.localeData()._week;
78168        return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
78169    }
78170
78171    function getSetWeekYearHelper(input, week, weekday, dow, doy) {
78172        var weeksTarget;
78173        if (input == null) {
78174            return weekOfYear(this, dow, doy).year;
78175        } else {
78176            weeksTarget = weeksInYear(input, dow, doy);
78177            if (week > weeksTarget) {
78178                week = weeksTarget;
78179            }
78180            return setWeekAll.call(this, input, week, weekday, dow, doy);
78181        }
78182    }
78183
78184    function setWeekAll(weekYear, week, weekday, dow, doy) {
78185        var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
78186            date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
78187
78188        this.year(date.getUTCFullYear());
78189        this.month(date.getUTCMonth());
78190        this.date(date.getUTCDate());
78191        return this;
78192    }
78193
78194    // FORMATTING
78195
78196    addFormatToken('Q', 0, 'Qo', 'quarter');
78197
78198    // ALIASES
78199
78200    addUnitAlias('quarter', 'Q');
78201
78202    // PRIORITY
78203
78204    addUnitPriority('quarter', 7);
78205
78206    // PARSING
78207
78208    addRegexToken('Q', match1);
78209    addParseToken('Q', function (input, array) {
78210        array[MONTH] = (toInt(input) - 1) * 3;
78211    });
78212
78213    // MOMENTS
78214
78215    function getSetQuarter (input) {
78216        return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
78217    }
78218
78219    // FORMATTING
78220
78221    addFormatToken('D', ['DD', 2], 'Do', 'date');
78222
78223    // ALIASES
78224
78225    addUnitAlias('date', 'D');
78226
78227    // PRIORITY
78228    addUnitPriority('date', 9);
78229
78230    // PARSING
78231
78232    addRegexToken('D',  match1to2);
78233    addRegexToken('DD', match1to2, match2);
78234    addRegexToken('Do', function (isStrict, locale) {
78235        // TODO: Remove "ordinalParse" fallback in next major release.
78236        return isStrict ?
78237          (locale._dayOfMonthOrdinalParse || locale._ordinalParse) :
78238          locale._dayOfMonthOrdinalParseLenient;
78239    });
78240
78241    addParseToken(['D', 'DD'], DATE);
78242    addParseToken('Do', function (input, array) {
78243        array[DATE] = toInt(input.match(match1to2)[0]);
78244    });
78245
78246    // MOMENTS
78247
78248    var getSetDayOfMonth = makeGetSet('Date', true);
78249
78250    // FORMATTING
78251
78252    addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
78253
78254    // ALIASES
78255
78256    addUnitAlias('dayOfYear', 'DDD');
78257
78258    // PRIORITY
78259    addUnitPriority('dayOfYear', 4);
78260
78261    // PARSING
78262
78263    addRegexToken('DDD',  match1to3);
78264    addRegexToken('DDDD', match3);
78265    addParseToken(['DDD', 'DDDD'], function (input, array, config) {
78266        config._dayOfYear = toInt(input);
78267    });
78268
78269    // HELPERS
78270
78271    // MOMENTS
78272
78273    function getSetDayOfYear (input) {
78274        var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
78275        return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
78276    }
78277
78278    // FORMATTING
78279
78280    addFormatToken('m', ['mm', 2], 0, 'minute');
78281
78282    // ALIASES
78283
78284    addUnitAlias('minute', 'm');
78285
78286    // PRIORITY
78287
78288    addUnitPriority('minute', 14);
78289
78290    // PARSING
78291
78292    addRegexToken('m',  match1to2);
78293    addRegexToken('mm', match1to2, match2);
78294    addParseToken(['m', 'mm'], MINUTE);
78295
78296    // MOMENTS
78297
78298    var getSetMinute = makeGetSet('Minutes', false);
78299
78300    // FORMATTING
78301
78302    addFormatToken('s', ['ss', 2], 0, 'second');
78303
78304    // ALIASES
78305
78306    addUnitAlias('second', 's');
78307
78308    // PRIORITY
78309
78310    addUnitPriority('second', 15);
78311
78312    // PARSING
78313
78314    addRegexToken('s',  match1to2);
78315    addRegexToken('ss', match1to2, match2);
78316    addParseToken(['s', 'ss'], SECOND);
78317
78318    // MOMENTS
78319
78320    var getSetSecond = makeGetSet('Seconds', false);
78321
78322    // FORMATTING
78323
78324    addFormatToken('S', 0, 0, function () {
78325        return ~~(this.millisecond() / 100);
78326    });
78327
78328    addFormatToken(0, ['SS', 2], 0, function () {
78329        return ~~(this.millisecond() / 10);
78330    });
78331
78332    addFormatToken(0, ['SSS', 3], 0, 'millisecond');
78333    addFormatToken(0, ['SSSS', 4], 0, function () {
78334        return this.millisecond() * 10;
78335    });
78336    addFormatToken(0, ['SSSSS', 5], 0, function () {
78337        return this.millisecond() * 100;
78338    });
78339    addFormatToken(0, ['SSSSSS', 6], 0, function () {
78340        return this.millisecond() * 1000;
78341    });
78342    addFormatToken(0, ['SSSSSSS', 7], 0, function () {
78343        return this.millisecond() * 10000;
78344    });
78345    addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
78346        return this.millisecond() * 100000;
78347    });
78348    addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
78349        return this.millisecond() * 1000000;
78350    });
78351
78352
78353    // ALIASES
78354
78355    addUnitAlias('millisecond', 'ms');
78356
78357    // PRIORITY
78358
78359    addUnitPriority('millisecond', 16);
78360
78361    // PARSING
78362
78363    addRegexToken('S',    match1to3, match1);
78364    addRegexToken('SS',   match1to3, match2);
78365    addRegexToken('SSS',  match1to3, match3);
78366
78367    var token;
78368    for (token = 'SSSS'; token.length <= 9; token += 'S') {
78369        addRegexToken(token, matchUnsigned);
78370    }
78371
78372    function parseMs(input, array) {
78373        array[MILLISECOND] = toInt(('0.' + input) * 1000);
78374    }
78375
78376    for (token = 'S'; token.length <= 9; token += 'S') {
78377        addParseToken(token, parseMs);
78378    }
78379    // MOMENTS
78380
78381    var getSetMillisecond = makeGetSet('Milliseconds', false);
78382
78383    // FORMATTING
78384
78385    addFormatToken('z',  0, 0, 'zoneAbbr');
78386    addFormatToken('zz', 0, 0, 'zoneName');
78387
78388    // MOMENTS
78389
78390    function getZoneAbbr () {
78391        return this._isUTC ? 'UTC' : '';
78392    }
78393
78394    function getZoneName () {
78395        return this._isUTC ? 'Coordinated Universal Time' : '';
78396    }
78397
78398    var proto = Moment.prototype;
78399
78400    proto.add               = add;
78401    proto.calendar          = calendar$1;
78402    proto.clone             = clone;
78403    proto.diff              = diff;
78404    proto.endOf             = endOf;
78405    proto.format            = format;
78406    proto.from              = from;
78407    proto.fromNow           = fromNow;
78408    proto.to                = to;
78409    proto.toNow             = toNow;
78410    proto.get               = stringGet;
78411    proto.invalidAt         = invalidAt;
78412    proto.isAfter           = isAfter;
78413    proto.isBefore          = isBefore;
78414    proto.isBetween         = isBetween;
78415    proto.isSame            = isSame;
78416    proto.isSameOrAfter     = isSameOrAfter;
78417    proto.isSameOrBefore    = isSameOrBefore;
78418    proto.isValid           = isValid$2;
78419    proto.lang              = lang;
78420    proto.locale            = locale;
78421    proto.localeData        = localeData;
78422    proto.max               = prototypeMax;
78423    proto.min               = prototypeMin;
78424    proto.parsingFlags      = parsingFlags;
78425    proto.set               = stringSet;
78426    proto.startOf           = startOf;
78427    proto.subtract          = subtract;
78428    proto.toArray           = toArray;
78429    proto.toObject          = toObject;
78430    proto.toDate            = toDate;
78431    proto.toISOString       = toISOString;
78432    proto.inspect           = inspect;
78433    proto.toJSON            = toJSON;
78434    proto.toString          = toString;
78435    proto.unix              = unix;
78436    proto.valueOf           = valueOf;
78437    proto.creationData      = creationData;
78438    proto.year       = getSetYear;
78439    proto.isLeapYear = getIsLeapYear;
78440    proto.weekYear    = getSetWeekYear;
78441    proto.isoWeekYear = getSetISOWeekYear;
78442    proto.quarter = proto.quarters = getSetQuarter;
78443    proto.month       = getSetMonth;
78444    proto.daysInMonth = getDaysInMonth;
78445    proto.week           = proto.weeks        = getSetWeek;
78446    proto.isoWeek        = proto.isoWeeks     = getSetISOWeek;
78447    proto.weeksInYear    = getWeeksInYear;
78448    proto.isoWeeksInYear = getISOWeeksInYear;
78449    proto.date       = getSetDayOfMonth;
78450    proto.day        = proto.days             = getSetDayOfWeek;
78451    proto.weekday    = getSetLocaleDayOfWeek;
78452    proto.isoWeekday = getSetISODayOfWeek;
78453    proto.dayOfYear  = getSetDayOfYear;
78454    proto.hour = proto.hours = getSetHour;
78455    proto.minute = proto.minutes = getSetMinute;
78456    proto.second = proto.seconds = getSetSecond;
78457    proto.millisecond = proto.milliseconds = getSetMillisecond;
78458    proto.utcOffset            = getSetOffset;
78459    proto.utc                  = setOffsetToUTC;
78460    proto.local                = setOffsetToLocal;
78461    proto.parseZone            = setOffsetToParsedOffset;
78462    proto.hasAlignedHourOffset = hasAlignedHourOffset;
78463    proto.isDST                = isDaylightSavingTime;
78464    proto.isLocal              = isLocal;
78465    proto.isUtcOffset          = isUtcOffset;
78466    proto.isUtc                = isUtc;
78467    proto.isUTC                = isUtc;
78468    proto.zoneAbbr = getZoneAbbr;
78469    proto.zoneName = getZoneName;
78470    proto.dates  = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
78471    proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
78472    proto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);
78473    proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
78474    proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);
78475
78476    function createUnix (input) {
78477        return createLocal(input * 1000);
78478    }
78479
78480    function createInZone () {
78481        return createLocal.apply(null, arguments).parseZone();
78482    }
78483
78484    function preParsePostFormat (string) {
78485        return string;
78486    }
78487
78488    var proto$1 = Locale.prototype;
78489
78490    proto$1.calendar        = calendar;
78491    proto$1.longDateFormat  = longDateFormat;
78492    proto$1.invalidDate     = invalidDate;
78493    proto$1.ordinal         = ordinal;
78494    proto$1.preparse        = preParsePostFormat;
78495    proto$1.postformat      = preParsePostFormat;
78496    proto$1.relativeTime    = relativeTime;
78497    proto$1.pastFuture      = pastFuture;
78498    proto$1.set             = set;
78499
78500    proto$1.months            =        localeMonths;
78501    proto$1.monthsShort       =        localeMonthsShort;
78502    proto$1.monthsParse       =        localeMonthsParse;
78503    proto$1.monthsRegex       = monthsRegex;
78504    proto$1.monthsShortRegex  = monthsShortRegex;
78505    proto$1.week = localeWeek;
78506    proto$1.firstDayOfYear = localeFirstDayOfYear;
78507    proto$1.firstDayOfWeek = localeFirstDayOfWeek;
78508
78509    proto$1.weekdays       =        localeWeekdays;
78510    proto$1.weekdaysMin    =        localeWeekdaysMin;
78511    proto$1.weekdaysShort  =        localeWeekdaysShort;
78512    proto$1.weekdaysParse  =        localeWeekdaysParse;
78513
78514    proto$1.weekdaysRegex       =        weekdaysRegex;
78515    proto$1.weekdaysShortRegex  =        weekdaysShortRegex;
78516    proto$1.weekdaysMinRegex    =        weekdaysMinRegex;
78517
78518    proto$1.isPM = localeIsPM;
78519    proto$1.meridiem = localeMeridiem;
78520
78521    function get$1 (format, index, field, setter) {
78522        var locale = getLocale();
78523        var utc = createUTC().set(setter, index);
78524        return locale[field](utc, format);
78525    }
78526
78527    function listMonthsImpl (format, index, field) {
78528        if (isNumber(format)) {
78529            index = format;
78530            format = undefined;
78531        }
78532
78533        format = format || '';
78534
78535        if (index != null) {
78536            return get$1(format, index, field, 'month');
78537        }
78538
78539        var i;
78540        var out = [];
78541        for (i = 0; i < 12; i++) {
78542            out[i] = get$1(format, i, field, 'month');
78543        }
78544        return out;
78545    }
78546
78547    // ()
78548    // (5)
78549    // (fmt, 5)
78550    // (fmt)
78551    // (true)
78552    // (true, 5)
78553    // (true, fmt, 5)
78554    // (true, fmt)
78555    function listWeekdaysImpl (localeSorted, format, index, field) {
78556        if (typeof localeSorted === 'boolean') {
78557            if (isNumber(format)) {
78558                index = format;
78559                format = undefined;
78560            }
78561
78562            format = format || '';
78563        } else {
78564            format = localeSorted;
78565            index = format;
78566            localeSorted = false;
78567
78568            if (isNumber(format)) {
78569                index = format;
78570                format = undefined;
78571            }
78572
78573            format = format || '';
78574        }
78575
78576        var locale = getLocale(),
78577            shift = localeSorted ? locale._week.dow : 0;
78578
78579        if (index != null) {
78580            return get$1(format, (index + shift) % 7, field, 'day');
78581        }
78582
78583        var i;
78584        var out = [];
78585        for (i = 0; i < 7; i++) {
78586            out[i] = get$1(format, (i + shift) % 7, field, 'day');
78587        }
78588        return out;
78589    }
78590
78591    function listMonths (format, index) {
78592        return listMonthsImpl(format, index, 'months');
78593    }
78594
78595    function listMonthsShort (format, index) {
78596        return listMonthsImpl(format, index, 'monthsShort');
78597    }
78598
78599    function listWeekdays (localeSorted, format, index) {
78600        return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
78601    }
78602
78603    function listWeekdaysShort (localeSorted, format, index) {
78604        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
78605    }
78606
78607    function listWeekdaysMin (localeSorted, format, index) {
78608        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
78609    }
78610
78611    getSetGlobalLocale('en', {
78612        dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
78613        ordinal : function (number) {
78614            var b = number % 10,
78615                output = (toInt(number % 100 / 10) === 1) ? 'th' :
78616                (b === 1) ? 'st' :
78617                (b === 2) ? 'nd' :
78618                (b === 3) ? 'rd' : 'th';
78619            return number + output;
78620        }
78621    });
78622
78623    // Side effect imports
78624
78625    hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);
78626    hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);
78627
78628    var mathAbs = Math.abs;
78629
78630    function abs () {
78631        var data           = this._data;
78632
78633        this._milliseconds = mathAbs(this._milliseconds);
78634        this._days         = mathAbs(this._days);
78635        this._months       = mathAbs(this._months);
78636
78637        data.milliseconds  = mathAbs(data.milliseconds);
78638        data.seconds       = mathAbs(data.seconds);
78639        data.minutes       = mathAbs(data.minutes);
78640        data.hours         = mathAbs(data.hours);
78641        data.months        = mathAbs(data.months);
78642        data.years         = mathAbs(data.years);
78643
78644        return this;
78645    }
78646
78647    function addSubtract$1 (duration, input, value, direction) {
78648        var other = createDuration(input, value);
78649
78650        duration._milliseconds += direction * other._milliseconds;
78651        duration._days         += direction * other._days;
78652        duration._months       += direction * other._months;
78653
78654        return duration._bubble();
78655    }
78656
78657    // supports only 2.0-style add(1, 's') or add(duration)
78658    function add$1 (input, value) {
78659        return addSubtract$1(this, input, value, 1);
78660    }
78661
78662    // supports only 2.0-style subtract(1, 's') or subtract(duration)
78663    function subtract$1 (input, value) {
78664        return addSubtract$1(this, input, value, -1);
78665    }
78666
78667    function absCeil (number) {
78668        if (number < 0) {
78669            return Math.floor(number);
78670        } else {
78671            return Math.ceil(number);
78672        }
78673    }
78674
78675    function bubble () {
78676        var milliseconds = this._milliseconds;
78677        var days         = this._days;
78678        var months       = this._months;
78679        var data         = this._data;
78680        var seconds, minutes, hours, years, monthsFromDays;
78681
78682        // if we have a mix of positive and negative values, bubble down first
78683        // check: https://github.com/moment/moment/issues/2166
78684        if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
78685                (milliseconds <= 0 && days <= 0 && months <= 0))) {
78686            milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
78687            days = 0;
78688            months = 0;
78689        }
78690
78691        // The following code bubbles up values, see the tests for
78692        // examples of what that means.
78693        data.milliseconds = milliseconds % 1000;
78694
78695        seconds           = absFloor(milliseconds / 1000);
78696        data.seconds      = seconds % 60;
78697
78698        minutes           = absFloor(seconds / 60);
78699        data.minutes      = minutes % 60;
78700
78701        hours             = absFloor(minutes / 60);
78702        data.hours        = hours % 24;
78703
78704        days += absFloor(hours / 24);
78705
78706        // convert days to months
78707        monthsFromDays = absFloor(daysToMonths(days));
78708        months += monthsFromDays;
78709        days -= absCeil(monthsToDays(monthsFromDays));
78710
78711        // 12 months -> 1 year
78712        years = absFloor(months / 12);
78713        months %= 12;
78714
78715        data.days   = days;
78716        data.months = months;
78717        data.years  = years;
78718
78719        return this;
78720    }
78721
78722    function daysToMonths (days) {
78723        // 400 years have 146097 days (taking into account leap year rules)
78724        // 400 years have 12 months === 4800
78725        return days * 4800 / 146097;
78726    }
78727
78728    function monthsToDays (months) {
78729        // the reverse of daysToMonths
78730        return months * 146097 / 4800;
78731    }
78732
78733    function as (units) {
78734        if (!this.isValid()) {
78735            return NaN;
78736        }
78737        var days;
78738        var months;
78739        var milliseconds = this._milliseconds;
78740
78741        units = normalizeUnits(units);
78742
78743        if (units === 'month' || units === 'year') {
78744            days   = this._days   + milliseconds / 864e5;
78745            months = this._months + daysToMonths(days);
78746            return units === 'month' ? months : months / 12;
78747        } else {
78748            // handle milliseconds separately because of floating point math errors (issue #1867)
78749            days = this._days + Math.round(monthsToDays(this._months));
78750            switch (units) {
78751                case 'week'   : return days / 7     + milliseconds / 6048e5;
78752                case 'day'    : return days         + milliseconds / 864e5;
78753                case 'hour'   : return days * 24    + milliseconds / 36e5;
78754                case 'minute' : return days * 1440  + milliseconds / 6e4;
78755                case 'second' : return days * 86400 + milliseconds / 1000;
78756                // Math.floor prevents floating point math errors here
78757                case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
78758                default: throw new Error('Unknown unit ' + units);
78759            }
78760        }
78761    }
78762
78763    // TODO: Use this.as('ms')?
78764    function valueOf$1 () {
78765        if (!this.isValid()) {
78766            return NaN;
78767        }
78768        return (
78769            this._milliseconds +
78770            this._days * 864e5 +
78771            (this._months % 12) * 2592e6 +
78772            toInt(this._months / 12) * 31536e6
78773        );
78774    }
78775
78776    function makeAs (alias) {
78777        return function () {
78778            return this.as(alias);
78779        };
78780    }
78781
78782    var asMilliseconds = makeAs('ms');
78783    var asSeconds      = makeAs('s');
78784    var asMinutes      = makeAs('m');
78785    var asHours        = makeAs('h');
78786    var asDays         = makeAs('d');
78787    var asWeeks        = makeAs('w');
78788    var asMonths       = makeAs('M');
78789    var asYears        = makeAs('y');
78790
78791    function clone$1 () {
78792        return createDuration(this);
78793    }
78794
78795    function get$2 (units) {
78796        units = normalizeUnits(units);
78797        return this.isValid() ? this[units + 's']() : NaN;
78798    }
78799
78800    function makeGetter(name) {
78801        return function () {
78802            return this.isValid() ? this._data[name] : NaN;
78803        };
78804    }
78805
78806    var milliseconds = makeGetter('milliseconds');
78807    var seconds      = makeGetter('seconds');
78808    var minutes      = makeGetter('minutes');
78809    var hours        = makeGetter('hours');
78810    var days         = makeGetter('days');
78811    var months       = makeGetter('months');
78812    var years        = makeGetter('years');
78813
78814    function weeks () {
78815        return absFloor(this.days() / 7);
78816    }
78817
78818    var round = Math.round;
78819    var thresholds = {
78820        ss: 44,         // a few seconds to seconds
78821        s : 45,         // seconds to minute
78822        m : 45,         // minutes to hour
78823        h : 22,         // hours to day
78824        d : 26,         // days to month
78825        M : 11          // months to year
78826    };
78827
78828    // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
78829    function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
78830        return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
78831    }
78832
78833    function relativeTime$1 (posNegDuration, withoutSuffix, locale) {
78834        var duration = createDuration(posNegDuration).abs();
78835        var seconds  = round(duration.as('s'));
78836        var minutes  = round(duration.as('m'));
78837        var hours    = round(duration.as('h'));
78838        var days     = round(duration.as('d'));
78839        var months   = round(duration.as('M'));
78840        var years    = round(duration.as('y'));
78841
78842        var a = seconds <= thresholds.ss && ['s', seconds]  ||
78843                seconds < thresholds.s   && ['ss', seconds] ||
78844                minutes <= 1             && ['m']           ||
78845                minutes < thresholds.m   && ['mm', minutes] ||
78846                hours   <= 1             && ['h']           ||
78847                hours   < thresholds.h   && ['hh', hours]   ||
78848                days    <= 1             && ['d']           ||
78849                days    < thresholds.d   && ['dd', days]    ||
78850                months  <= 1             && ['M']           ||
78851                months  < thresholds.M   && ['MM', months]  ||
78852                years   <= 1             && ['y']           || ['yy', years];
78853
78854        a[2] = withoutSuffix;
78855        a[3] = +posNegDuration > 0;
78856        a[4] = locale;
78857        return substituteTimeAgo.apply(null, a);
78858    }
78859
78860    // This function allows you to set the rounding function for relative time strings
78861    function getSetRelativeTimeRounding (roundingFunction) {
78862        if (roundingFunction === undefined) {
78863            return round;
78864        }
78865        if (typeof(rou
vendor: 9,335 bytes, lines 78865-79162
78865ndingFunction) === 'function') {
78866            round = roundingFunction;
78867            return true;
78868        }
78869        return false;
78870    }
78871
78872    // This function allows you to set a threshold for relative time strings
78873    function getSetRelativeTimeThreshold (threshold, limit) {
78874        if (thresholds[threshold] === undefined) {
78875            return false;
78876        }
78877        if (limit === undefined) {
78878            return thresholds[threshold];
78879        }
78880        thresholds[threshold] = limit;
78881        if (threshold === 's') {
78882            thresholds.ss = limit - 1;
78883        }
78884        return true;
78885    }
78886
78887    function humanize (withSuffix) {
78888        if (!this.isValid()) {
78889            return this.localeData().invalidDate();
78890        }
78891
78892        var locale = this.localeData();
78893        var output = relativeTime$1(this, !withSuffix, locale);
78894
78895        if (withSuffix) {
78896            output = locale.pastFuture(+this, output);
78897        }
78898
78899        return locale.postformat(output);
78900    }
78901
78902    var abs$1 = Math.abs;
78903
78904    function sign(x) {
78905        return ((x > 0) - (x < 0)) || +x;
78906    }
78907
78908    function toISOString$1() {
78909        // for ISO strings we do not use the normal bubbling rules:
78910        //  * milliseconds bubble up until they become hours
78911        //  * days do not bubble at all
78912        //  * months bubble up until they become years
78913        // This is because there is no context-free conversion between hours and days
78914        // (think of clock changes)
78915        // and also not between days and months (28-31 days per month)
78916        if (!this.isValid()) {
78917            return this.localeData().invalidDate();
78918        }
78919
78920        var seconds = abs$1(this._milliseconds) / 1000;
78921        var days         = abs$1(this._days);
78922        var months       = abs$1(this._months);
78923        var minutes, hours, years;
78924
78925        // 3600 seconds -> 60 minutes -> 1 hour
78926        minutes           = absFloor(seconds / 60);
78927        hours             = absFloor(minutes / 60);
78928        seconds %= 60;
78929        minutes %= 60;
78930
78931        // 12 months -> 1 year
78932        years  = absFloor(months / 12);
78933        months %= 12;
78934
78935
78936        // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
78937        var Y = years;
78938        var M = months;
78939        var D = days;
78940        var h = hours;
78941        var m = minutes;
78942        var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
78943        var total = this.asSeconds();
78944
78945        if (!total) {
78946            // this is the same as C#'s (Noda) and python (isodate)...
78947            // but not other JS (goog.date)
78948            return 'P0D';
78949        }
78950
78951        var totalSign = total < 0 ? '-' : '';
78952        var ymSign = sign(this._months) !== sign(total) ? '-' : '';
78953        var daysSign = sign(this._days) !== sign(total) ? '-' : '';
78954        var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
78955
78956        return totalSign + 'P' +
78957            (Y ? ymSign + Y + 'Y' : '') +
78958            (M ? ymSign + M + 'M' : '') +
78959            (D ? daysSign + D + 'D' : '') +
78960            ((h || m || s) ? 'T' : '') +
78961            (h ? hmsSign + h + 'H' : '') +
78962            (m ? hmsSign + m + 'M' : '') +
78963            (s ? hmsSign + s + 'S' : '');
78964    }
78965
78966    var proto$2 = Duration.prototype;
78967
78968    proto$2.isValid        = isValid$1;
78969    proto$2.abs            = abs;
78970    proto$2.add            = add$1;
78971    proto$2.subtract       = subtract$1;
78972    proto$2.as             = as;
78973    proto$2.asMilliseconds = asMilliseconds;
78974    proto$2.asSeconds      = asSeconds;
78975    proto$2.asMinutes      = asMinutes;
78976    proto$2.asHours        = asHours;
78977    proto$2.asDays         = asDays;
78978    proto$2.asWeeks        = asWeeks;
78979    proto$2.asMonths       = asMonths;
78980    proto$2.asYears        = asYears;
78981    proto$2.valueOf        = valueOf$1;
78982    proto$2._bubble        = bubble;
78983    proto$2.clone          = clone$1;
78984    proto$2.get            = get$2;
78985    proto$2.milliseconds   = milliseconds;
78986    proto$2.seconds        = seconds;
78987    proto$2.minutes        = minutes;
78988    proto$2.hours          = hours;
78989    proto$2.days           = days;
78990    proto$2.weeks          = weeks;
78991    proto$2.months         = months;
78992    proto$2.years          = years;
78993    proto$2.humanize       = humanize;
78994    proto$2.toISOString    = toISOString$1;
78995    proto$2.toString       = toISOString$1;
78996    proto$2.toJSON         = toISOString$1;
78997    proto$2.locale         = locale;
78998    proto$2.localeData     = localeData;
78999
79000    proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);
79001    proto$2.lang = lang;
79002
79003    // Side effect imports
79004
79005    // FORMATTING
79006
79007    addFormatToken('X', 0, 0, 'unix');
79008    addFormatToken('x', 0, 0, 'valueOf');
79009
79010    // PARSING
79011
79012    addRegexToken('x', matchSigned);
79013    addRegexToken('X', matchTimestamp);
79014    addParseToken('X', function (input, array, config) {
79015        config._d = new Date(parseFloat(input, 10) * 1000);
79016    });
79017    addParseToken('x', function (input, array, config) {
79018        config._d = new Date(toInt(input));
79019    });
79020
79021    // Side effect imports
79022
79023
79024    hooks.version = '2.22.2';
79025
79026    setHookCallback(createLocal);
79027
79028    hooks.fn                    = proto;
79029    hooks.min                   = min;
79030    hooks.max                   = max;
79031    hooks.now                   = now;
79032    hooks.utc                   = createUTC;
79033    hooks.unix                  = createUnix;
79034    hooks.months                = listMonths;
79035    hooks.isDate                = isDate;
79036    hooks.locale                = getSetGlobalLocale;
79037    hooks.invalid               = createInvalid;
79038    hooks.duration              = createDuration;
79039    hooks.isMoment              = isMoment;
79040    hooks.weekdays              = listWeekdays;
79041    hooks.parseZone             = createInZone;
79042    hooks.localeData            = getLocale;
79043    hooks.isDuration            = isDuration;
79044    hooks.monthsShort           = listMonthsShort;
79045    hooks.weekdaysMin           = listWeekdaysMin;
79046    hooks.defineLocale          = defineLocale;
79047    hooks.updateLocale          = updateLocale;
79048    hooks.locales               = listLocales;
79049    hooks.weekdaysShort         = listWeekdaysShort;
79050    hooks.normalizeUnits        = normalizeUnits;
79051    hooks.relativeTimeRounding  = getSetRelativeTimeRounding;
79052    hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
79053    hooks.calendarFormat        = getCalendarFormat;
79054    hooks.prototype             = proto;
79055
79056    // currently HTML5 input type only supports 24-hour formats
79057    hooks.HTML5_FMT = {
79058        DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm',             // <input type="datetime-local" />
79059        DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss',  // <input type="datetime-local" step="1" />
79060        DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS',   // <input type="datetime-local" step="0.001" />
79061        DATE: 'YYYY-MM-DD',                             // <input type="date" />
79062        TIME: 'HH:mm',                                  // <input type="time" />
79063        TIME_SECONDS: 'HH:mm:ss',                       // <input type="time" step="1" />
79064        TIME_MS: 'HH:mm:ss.SSS',                        // <input type="time" step="0.001" />
79065        WEEK: 'YYYY-[W]WW',                             // <input type="week" />
79066        MONTH: 'YYYY-MM'                                // <input type="month" />
79067    };
79068
79069    return hooks;
79070
79071})));
79072
79073},{}],7:[function(require,module,exports){
79074/**
79075 * @namespace Chart
79076 */
79077var Chart = require(30)();
79078
79079Chart.helpers = require(46);
79080
79081// @todo dispatch these helpers into appropriated helpers/helpers.* file and write unit tests!
79082require(28)(Chart);
79083
79084Chart.Animation = require(22);
79085Chart.animationService = require(23);
79086Chart.defaults = require(26);
79087Chart.Element = require(27);
79088Chart.elements = require(41);
79089Chart.Interaction = require(29);
79090Chart.layouts = require(31);
79091Chart.platform = require(49);
79092Chart.plugins = require(32);
79093Chart.Scale = require(33);
79094Chart.scaleService = require(34);
79095Chart.Ticks = require(35);
79096Chart.Tooltip = require(36);
79097
79098require(24)(Chart);
79099require(25)(Chart);
79100
79101require(56)(Chart);
79102require(54)(Chart);
79103require(55)(Chart);
79104require(57)(Chart);
79105require(58)(Chart);
79106require(59)(Chart);
79107
79108// Controllers must be loaded after elements
79109// See Chart.core.datasetController.dataElementType
79110require(15)(Chart);
79111require(16)(Chart);
79112require(17)(Chart);
79113require(18)(Chart);
79114require(19)(Chart);
79115require(20)(Chart);
79116require(21)(Chart);
79117
79118require(8)(Chart);
79119require(9)(Chart);
79120require(10)(Chart);
79121require(11)(Chart);
79122require(12)(Chart);
79123require(13)(Chart);
79124require(14)(Chart);
79125
79126// Loading built-in plugins
79127var plugins = require(50);
79128for (var k in plugins) {
79129	if (plugins.hasOwnProperty(k)) {
79130		Chart.plugins.register(plugins[k]);
79131	}
79132}
79133
79134Chart.platform.initialize();
79135
79136module.exports = Chart;
79137if (typeof window !== 'undefined') {
79138	window.Chart = Chart;
79139}
79140
79141// DEPRECATIONS
79142
79143/**
79144 * Provided for backward compatibility, not available anymore
79145 * @namespace Chart.Legend
79146 * @deprecated since version 2.1.5
79147 * @todo remove at version 3
79148 * @private
79149 */
79150Chart.Legend = plugins.legend._element;
79151
79152/**
79153 * Provided for backward compatibility, not available anymore
79154 * @namespace Chart.Title
79155 * @deprecated since version 2.1.5
79156 * @todo remove at version 3
79157 * @private
79158 */
79159Chart.Title = plugins.title._element;
79160
79161/**
79162 * Provided for backward compatibility, use Chart.plugins instead
79163 * @namespace Chart.pluginService
79164 * @deprecated since version 2.1.5
79165 * @todo remove at version 3
79166 * @private
79167 */
79168Chart.pluginService = Chart.plugins;
79169
79170/**
79171 * Provided for backward compatibility, inheriting from Chart.PlugingBase has no
79172 * effect, instead simply create/register plugins via plain JavaScript objects.
79173 * @interface Chart.PluginBase
79174 * @deprecated since version 2.5.0
79175 * @todo remove at version 3
79176 * @private
79177 */
79178Chart.PluginBase = Chart.Element.extend({});
79179
79180/**
79181 * Provided for backward compatibility, use Chart.helpers.canvas instead.
79182 * @namespace Chart.canvasHelpers
79183 * @deprecated since version 2.6.0
79184 * @todo remove at version 3
79185 * @private
79186 */
79187Chart.canvasHelpers = Chart.helpers.canvas;
79188
79189/**
79190 * Provided for backward compatibility, use Chart.layouts instead.
79191 * @namespace Chart.layoutService
79192 * @deprecated since version 2.8.0
79193 * @todo remove at version 3
79194 * @private
79195 */
79196Chart.layoutService = Chart.layouts;
79197
79198},{"10":10,"11":11,"12":12,"13":13,"14":14,"15":15,"16":16,"17":17,"18":18,"19":19,"20":20,"21":21,"22":22,"23":23,"24":24,"25":25,"26":26,"27":27,"28":28,"29":29,"30":30,"31":31,"32":32,"33":33,"34":34,"35":35,"36":36,"41":41,"46":46,"49":49,"50":50,"54":54,"55":55,"56":56,"57":57,"58":58,"59":59,"8":8,"9":9}],8:[function(require,module,exports){
79199'use strict';
79200
79201module.exports = function(Chart) {
79202
79203	Chart.Bar = function(context, config) {
79204		config.type = 'bar';
79205
79206		return new Chart(context, config);
79207	};
79208
79209};
79210
79211},{}],9:[function(require,module,exports){
79212'use strict';
79213
79214module.exports = function(Chart) {
79215
79216	Chart.Bubble = function(context, config) {
79217		config.type = 'bubble';
79218		return new Chart(context, config);
79219	};
79220
79221};
79222
79223},{}],10:[function(require,module,exports){
79224'use strict';
79225
79226module.exports = function(Chart) {
79227
79228	Chart.Doughnut = function(context, config) {
79229		config.type = 'doughnut';
79230
79231		return new Chart(context, config);
79232	};
79233
79234};
79235
79236},{}],11:[function(require,module,exports){
79237'use strict';
79238
79239module.exports = function(Chart) {
79240
79241	Chart.Line = function(context, config) {
79242		config.type = 'line';
79243
79244		return new Chart(context, config);
79245	};
79246
79247};
79248
79249},{}],12:[function(require,module,exports){
79250'use strict';
79251
79252module.exports = function(Chart) {
79253
79254	Chart.PolarArea = function(context, config) {
79255		config.type = 'polarArea';
79256
79257		return new Chart(context, config);
79258	};
79259
79260};
79261
79262},{}],13:[function(require,module,exports){
79263'use strict';
79264
79265module.exports = function(Chart) {
79266
79267	Chart.Radar = function(context, config) {
79268		config.type = 'radar';
79269
79270		return new Chart(context, config);
79271	};
79272
79273};
79274
79275},{}],14:[function(require,module,exports){
79276'use strict';
79277
79278module.exports = function(Chart) {
79279	Chart.Scatter = function(context, config) {
79280		config.type = 'scatter';
79281		return new Chart(context, config);
79282	};
79283};
79284
79285},{}],15:[function(require,module,exports){
79286'use strict';
79287
79288var defaults = require(26);
79289var elements = require(41);
79290var helpers = require(46);
79291
79292defaults._set('bar', {
79293	hover: {
79294		mode: 'label'
79295	},
79296
79297	scales: {
79298		xAxes: [{
79299			type: 'category',
79300
79301			// Specific to Bar Controller
79302			categoryPercentage: 0.8,
79303			barPercentage: 0.9,
79304
79305			// offset settings
79306			offset: true,
79307
79308			// grid line settings
79309			gridLines: {
79310				offsetGridLines: true
79311			}
79312		}],
79313
79314		yAxes: [{
79315			type: 'linear'
79316		}]
79317	}
79318});
79319
79320defaults._set('horizontalBar', {
79321	hover: {
79322		mode: 'index',
79323		axis: 'y'
79324	},
79325
79326	scales: {
79327		xAxes: [{
79328			type: 'linear',
79329			position: 'bottom'
79330		}],
79331
79332		yAxes: [{
79333			position: 'left',
79334			type: 'category',
79335
79336			// Specific to Horizontal Bar Controller
79337			categoryPercentage: 0.8,
79338			barPercentage: 0.9,
79339
79340			// offset settings
79341			offset: true,
79342
79343			// grid line settings
79344			gridLines: {
79345				offsetGridLines: true
79346			}
79347		}]
79348	},
79349
79350	elements: {
79351		rectangle: {
79352			borderSkipped: 'left'
79353		}
79354	},
79355
79356	tooltips: {
79357		callbacks: {
79358			title: function(item, data) {
79359				// Pick first xLabel for now
79360				var title = '';
79361
79362				if (item.length > 0) {
79363					if (item[0].yLabel) {
79364						title = item[0].yLabel;
79365					} else if (data.labels.length > 0 && item[0].index < data.labels.length) {
79366						title = data.labels[item[0].index];
79367					}
79368				}
79369
79370				return title;
79371			},
79372
79373			label: function(item, data) {
79374				var datasetLabel = data.datasets[item.datasetIndex].label || '';
79375				return datasetLabel + ': ' + item.xLabel;
79376			}
79377		},
79378		mode: 'index',
79379		axis: 'y'
79380	}
79381});
79382
79383/**
79384 * Computes the "optimal" sample size to maintain bars equally sized while preventing overlap.
79385 * @private
79386 */
79387function computeMinSampleSize(scale, pixels) {
79388	var min = scale.isHorizontal() ? scale.width : scale.height;
79389	var ticks = scale.getTicks();
79390	var prev, curr, i, ilen;
79391
79392	for (i = 1, ilen = pixels.length; i < ilen; ++i) {
79393		min = Math.min(min, pixels[i] - pixels[i - 1]);
79394	}
79395
79396	for (i = 0, ilen = ticks.length; i < ilen; ++i) {
79397		curr = scale.getPixelForTick(i);
79398		min = i > 0 ? Math.min(min, curr - prev) : min;
79399		prev = curr;
79400	}
79401
79402	return min;
79403}
79404
79405/**
79406 * Computes an "ideal" category based on the absolute bar thickness or, if undefined or null,
79407 * uses the smallest interval (see computeMinSampleSize) that prevents bar overlapping. This
79408 * mode currently always generates bars equally sized (until we introduce scriptable options?).
79409 * @private
79410 */
79411function computeFitCategoryTraits(index, ruler, options) {
79412	var thickness = options.barThickness;
79413	var count = ruler.stackCount;
79414	var curr = ruler.pixels[index];
79415	var size, ratio;
79416
79417	if (helpers.isNullOrUndef(thickness)) {
79418		size = ruler.min * options.categoryPercentage;
79419		ratio = options.barPercentage;
79420	} else {
79421		// When bar thickness is enforced, category and bar percentages are ignored.
79422		// Note(SB): we could add support for relative bar thickness (e.g. barThickness: '50%')
79423		// and deprecate barPercentage since this value is ignored when thickness is absolute.
79424		size = thickness * count;
79425		ratio = 1;
79426	}
79427
79428	return {
79429		chunk: size / count,
79430		ratio: ratio,
79431		start: curr - (size / 2)
79432	};
79433}
79434
79435/**
79436 * Computes an "optimal" category that globally arranges bars side by side (no gap when
79437 * percentage options are 1), based on the previous and following categories. This mode
79438 * generates bars with different widths when data are not evenly spaced.
79439 * @private
79440 */
79441function computeFlexCategoryTraits(index, ruler, options) {
79442	var pixels = ruler.pixels;
79443	var curr = pixels[index];
79444	var prev = index > 0 ? pixels[index - 1] : null;
79445	var next = index < pixels.length - 1 ? pixels[index + 1] : null;
79446	var percent = options.categoryPercentage;
79447	var start, size;
79448
79449	if (prev === null) {
79450		// first data: its size is double based on the next point or,
79451		// if it's also the last data, we use the scale end extremity.
79452		prev = curr - (next === null ? ruler.end - curr : next - curr);
79453	}
79454
79455	if (next === null) {
79456		// last data: its size is also double based on the previous point.
79457		next = curr + curr - prev;
79458	}
79459
79460	start = curr - ((curr - prev) / 2) * percent;
79461	size = ((next - prev) / 2) * percent;
79462
79463	return {
79464		chunk: size / ruler.stackCount,
79465		ratio: options.barPercentage,
79466		start: start
79467	};
79468}
79469
79470module.exports = function(Chart) {
79471
79472	Chart.controllers.bar = Chart.DatasetController.extend({
79473
79474		dataElementType: elements.Rectangle,
79475
79476		initialize: function() {
79477			var me = this;
79478			var meta;
79479
79480			Chart.DatasetController.prototype.initialize.apply(me, arguments);
79481
79482			meta = me.getMeta();
79483			meta.stack = me.getDataset().stack;
79484			meta.bar = true;
79485		},
79486
79487		update: function(reset) {
79488			var me = this;
79489			var rects = me.getMeta().data;
79490			var i, ilen;
79491
79492			me._ruler = me.getRuler();
79493
79494			for (i = 0, ilen = rects.length; i < ilen; ++i) {
79495				me.updateElement(rects[i], i, reset);
79496			}
79497		},
79498
79499		updateElement: function(rectangle, index, reset) {
79500			var me = this;
79501			var chart = me.chart;
79502			var meta = me.getMeta();
79503			var dataset = me.getDataset();
79504			var custom = rectangle.custom || {};
79505			var rectangleOptions = chart.options.elements.rectangle;
79506
79507			rectangle._xScale = me.getScaleForId(meta.xAxisID);
79508			rectangle._yScale = me.getScaleForId(meta.yAxisID);
79509			rectangle._datasetIndex = me.index;
79510			rectangle._index = index;
79511
79512			rectangle._model = {
79513				datasetLabel: dataset.label,
79514				label: chart.data.labels[index],
79515				borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleOptions.borderSkipped,
79516				backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.valueAtIndexOrDefault(dataset.backgroundColor, index, rectangleOptions.backgroundColor),
79517				borderColor: custom.borderColor ? custom.borderColor : helpers.valueAtIndexOrDefault(dataset.borderColor, index, rectangleOptions.borderColor),
79518				borderWidth: custom.borderWidth ? custom.borderWidth : helpers.valueAtIndexOrDefault(dataset.borderWidth, index, rectangleOptions.borderWidth)
79519			};
79520
79521			me.updateElementGeometry(rectangle, index, reset);
79522
79523			rectangle.pivot();
79524		},
79525
79526		/**
79527		 * @private
79528		 */
79529		updateElementGeometry: function(rectangle, index, reset) {
79530			var me = this;
79531			var model = rectangle._model;
79532			var vscale = me.getValueScale();
79533			var base = vscale.getBasePixel();
79534			var horizontal = vscale.isHorizontal();
79535			var ruler = me._ruler || me.getRuler();
79536			var vpixels = me.calculateBarValuePixels(me.index, index);
79537			var ipixels = me.calculateBarIndexPixels(me.index, index, ruler);
79538
79539			model.horizontal = horizontal;
79540			model.base = reset ? base : vpixels.base;
79541			model.x = horizontal ? reset ? base : vpixels.head : ipixels.center;
79542			model.y = horizontal ? ipixels.center : reset ? base : vpixels.head;
79543			model.height = horizontal ? ipixels.size : undefined;
79544			model.width = horizontal ? undefined : ipixels.size;
79545		},
79546
79547		/**
79548		 * @private
79549		 */
79550		getValueScaleId: function() {
79551			return this.getMeta().yAxisID;
79552		},
79553
79554		/**
79555		 * @private
79556		 */
79557		getIndexScaleId: function() {
79558			return this.getMeta().xAxisID;
79559		},
79560
79561		/**
79562		 * @private
79563		 */
79564		getValueScale: function() {
79565			return this.getScaleForId(this.getValueScaleId());
79566		},
79567
79568		/**
79569		 * @private
79570		 */
79571		getIndexScale: function() {
79572			return this.getScaleForId(this.getIndexScaleId());
79573		},
79574
79575		/**
79576		 * Returns the stacks based on groups and bar visibility.
79577		 * @param {Number} [last] - The dataset index
79578		 * @returns {Array} The stack list
79579		 * @private
79580		 */
79581		_getStacks: function(last) {
79582			var me = this;
79583			var chart = me.chart;
79584			var scale = me.getIndexScale();
79585			var stacked = scale.options.stacked;
79586			var ilen = last === undefined ? chart.data.datasets.length : last + 1;
79587			var stacks = [];
79588			var i, meta;
79589
79590			for (i = 0; i < ilen; ++i) {
79591				meta = chart.getDatasetMeta(i);
79592				if (meta.bar && chart.isDatasetVisible(i) &&
79593					(stacked === false ||
79594					(stacked === true && stacks.indexOf(meta.stack) === -1) ||
79595					(stacked === undefined && (meta.stack === undefined || stacks.indexOf(meta.stack) === -1)))) {
79596					stacks.push(meta.stack);
79597				}
79598			}
79599
79600			return stacks;
79601		},
79602
79603		/**
79604		 * Returns the effective number of stacks based on groups and bar visibility.
79605		 * @private
79606		 */
79607		getStackCount: function() {
79608			return this._getStacks().length;
79609		},
79610
79611		/**
79612		 * Returns the stack index for the given dataset based on groups and bar visibility.
79613		 * @param {Number} [datasetIndex] - The dataset index
79614		 * @param {String} [name] - The stack name to find
79615		 * @returns {Number} The stack index
79616		 * @private
79617		 */
79618		getStackIndex: function(datasetIndex, name) {
79619			var stacks = this._getStacks(datasetIndex);
79620			var index = (name !== undefined)
79621				? stacks.indexOf(name)
79622				: -1; // indexOf returns -1 if element is not present
79623
79624			return (index === -1)
79625				? stacks.length - 1
79626				: index;
79627		},
79628
79629		/**
79630		 * @private
79631		 */
79632		getRuler: function() {
79633			var me = this;
79634			var scale = me.getIndexScale();
79635			var stackCount = me.getStackCount();
79636			var datasetIndex = me.index;
79637			var isHorizontal = scale.isHorizontal();
79638			var start = isHorizontal ? scale.left : scale.top;
79639			var end = start + (isHorizontal ? scale.width : scale.height);
79640			var pixels = [];
79641			var i, ilen, min;
79642
79643			for (i = 0, ilen = me.getMeta().data.length; i < ilen; ++i) {
79644				pixels.push(scale.getPixelForValue(null, i, datasetIndex));
79645			}
79646
79647			min = helpers.isNullOrUndef(scale.options.barThickness)
79648				? computeMinSampleSize(scale, pixels)
79649				: -1;
79650
79651			return {
79652				min: min,
79653				pixels: pixels,
79654				start: start,
79655				end: end,
79656				stackCount: stackCount,
79657				scale: scale
79658			};
79659		},
79660
79661		/**
79662		 * Note: pixel values are not clamped to the scale area.
79663		 * @private
79664		 */
79665		calculateBarValuePixels: function(datasetIndex, index) {
79666			var me = this;
79667			var chart = me.chart;
79668			var meta = me.getMeta();
79669			var scale = me.getValueScale();
79670			var datasets = chart.data.datasets;
79671			var value = scale.getRightValue(datasets[datasetIndex].data[index]);
79672			var stacked = scale.options.stacked;
79673			var stack = meta.stack;
79674			var start = 0;
79675			var i, imeta, ivalue, base, head, size;
79676
79677			if (stacked || (stacked === undefined && stack !== undefined)) {
79678				for (i = 0; i < datasetIndex; ++i) {
79679					imeta = chart.getDatasetMeta(i);
79680
79681					if (imeta.bar &&
79682						imeta.stack === stack &&
79683						imeta.controller.getValueScaleId() === scale.id &&
79684						chart.isDatasetVisible(i)) {
79685
79686						ivalue = scale.getRightValue(datasets[i].data[index]);
79687						if ((value < 0 && ivalue < 0) || (value >= 0 && ivalue > 0)) {
79688							start += ivalue;
79689						}
79690					}
79691				}
79692			}
79693
79694			base = scale.getPixelForValue(start);
79695			head = scale.getPixelForValue(start + value);
79696			size = (head - base) / 2;
79697
79698			return {
79699				size: size,
79700				base: base,
79701				head: head,
79702				center: head + size / 2
79703			};
79704		},
79705
79706		/**
79707		 * @private
79708		 */
79709		calculateBarIndexPixels: function(datasetIndex, index, ruler) {
79710			var me = this;
79711			var options = ruler.scale.options;
79712			var range = options.barThickness === 'flex'
79713				? computeFlexCategoryTraits(index, ruler, options)
79714				: computeFitCategoryTraits(index, ruler, options);
79715
79716			var stackIndex = me.getStackIndex(datasetIndex, me.getMeta().stack);
79717			var center = range.start + (range.chunk * stackIndex) + (range.chunk / 2);
79718			var size = Math.min(
79719				helpers.valueOrDefault(options.maxBarThickness, Infinity),
79720				range.chunk * range.ratio);
79721
79722			return {
79723				base: center - size / 2,
79724				head: center + size / 2,
79725				center: center,
79726				size: size
79727			};
79728		},
79729
79730		draw: function() {
79731			var me = this;
79732			var chart = me.chart;
79733			var scale = me.getValueScale();
79734			var rects = me.getMeta().data;
79735			var dataset = me.getDataset();
79736			var ilen = rects.length;
79737			var i = 0;
79738
79739			helpers.canvas.clipArea(chart.ctx, chart.chartArea);
79740
79741			for (; i < ilen; ++i) {
79742				if (!isNaN(scale.getRightValue(dataset.data[i]))) {
79743					rects[i].draw();
79744				}
79745			}
79746
79747			helpers.canvas.unclipArea(chart.ctx);
79748		},
79749	});
79750
79751	Chart.controllers.horizontalBar = Chart.controllers.bar.extend({
79752		/**
79753		 * @private
79754		 */
79755		getValueScaleId: function() {
79756			return this.getMeta().xAxisID;
79757		},
79758
79759		/**
79760		 * @private
79761		 */
79762		getIndexScaleId: function() {
79763			return this.getMeta().yAxisID;
79764		}
79765	});
79766};
79767
79768},{"26":26,"41":41,"46":46}],16:[function(require,module,exports){
79769'use strict';
79770
79771var defaults = require(26);
79772var elements = require(41);
79773var helpers = require(46);
79774
79775defaults._set('bubble', {
79776	hover: {
79777		mode: 'single'
79778	},
79779
79780	scales: {
79781		xAxes: [{
79782			type: 'linear', // bubble should probably use a linear scale by default
79783			position: 'bottom',
79784			id: 'x-axis-0' // need an ID so datasets can reference the scale
79785		}],
79786		yAxes: [{
79787			type: 'linear',
79788			position: 'left',
79789			id: 'y-axis-0'
79790		}]
79791	},
79792
79793	tooltips: {
79794		callbacks: {
79795			title: function() {
79796				// Title doesn't make sense for scatter since we format the data as a point
79797				return '';
79798			},
79799			label: function(item, data) {
79800				var datasetLabel = data.datasets[item.datasetIndex].label || '';
79801				var dataPoint = data.datasets[item.datasetIndex].data[item.index];
79802				return datasetLabel + ': (' + item.xLabel + ', ' + item.yLabel + ', ' + dataPoint.r + ')';
79803			}
79804		}
79805	}
79806});
79807
79808
79809module.exports = function(Chart) {
79810
79811	Chart.controllers.bubble = Chart.DatasetController.extend({
79812		/**
79813		 * @protected
79814		 */
79815		dataElementType: elements.Point,
79816
79817		/**
79818		 * @protected
79819		 */
79820		update: function(reset) {
79821			var me = this;
79822			var meta = me.getMeta();
79823			var points = meta.data;
79824
79825			// Update Points
79826			helpers.each(points, function(point, index) {
79827				me.updateElement(point, index, reset);
79828			});
79829		},
79830
79831		/**
79832		 * @protected
79833		 */
79834		updateElement: function(point, index, reset) {
79835			var me = this;
79836			var meta = me.getMeta();
79837			var custom = point.custom || {};
79838			var xScale = me.getScaleForId(meta.xAxisID);
79839			var yScale = me.getScaleForId(meta.yAxisID);
79840			var options = me._resolveElementOptions(point, index);
79841			var data = me.getDataset().data[index];
79842			var dsIndex = me.index;
79843
79844			var x = reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(typeof data === 'object' ? data : NaN, index, dsIndex);
79845			var y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, dsIndex);
79846
79847			point._xScale = xScale;
79848			point._yScale = yScale;
79849			point._options = options;
79850			point._datasetIndex = dsIndex;
79851			point._index = index;
79852			point._model = {
79853				backgroundColor: options.backgroundColor,
79854				borderColor: options.borderColor,
79855				borderWidth: options.borderWidth,
79856				hitRadius: options.hitRadius,
79857				pointStyle: options.pointStyle,
79858				rotation: options.rotation,
79859				radius: reset ? 0 : options.radius,
79860				skip: custom.skip || isNaN(x) || isNaN(y),
79861				x: x,
79862				y: y,
79863			};
79864
79865			point.pivot();
79866		},
79867
79868		/**
79869		 * @protected
79870		 */
79871		setHoverStyle: function(point) {
79872			var model = point._model;
79873			var options = point._options;
79874			point.$previousStyle = {
79875				backgroundColor: model.backgroundColor,
79876				borderColor: model.borderColor,
79877				borderWidth: model.borderWidth,
79878				radius: model.radius
79879			};
79880			model.backgroundColor = helpers.valueOrDefault(options.hoverBackgroundColor, helpers.getHoverColor(options.backgroundColor));
79881			model.borderColor = helpers.valueOrDefault(options.hoverBorderColor, helpers.getHoverColor(options.borderColor));
79882			model.borderWidth = helpers.valueOrDefault(options.hoverBorderWidth, options.borderWidth);
79883			model.radius = options.radius + options.hoverRadius;
79884		},
79885
79886		/**
79887		 * @private
79888		 */
79889		_resolveElementOptions: function(point, index) {
79890			var me = this;
79891			var chart = me.chart;
79892			var datasets = chart.data.datasets;
79893			var dataset = datasets[me.index];
79894			var custom = point.custom || {};
79895			var options = chart.options.elements.point;
79896			var resolve = helpers.options.resolve;
79897			var data = dataset.data[index];
79898			var values = {};
79899			var i, ilen, key;
79900
79901			// Scriptable options
79902			var context = {
79903				chart: chart,
79904				dataIndex: index,
79905				dataset: dataset,
79906				datasetIndex: me.index
79907			};
79908
79909			var keys = [
79910				'backgroundColor',
79911				'borderColor',
79912				'borderWidth',
79913				'hoverBackgroundColor',
79914				'hoverBorderColor',
79915				'hoverBorderWidth',
79916				'hoverRadius',
79917				'hitRadius',
79918				'pointStyle',
79919				'rotation'
79920			];
79921
79922			for (i = 0, ilen = keys.length; i < ilen; ++i) {
79923				key = keys[i];
79924				values[key] = resolve([
79925					custom[key],
79926					dataset[key],
79927					options[key]
79928				], context, index);
79929			}
79930
79931			// Custom radius resolution
79932			values.radius = resolve([
79933				custom.radius,
79934				data ? data.r : undefined,
79935				dataset.radius,
79936				options.radius
79937			], context, index);
79938			return values;
79939		}
79940	});
79941};
79942
79943},{"26":26,"41":41,"46":46}],17:[function(require,module,exports){
79944'use strict';
79945
79946var defaults = require(26);
79947var elements = require(41);
79948var helpers = require(46);
79949
79950defaults._set('doughnut', {
79951	animation: {
79952		// Boolean - Whether we animate the rotation of the Doughnut
79953		animateRotate: true,
79954		// Boolean - Whether we animate scaling the Doughnut from the centre
79955		animateScale: false
79956	},
79957	hover: {
79958		mode: 'single'
79959	},
79960	legendCallback: function(chart) {
79961		var text = [];
79962		text.push('<ul class="' + chart.id + '-legend">');
79963
79964		var data = chart.data;
79965		var datasets = data.datasets;
79966		var labels = data.labels;
79967
79968		if (datasets.length) {
79969			for (var i = 0; i < datasets[0].data.length; ++i) {
79970				text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');
79971				if (labels[i]) {
79972					text.push(labels[i]);
79973				}
79974				text.push('</li>');
79975			}
79976		}
79977
79978		text.push('</ul>');
79979		return text.join('');
79980	},
79981	legend: {
79982		labels: {
79983			generateLabels: function(chart) {
79984				var data = chart.data;
79985				if (data.labels.length && data.datasets.length) {
79986					return data.labels.map(function(label, i) {
79987						var meta = chart.getDatasetMeta(0);
79988						var ds = data.datasets[0];
79989						var arc = meta.data[i];
79990						var custom = arc && arc.custom || {};
79991						var valueAtIndexOrDefault = helpers.valueAtIndexOrDefault;
79992						var arcOpts = chart.options.elements.arc;
79993						var fill = custom.backgroundColor ? custom.backgroundColor : valueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
79994						var stroke = custom.borderColor ? custom.borderColor : valueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
79995						var bw = custom.borderWidth ? custom.borderWidth : valueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
79996
79997						return {
79998							text: label,
79999							fillStyle: fill,
80000							strokeStyle: stroke,
80001							lineWidth: bw,
80002							hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
80003
80004							// Extra data used for toggling the correct item
80005							index: i
80006						};
80007					});
80008				}
80009				return [];
80010			}
80011		},
80012
80013		onClick: function(e, legendItem) {
80014			var index = legendItem.index;
80015			var chart = this.chart;
80016			var i, ilen, meta;
80017
80018			for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
80019				meta = chart.getDatasetMeta(i);
80020				// toggle visibility of index if exists
80021				if (meta.data[index]) {
80022					meta.data[index].hidden = !meta.data[index].hidden;
80023				}
80024			}
80025
80026			chart.update();
80027		}
80028	},
80029
80030	// The percentage of the chart that we cut out of the middle.
80031	cutoutPercentage: 50,
80032
80033	// The rotation of the chart, where the first data arc begins.
80034	rotation: Math.PI * -0.5,
80035
80036	// The total circumference of the chart.
80037	circumference: Math.PI * 2.0,
80038
80039	// Need to override these to give a nice default
80040	tooltips: {
80041		callbacks: {
80042			title: function() {
80043				return '';
80044			},
80045			label: function(tooltipItem, data) {
80046				var dataLabel = data.labels[tooltipItem.index];
80047				var value = ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
80048
80049				if (helpers.isArray(dataLabel)) {
80050					// show value on first line of multiline label
80051					// need to clone because we are changing the value
80052					dataLabel = dataLabel.slice();
80053					dataLabel[0] += value;
80054				} else {
80055					dataLabel += value;
80056				}
80057
80058				return dataLabel;
80059			}
80060		}
80061	}
80062});
80063
80064defaults._set('pie', helpers.clone(defaults.doughnut));
80065defaults._set('pie', {
80066	cutoutPercentage: 0
80067});
80068
80069module.exports = function(Chart) {
80070
80071	Chart.controllers.doughnut = Chart.controllers.pie = Chart.DatasetController.extend({
80072
80073		dataElementType: elements.Arc,
80074
80075		linkScales: helpers.noop,
80076
80077		// Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly
80078		getRingIndex: function(datasetIndex) {
80079			var ringIndex = 0;
80080
80081			for (var j = 0; j < datasetIndex; ++j) {
80082				if (this.chart.isDatasetVisible(j)) {
80083					++ringIndex;
80084				}
80085			}
80086
80087			return ringIndex;
80088		},
80089
80090		update: function(reset) {
80091			var me = this;
80092			var chart = me.chart;
80093			var chartArea = chart.chartArea;
80094			var opts = chart.options;
80095			var arcOpts = opts.elements.arc;
80096			var availableWidth = chartArea.right - chartArea.left - arcOpts.borderWidth;
80097			var availableHeight = chartArea.bottom - chartArea.top - arcOpts.borderWidth;
80098			var minSize = Math.min(availableWidth, availableHeight);
80099			var offset = {x: 0, y: 0};
80100			var meta = me.getMeta();
80101			var cutoutPercentage = opts.cutoutPercentage;
80102			var circumference = opts.circumference;
80103
80104			// If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc
80105			if (circumference < Math.PI * 2.0) {
80106				var startAngle = opts.rotation % (Math.PI * 2.0);
80107				startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0);
80108				var endAngle = startAngle + circumference;
80109				var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)};
80110				var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)};
80111				var contains0 = (startAngle <= 0 && endAngle >= 0) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle);
80112				var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle);
80113				var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle);
80114				var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle);
80115				var cutout = cutoutPercentage / 100.0;
80116				var min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))};
80117				var max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))};
80118				var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5};
80119				minSize = Math.min(availableWidth / size.width, availableHeight / size.height);
80120				offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5};
80121			}
80122
80123			chart.borderWidth = me.getMaxBorderWidth(meta.data);
80124			chart.outerRadius = Math.max((minSize - chart.borderWidth) / 2, 0);
80125			chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 0, 0);
80126			chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();
80127			chart.offsetX = offset.x * chart.outerRadius;
80128			chart.offsetY = offset.y * chart.outerRadius;
80129
80130			meta.total = me.calculateTotal();
80131
80132			me.outerRadius = chart.outerRadius - (chart.radiusLength * me.getRingIndex(me.index));
80133			me.innerRadius = Math.max(me.outerRadius - chart.radiusLength, 0);
80134
80135			helpers.each(meta.data, function(arc, index) {
80136				me.updateElement(arc, index, reset);
80137			});
80138		},
80139
80140		updateElement: function(arc, index, reset) {
80141			var me = this;
80142			var chart = me.chart;
80143			var chartArea = chart.chartArea;
80144			var opts = chart.options;
80145			var animationOpts = opts.animation;
80146			var centerX = (chartArea.left + chartArea.right) / 2;
80147			var centerY = (chartArea.top + chartArea.bottom) / 2;
80148			var startAngle = opts.rotation; // non reset case handled later
80149			var endAngle = opts.rotation; // non reset case handled later
80150			var dataset = me.getDataset();
80151			var circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * Math.PI));
80152			var innerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius;
80153			var outerRadius = reset && animationOpts.animateScale ? 0 : me.outerRadius;
80154			var valueAtIndexOrDefault = helpers.valueAtIndexOrDefault;
80155
80156			helpers.extend(arc, {
80157				// Utility
80158				_datasetIndex: me.index,
80159				_index: index,
80160
80161				// Desired view properties
80162				_model: {
80163					x: centerX + chart.offsetX,
80164					y: centerY + chart.offsetY,
80165					startAngle: startAngle,
80166					endAngle: endAngle,
80167					circumference: circumference,
80168					outerRadius: outerRadius,
80169					innerRadius: innerRadius,
80170					label: valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index])
80171				}
80172			});
80173
80174			var model = arc._model;
80175
80176			// Resets the visual styles
80177			var custom = arc.custom || {};
80178			var valueOrDefault = helpers.valueAtIndexOrDefault;
80179			var elementOpts = this.chart.options.elements.arc;
80180			model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : valueOrDefault(dataset.backgroundColor, index, elementOpts.backgroundColor);
80181			model.borderColor = custom.borderColor ? custom.borderColor : valueOrDefault(dataset.borderColor, index, elementOpts.borderColor);
80182			model.borderWidth = custom.borderWidth ? custom.borderWidth : valueOrDefault(dataset.borderWidth, index, elementOpts.borderWidth);
80183
80184			// Set correct angles if not resetting
80185			if (!reset || !animationOpts.animateRotate) {
80186				if (index === 0) {
80187					model.startAngle = opts.rotation;
80188				} else {
80189					model.startAngle = me.getMeta().data[index - 1]._model.endAngle;
80190				}
80191
80192				model.endAngle = model.startAngle + model.circumference;
80193			}
80194
80195			arc.pivot();
80196		},
80197
80198		calculateTotal: function() {
80199			var dataset = this.getDataset();
80200			var meta = this.getMeta();
80201			var total = 0;
80202			var value;
80203
80204			helpers.each(meta.data, function(element, index) {
80205				value = dataset.data[index];
80206				if (!isNaN(value) && !element.hidden) {
80207					total += Math.abs(value);
80208				}
80209			});
80210
80211			/* if (total === 0) {
80212				total = NaN;
80213			}*/
80214
80215			return total;
80216		},
80217
80218		calculateCircumference: function(value) {
80219			var total = this.getMeta().total;
80220			if (total > 0 && !isNaN(value)) {
80221				return (Math.PI * 2.0) * (Math.abs(value) / total);
80222			}
80223			return 0;
80224		},
80225
80226		// gets the max border or hover width to properly scale pie charts
80227		getMaxBorderWidth: function(arcs) {
80228			var max = 0;
80229			var index = this.index;
80230			var length = arcs.length;
80231			var borderWidth;
80232			var hoverWidth;
80233
80234			for (var i = 0; i < length; i++) {
80235				borderWidth = arcs[i]._model ? arcs[i]._model.borderWidth : 0;
80236				hoverWidth = arcs[i]._chart ? arcs[i]._chart.config.data.datasets[index].hoverBorderWidth : 0;
80237
80238				max = borderWidth > max ? borderWidth : max;
80239				max = hoverWidth > max ? hoverWidth : max;
80240			}
80241			return max;
80242		}
80243	});
80244};
80245
80246},{"26":26,"41":41,"46":46}],18:[function(require,module,exports){
80247'use strict';
80248
80249var defaults = require(26);
80250var elements = require(41);
80251var helpers = require(46);
80252
80253defaults._set('line', {
80254	showLines: true,
80255	spanGaps: false,
80256
80257	hover: {
80258		mode: 'label'
80259	},
80260
80261	scales: {
80262		xAxes: [{
80263			type: 'category',
80264			id: 'x-axis-0'
80265		}],
80266		yAxes: [{
80267			type: 'linear',
80268			id: 'y-axis-0'
80269		}]
80270	}
80271});
80272
80273module.exports = function(Chart) {
80274
80275	function lineEnabled(dataset, options) {
80276		return helpers.valueOrDefault(dataset.showLine, options.showLines);
80277	}
80278
80279	Chart.controllers.line = Chart.DatasetController.extend({
80280
80281		datasetElementType: elements.Line,
80282
80283		dataElementType: elements.Point,
80284
80285		update: function(reset) {
80286			var me = this;
80287			var meta = me.getMeta();
80288			var line = meta.dataset;
80289			var points = meta.data || [];
80290			var options = me.chart.options;
80291			var lineElementOptions = options.elements.line;
80292			var scale = me.getScaleForId(meta.yAxisID);
80293			var i, ilen, custom;
80294			var dataset = me.getDataset();
80295			var showLine = lineEnabled(dataset, options);
80296
80297			// Update Line
80298			if (showLine) {
80299				custom = line.custom || {};
80300
80301				// Compatibility: If the properties are defined with only the old name, use those values
80302				if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {
80303					dataset.lineTension = dataset.tension;
80304				}
80305
80306				// Utility
80307				line._scale = scale;
80308				line._datasetIndex = me.index;
80309				// Data
80310				line._children = points;
80311				// Model
80312				line._model = {
80313					// Appearance
80314					// The default behavior of lines is to break at null values, according
80315					// to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158
80316					// This option gives lines the ability to span gaps
80317					spanGaps: dataset.spanGaps ? dataset.spanGaps : options.spanGaps,
80318					tension: custom.tension ? custom.tension : helpers.valueOrDefault(dataset.lineTension, lineElementOptions.tension),
80319					backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),
80320					borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),
80321					borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),
80322					borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),
80323					borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),
80324					borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),
80325					borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),
80326					fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),
80327					steppedLine: custom.steppedLine ? custom.steppedLine : helpers.valueOrDefault(dataset.steppedLine, lineElementOptions.stepped),
80328					cubicInterpolationMode: custom.cubicInterpolationMode ? custom.cubicInterpolationMode : helpers.valueOrDefault(dataset.cubicInterpolationMode, lineElementOptions.cubicInterpolationMode),
80329				};
80330
80331				line.pivot();
80332			}
80333
80334			// Update Points
80335			for (i = 0, ilen = points.length; i < ilen; ++i) {
80336				me.updateElement(points[i], i, reset);
80337			}
80338
80339			if (showLine && line._model.tension !== 0) {
80340				me.updateBezierControlPoints();
80341			}
80342
80343			// Now pivot the point for animation
80344			for (i = 0, ilen = points.length; i < ilen; ++i) {
80345				points[i].pivot();
80346			}
80347		},
80348
80349		getPointBackgroundColor: function(point, index) {
80350			var backgroundColor = this.chart.options.elements.point.backgroundColor;
80351			var dataset = this.getDataset();
80352			var custom = point.custom || {};
80353
80354			if (custom.backgroundColor) {
80355				backgroundColor = custom.backgroundColor;
80356			}
80356 else if (dataset.pointBackgroundColor) {
80357				backgroundColor = helpers.valueAtIndexOrDefault(dataset.pointBackgroundColor, index, backgroundColor);
80358			} else if (dataset.backgroundColor) {
80359				backgroundColor = dataset.backgroundColor;
80360			}
80361
80362			return backgroundColor;
80363		},
80364
80365		getPointBorderColor: function(point, index) {
80366			var borderColor = this.chart.options.elements.point.borderColor;
80367			var dataset = this.getDataset();
80368			var custom = point.custom || {};
80369
80370			if (custom.borderColor) {
80371				borderColor = custom.borderColor;
80372			} else if (dataset.pointBorderColor) {
80373				borderColor = helpers.valueAtIndexOrDefault(dataset.pointBorderColor, index, borderColor);
80374			} else if (dataset.borderColor) {
80375				borderColor = dataset.borderColor;
80376			}
80377
80378			return borderColor;
80379		},
80380
80381		getPointBorderWidth: function(point, index) {
80382			var borderWidth = this.chart.options.elements.point.borderWidth;
80383			var dataset = this.getDataset();
80384			var custom = point.custom || {};
80385
80386			if (!isNaN(custom.borderWidth)) {
80387				borderWidth = custom.borderWidth;
80388			} else if (!isNaN(dataset.pointBorderWidth) || helpers.isArray(dataset.pointBorderWidth)) {
80389				borderWidth = helpers.valueAtIndexOrDefault(dataset.pointBorderWidth, index, borderWidth);
80390			} else if (!isNaN(dataset.borderWidth)) {
80391				borderWidth = dataset.borderWidth;
80392			}
80393
80394			return borderWidth;
80395		},
80396
80397		getPointRotation: function(point, index) {
80398			var pointRotation = this.chart.options.elements.point.rotation;
80399			var dataset = this.getDataset();
80400			var custom = point.custom || {};
80401
80402			if (!isNaN(custom.rotation)) {
80403				pointRotation = custom.rotation;
80404			} else if (!isNaN(dataset.pointRotation) || helpers.isArray(dataset.pointRotation)) {
80405				pointRotation = helpers.valueAtIndexOrDefault(dataset.pointRotation, index, pointRotation);
80406			}
80407			return pointRotation;
80408		},
80409
80410		updateElement: function(point, index, reset) {
80411			var me = this;
80412			var meta = me.getMeta();
80413			var custom = point.custom || {};
80414			var dataset = me.getDataset();
80415			var datasetIndex = me.index;
80416			var value = dataset.data[index];
80417			var yScale = me.getScaleForId(meta.yAxisID);
80418			var xScale = me.getScaleForId(meta.xAxisID);
80419			var pointOptions = me.chart.options.elements.point;
80420			var x, y;
80421
80422			// Compatibility: If the properties are defined with only the old name, use those values
80423			if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {
80424				dataset.pointRadius = dataset.radius;
80425			}
80426			if ((dataset.hitRadius !== undefined) && (dataset.pointHitRadius === undefined)) {
80427				dataset.pointHitRadius = dataset.hitRadius;
80428			}
80429
80430			x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex);
80431			y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex);
80432
80433			// Utility
80434			point._xScale = xScale;
80435			point._yScale = yScale;
80436			point._datasetIndex = datasetIndex;
80437			point._index = index;
80438
80439			// Desired view properties
80440			point._model = {
80441				x: x,
80442				y: y,
80443				skip: custom.skip || isNaN(x) || isNaN(y),
80444				// Appearance
80445				radius: custom.radius || helpers.valueAtIndexOrDefault(dataset.pointRadius, index, pointOptions.radius),
80446				pointStyle: custom.pointStyle || helpers.valueAtIndexOrDefault(dataset.pointStyle, index, pointOptions.pointStyle),
80447				rotation: me.getPointRotation(point, index),
80448				backgroundColor: me.getPointBackgroundColor(point, index),
80449				borderColor: me.getPointBorderColor(point, index),
80450				borderWidth: me.getPointBorderWidth(point, index),
80451				tension: meta.dataset._model ? meta.dataset._model.tension : 0,
80452				steppedLine: meta.dataset._model ? meta.dataset._model.steppedLine : false,
80453				// Tooltip
80454				hitRadius: custom.hitRadius || helpers.valueAtIndexOrDefault(dataset.pointHitRadius, index, pointOptions.hitRadius)
80455			};
80456		},
80457
80458		calculatePointY: function(value, index, datasetIndex) {
80459			var me = this;
80460			var chart = me.chart;
80461			var meta = me.getMeta();
80462			var yScale = me.getScaleForId(meta.yAxisID);
80463			var sumPos = 0;
80464			var sumNeg = 0;
80465			var i, ds, dsMeta;
80466
80467			if (yScale.options.stacked) {
80468				for (i = 0; i < datasetIndex; i++) {
80469					ds = chart.data.datasets[i];
80470					dsMeta = chart.getDatasetMeta(i);
80471					if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {
80472						var stackedRightValue = Number(yScale.getRightValue(ds.data[index]));
80473						if (stackedRightValue < 0) {
80474							sumNeg += stackedRightValue || 0;
80475						} else {
80476							sumPos += stackedRightValue || 0;
80477						}
80478					}
80479				}
80480
80481				var rightValue = Number(yScale.getRightValue(value));
80482				if (rightValue < 0) {
80483					return yScale.getPixelForValue(sumNeg + rightValue);
80484				}
80485				return yScale.getPixelForValue(sumPos + rightValue);
80486			}
80487
80488			return yScale.getPixelForValue(value);
80489		},
80490
80491		updateBezierControlPoints: function() {
80492			var me = this;
80493			var meta = me.getMeta();
80494			var area = me.chart.chartArea;
80495			var points = (meta.data || []);
80496			var i, ilen, point, model, controlPoints;
80497
80498			// Only consider points that are drawn in case the spanGaps option is used
80499			if (meta.dataset._model.spanGaps) {
80500				points = points.filter(function(pt) {
80501					return !pt._model.skip;
80502				});
80503			}
80504
80505			function capControlPoint(pt, min, max) {
80506				return Math.max(Math.min(pt, max), min);
80507			}
80508
80509			if (meta.dataset._model.cubicInterpolationMode === 'monotone') {
80510				helpers.splineCurveMonotone(points);
80511			} else {
80512				for (i = 0, ilen = points.length; i < ilen; ++i) {
80513					point = points[i];
80514					model = point._model;
80515					controlPoints = helpers.splineCurve(
80516						helpers.previousItem(points, i)._model,
80517						model,
80518						helpers.nextItem(points, i)._model,
80519						meta.dataset._model.tension
80520					);
80521					model.controlPointPreviousX = controlPoints.previous.x;
80522					model.controlPointPreviousY = controlPoints.previous.y;
80523					model.controlPointNextX = controlPoints.next.x;
80524					model.controlPointNextY = controlPoints.next.y;
80525				}
80526			}
80527
80528			if (me.chart.options.elements.line.capBezierPoints) {
80529				for (i = 0, ilen = points.length; i < ilen; ++i) {
80530					model = points[i]._model;
80531					model.controlPointPreviousX = capControlPoint(model.controlPointPreviousX, area.left, area.right);
80532					model.controlPointPreviousY = capControlPoint(model.controlPointPreviousY, area.top, area.bottom);
80533					model.controlPointNextX = capControlPoint(model.controlPointNextX, area.left, area.right);
80534					model.controlPointNextY = capControlPoint(model.controlPointNextY, area.top, area.bottom);
80535				}
80536			}
80537		},
80538
80539		draw: function() {
80540			var me = this;
80541			var chart = me.chart;
80542			var meta = me.getMeta();
80543			var points = meta.data || [];
80544			var area = chart.chartArea;
80545			var ilen = points.length;
80546			var halfBorderWidth;
80547			var i = 0;
80548
80549			if (lineEnabled(me.getDataset(), chart.options)) {
80550				halfBorderWidth = (meta.dataset._model.borderWidth || 0) / 2;
80551
80552				helpers.canvas.clipArea(chart.ctx, {
80553					left: area.left,
80554					right: area.right,
80555					top: area.top - halfBorderWidth,
80556					bottom: area.bottom + halfBorderWidth
80557				});
80558
80559				meta.dataset.draw();
80560
80561				helpers.canvas.unclipArea(chart.ctx);
80562			}
80563
80564			// Draw the points
80565			for (; i < ilen; ++i) {
80566				points[i].draw(area);
80567			}
80568		},
80569
80570		setHoverStyle: function(element) {
80571			// Point
80572			var dataset = this.chart.data.datasets[element._datasetIndex];
80573			var index = element._index;
80574			var custom = element.custom || {};
80575			var model = element._model;
80576
80577			element.$previousStyle = {
80578				backgroundColor: model.backgroundColor,
80579				borderColor: model.borderColor,
80580				borderWidth: model.borderWidth,
80581				radius: model.radius
80582			};
80583
80584			model.backgroundColor = custom.hoverBackgroundColor || helpers.valueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
80585			model.borderColor = custom.hoverBorderColor || helpers.valueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor));
80586			model.borderWidth = custom.hoverBorderWidth || helpers.valueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth);
80587			model.radius = custom.hoverRadius || helpers.valueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);
80588		},
80589	});
80590};
80591
80592},{"26":26,"41":41,"46":46}],19:[function(require,module,exports){
80593'use strict';
80594
80595var defaults = require(26);
80596var elements = require(41);
80597var helpers = require(46);
80598
80599defaults._set('polarArea', {
80600	scale: {
80601		type: 'radialLinear',
80602		angleLines: {
80603			display: false
80604		},
80605		gridLines: {
80606			circular: true
80607		},
80608		pointLabels: {
80609			display: false
80610		},
80611		ticks: {
80612			beginAtZero: true
80613		}
80614	},
80615
80616	// Boolean - Whether to animate the rotation of the chart
80617	animation: {
80618		animateRotate: true,
80619		animateScale: true
80620	},
80621
80622	startAngle: -0.5 * Math.PI,
80623	legendCallback: function(chart) {
80624		var text = [];
80625		text.push('<ul class="' + chart.id + '-legend">');
80626
80627		var data = chart.data;
80628		var datasets = data.datasets;
80629		var labels = data.labels;
80630
80631		if (datasets.length) {
80632			for (var i = 0; i < datasets[0].data.length; ++i) {
80633				text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');
80634				if (labels[i]) {
80635					text.push(labels[i]);
80636				}
80637				text.push('</li>');
80638			}
80639		}
80640
80641		text.push('</ul>');
80642		return text.join('');
80643	},
80644	legend: {
80645		labels: {
80646			generateLabels: function(chart) {
80647				var data = chart.data;
80648				if (data.labels.length && data.datasets.length) {
80649					return data.labels.map(function(label, i) {
80650						var meta = chart.getDatasetMeta(0);
80651						var ds = data.datasets[0];
80652						var arc = meta.data[i];
80653						var custom = arc.custom || {};
80654						var valueAtIndexOrDefault = helpers.valueAtIndexOrDefault;
80655						var arcOpts = chart.options.elements.arc;
80656						var fill = custom.backgroundColor ? custom.backgroundColor : valueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
80657						var stroke = custom.borderColor ? custom.borderColor : valueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
80658						var bw = custom.borderWidth ? custom.borderWidth : valueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
80659
80660						return {
80661							text: label,
80662							fillStyle: fill,
80663							strokeStyle: stroke,
80664							lineWidth: bw,
80665							hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
80666
80667							// Extra data used for toggling the correct item
80668							index: i
80669						};
80670					});
80671				}
80672				return [];
80673			}
80674		},
80675
80676		onClick: function(e, legendItem) {
80677			var index = legendItem.index;
80678			var chart = this.chart;
80679			var i, ilen, meta;
80680
80681			for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
80682				meta = chart.getDatasetMeta(i);
80683				meta.data[index].hidden = !meta.data[index].hidden;
80684			}
80685
80686			chart.update();
80687		}
80688	},
80689
80690	// Need to override these to give a nice default
80691	tooltips: {
80692		callbacks: {
80693			title: function() {
80694				return '';
80695			},
80696			label: function(item, data) {
80697				return data.labels[item.index] + ': ' + item.yLabel;
80698			}
80699		}
80700	}
80701});
80702
80703module.exports = function(Chart) {
80704
80705	Chart.controllers.polarArea = Chart.DatasetController.extend({
80706
80707		dataElementType: elements.Arc,
80708
80709		linkScales: helpers.noop,
80710
80711		update: function(reset) {
80712			var me = this;
80713			var dataset = me.getDataset();
80714			var meta = me.getMeta();
80715			var start = me.chart.options.startAngle || 0;
80716			var starts = me._starts = [];
80717			var angles = me._angles = [];
80718			var i, ilen, angle;
80719
80720			me._updateRadius();
80721
80722			meta.count = me.countVisibleElements();
80723
80724			for (i = 0, ilen = dataset.data.length; i < ilen; i++) {
80725				starts[i] = start;
80726				angle = me._computeAngle(i);
80727				angles[i] = angle;
80728				start += angle;
80729			}
80730
80731			helpers.each(meta.data, function(arc, index) {
80732				me.updateElement(arc, index, reset);
80733			});
80734		},
80735
80736		/**
80737		 * @private
80738		 */
80739		_updateRadius: function() {
80740			var me = this;
80741			var chart = me.chart;
80742			var chartArea = chart.chartArea;
80743			var opts = chart.options;
80744			var arcOpts = opts.elements.arc;
80745			var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
80746
80747			chart.outerRadius = Math.max((minSize - arcOpts.borderWidth / 2) / 2, 0);
80748			chart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0);
80749			chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();
80750
80751			me.outerRadius = chart.outerRadius - (chart.radiusLength * me.index);
80752			me.innerRadius = me.outerRadius - chart.radiusLength;
80753		},
80754
80755		updateElement: function(arc, index, reset) {
80756			var me = this;
80757			var chart = me.chart;
80758			var dataset = me.getDataset();
80759			var opts = chart.options;
80760			var animationOpts = opts.animation;
80761			var scale = chart.scale;
80762			var labels = chart.data.labels;
80763
80764			var centerX = scale.xCenter;
80765			var centerY = scale.yCenter;
80766
80767			// var negHalfPI = -0.5 * Math.PI;
80768			var datasetStartAngle = opts.startAngle;
80769			var distance = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
80770			var startAngle = me._starts[index];
80771			var endAngle = startAngle + (arc.hidden ? 0 : me._angles[index]);
80772
80773			var resetRadius = animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
80774
80775			helpers.extend(arc, {
80776				// Utility
80777				_datasetIndex: me.index,
80778				_index: index,
80779				_scale: scale,
80780
80781				// Desired view properties
80782				_model: {
80783					x: centerX,
80784					y: centerY,
80785					innerRadius: 0,
80786					outerRadius: reset ? resetRadius : distance,
80787					startAngle: reset && animationOpts.animateRotate ? datasetStartAngle : startAngle,
80788					endAngle: reset && animationOpts.animateRotate ? datasetStartAngle : endAngle,
80789					label: helpers.valueAtIndexOrDefault(labels, index, labels[index])
80790				}
80791			});
80792
80793			// Apply border and fill style
80794			var elementOpts = this.chart.options.elements.arc;
80795			var custom = arc.custom || {};
80796			var valueOrDefault = helpers.valueAtIndexOrDefault;
80797			var model = arc._model;
80798
80799			model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : valueOrDefault(dataset.backgroundColor, index, elementOpts.backgroundColor);
80800			model.borderColor = custom.borderColor ? custom.borderColor : valueOrDefault(dataset.borderColor, index, elementOpts.borderColor);
80801			model.borderWidth = custom.borderWidth ? custom.borderWidth : valueOrDefault(dataset.borderWidth, index, elementOpts.borderWidth);
80802
80803			arc.pivot();
80804		},
80805
80806		countVisibleElements: function() {
80807			var dataset = this.getDataset();
80808			var meta = this.getMeta();
80809			var count = 0;
80810
80811			helpers.each(meta.data, function(element, index) {
80812				if (!isNaN(dataset.data[index]) && !element.hidden) {
80813					count++;
80814				}
80815			});
80816
80817			return count;
80818		},
80819
80820		/**
80821		 * @private
80822		 */
80823		_computeAngle: function(index) {
80824			var me = this;
80825			var count = this.getMeta().count;
80826			var dataset = me.getDataset();
80827			var meta = me.getMeta();
80828
80829			if (isNaN(dataset.data[index]) || meta.data[index].hidden) {
80830				return 0;
80831			}
80832
80833			// Scriptable options
80834			var context = {
80835				chart: me.chart,
80836				dataIndex: index,
80837				dataset: dataset,
80838				datasetIndex: me.index
80839			};
80840
80841			return helpers.options.resolve([
80842				me.chart.options.elements.arc.angle,
80843				(2 * Math.PI) / count
80844			], context, index);
80845		}
80846	});
80847};
80848
80849},{"26":26,"41":41,"46":46}],20:[function(require,module,exports){
80850'use strict';
80851
80852var defaults = require(26);
80853var elements = require(41);
80854var helpers = require(46);
80855
80856defaults._set('radar', {
80857	scale: {
80858		type: 'radialLinear'
80859	},
80860	elements: {
80861		line: {
80862			tension: 0 // no bezier in radar
80863		}
80864	}
80865});
80866
80867module.exports = function(Chart) {
80868
80869	Chart.controllers.radar = Chart.DatasetController.extend({
80870
80871		datasetElementType: elements.Line,
80872
80873		dataElementType: elements.Point,
80874
80875		linkScales: helpers.noop,
80876
80877		update: function(reset) {
80878			var me = this;
80879			var meta = me.getMeta();
80880			var line = meta.dataset;
80881			var points = meta.data;
80882			var custom = line.custom || {};
80883			var dataset = me.getDataset();
80884			var lineElementOptions = me.chart.options.elements.line;
80885			var scale = me.chart.scale;
80886
80887			// Compatibility: If the properties are defined with only the old name, use those values
80888			if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {
80889				dataset.lineTension = dataset.tension;
80890			}
80891
80892			helpers.extend(meta.dataset, {
80893				// Utility
80894				_datasetIndex: me.index,
80895				_scale: scale,
80896				// Data
80897				_children: points,
80898				_loop: true,
80899				// Model
80900				_model: {
80901					// Appearance
80902					tension: custom.tension ? custom.tension : helpers.valueOrDefault(dataset.lineTension, lineElementOptions.tension),
80903					backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),
80904					borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),
80905					borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),
80906					fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),
80907					borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),
80908					borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),
80909					borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),
80910					borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),
80911				}
80912			});
80913
80914			meta.dataset.pivot();
80915
80916			// Update Points
80917			helpers.each(points, function(point, index) {
80918				me.updateElement(point, index, reset);
80919			}, me);
80920
80921			// Update bezier control points
80922			me.updateBezierControlPoints();
80923		},
80924		updateElement: function(point, index, reset) {
80925			var me = this;
80926			var custom = point.custom || {};
80927			var dataset = me.getDataset();
80928			var scale = me.chart.scale;
80929			var pointElementOptions = me.chart.options.elements.point;
80930			var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]);
80931
80932			// Compatibility: If the properties are defined with only the old name, use those values
80933			if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {
80934				dataset.pointRadius = dataset.radius;
80935			}
80936			if ((dataset.hitRadius !== undefined) && (dataset.pointHitRadius === undefined)) {
80937				dataset.pointHitRadius = dataset.hitRadius;
80938			}
80939
80940			helpers.extend(point, {
80941				// Utility
80942				_datasetIndex: me.index,
80943				_index: index,
80944				_scale: scale,
80945
80946				// Desired view properties
80947				_model: {
80948					x: reset ? scale.xCenter : pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales
80949					y: reset ? scale.yCenter : pointPosition.y,
80950
80951					// Appearance
80952					tension: custom.tension ? custom.tension : helpers.valueOrDefault(dataset.lineTension, me.chart.options.elements.line.tension),
80953					radius: custom.radius ? custom.radius : helpers.valueAtIndexOrDefault(dataset.pointRadius, index, pointElementOptions.radius),
80954					backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.valueAtIndexOrDefault(dataset.pointBackgroun
80954dColor, index, pointElementOptions.backgroundColor),
80955					borderColor: custom.borderColor ? custom.borderColor : helpers.valueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor),
80956					borderWidth: custom.borderWidth ? custom.borderWidth : helpers.valueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth),
80957					pointStyle: custom.pointStyle ? custom.pointStyle : helpers.valueAtIndexOrDefault(dataset.pointStyle, index, pointElementOptions.pointStyle),
80958					rotation: custom.rotation ? custom.rotation : helpers.valueAtIndexOrDefault(dataset.pointRotation, index, pointElementOptions.rotation),
80959
80960					// Tooltip
80961					hitRadius: custom.hitRadius ? custom.hitRadius : helpers.valueAtIndexOrDefault(dataset.pointHitRadius, index, pointElementOptions.hitRadius)
80962				}
80963			});
80964
80965			point._model.skip = custom.skip ? custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));
80966		},
80967		updateBezierControlPoints: function() {
80968			var chartArea = this.chart.chartArea;
80969			var meta = this.getMeta();
80970
80971			helpers.each(meta.data, function(point, index) {
80972				var model = point._model;
80973				var controlPoints = helpers.splineCurve(
80974					helpers.previousItem(meta.data, index, true)._model,
80975					model,
80976					helpers.nextItem(meta.data, index, true)._model,
80977					model.tension
80978				);
80979
80980				// Prevent the bezier going outside of the bounds of the graph
80981				model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, chartArea.right), chartArea.left);
80982				model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, chartArea.bottom), chartArea.top);
80983
80984				model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, chartArea.right), chartArea.left);
80985				model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, chartArea.bottom), chartArea.top);
80986
80987				// Now pivot the point for animation
80988				point.pivot();
80989			});
80990		},
80991
80992		setHoverStyle: function(point) {
80993			// Point
80994			var dataset = this.chart.data.datasets[point._datasetIndex];
80995			var custom = point.custom || {};
80996			var index = point._index;
80997			var model = point._model;
80998
80999			point.$previousStyle = {
81000				backgroundColor: model.backgroundColor,
81001				borderColor: model.borderColor,
81002				borderWidth: model.borderWidth,
81003				radius: model.radius
81004			};
81005
81006			model.radius = custom.hoverRadius ? custom.hoverRadius : helpers.valueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);
81007			model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.valueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
81008			model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.valueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor));
81009			model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.valueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth);
81010		},
81011	});
81012};
81013
81014},{"26":26,"41":41,"46":46}],21:[function(require,module,exports){
81015'use strict';
81016
81017var defaults = require(26);
81018
81019defaults._set('scatter', {
81020	hover: {
81021		mode: 'single'
81022	},
81023
81024	scales: {
81025		xAxes: [{
81026			id: 'x-axis-1',    // need an ID so datasets can reference the scale
81027			type: 'linear',    // scatter should not use a category axis
81028			position: 'bottom'
81029		}],
81030		yAxes: [{
81031			id: 'y-axis-1',
81032			type: 'linear',
81033			position: 'left'
81034		}]
81035	},
81036
81037	showLines: false,
81038
81039	tooltips: {
81040		callbacks: {
81041			title: function() {
81042				return '';     // doesn't make sense for scatter since data are formatted as a point
81043			},
81044			label: function(item) {
81045				return '(' + item.xLabel + ', ' + item.yLabel + ')';
81046			}
81047		}
81048	}
81049});
81050
81051module.exports = function(Chart) {
81052
81053	// Scatter charts use line controllers
81054	Chart.controllers.scatter = Chart.controllers.line;
81055
81056};
81057
81058},{"26":26}],22:[function(require,module,exports){
81059'use strict';
81060
81061var Element = require(27);
81062
81063var exports = module.exports = Element.extend({
81064	chart: null, // the animation associated chart instance
81065	currentStep: 0, // the current animation step
81066	numSteps: 60, // default number of steps
81067	easing: '', // the easing to use for this animation
81068	render: null, // render function used by the animation service
81069
81070	onAnimationProgress: null, // user specified callback to fire on each step of the animation
81071	onAnimationComplete: null, // user specified callback to fire when the animation finishes
81072});
81073
81074// DEPRECATIONS
81075
81076/**
81077 * Provided for backward compatibility, use Chart.Animation instead
81078 * @prop Chart.Animation#animationObject
81079 * @deprecated since version 2.6.0
81080 * @todo remove at version 3
81081 */
81082Object.defineProperty(exports.prototype, 'animationObject', {
81083	get: function() {
81084		return this;
81085	}
81086});
81087
81088/**
81089 * Provided for backward compatibility, use Chart.Animation#chart instead
81090 * @prop Chart.Animation#chartInstance
81091 * @deprecated since version 2.6.0
81092 * @todo remove at version 3
81093 */
81094Object.defineProperty(exports.prototype, 'chartInstance', {
81095	get: function() {
81096		return this.chart;
81097	},
81098	set: function(value) {
81099		this.chart = value;
81100	}
81101});
81102
81103},{"27":27}],23:[function(require,module,exports){
81104/* global window: false */
81105'use strict';
81106
81107var defaults = require(26);
81108var helpers = require(46);
81109
81110defaults._set('global', {
81111	animation: {
81112		duration: 1000,
81113		easing: 'easeOutQuart',
81114		onProgress: helpers.noop,
81115		onComplete: helpers.noop
81116	}
81117});
81118
81119module.exports = {
81120	frameDuration: 17,
81121	animations: [],
81122	dropFrames: 0,
81123	request: null,
81124
81125	/**
81126	 * @param {Chart} chart - The chart to animate.
81127	 * @param {Chart.Animation} animation - The animation that we will animate.
81128	 * @param {Number} duration - The animation duration in ms.
81129	 * @param {Boolean} lazy - if true, the chart is not marked as animating to enable more responsive interactions
81130	 */
81131	addAnimation: function(chart, animation, duration, lazy) {
81132		var animations = this.animations;
81133		var i, ilen;
81134
81135		animation.chart = chart;
81136
81137		if (!lazy) {
81138			chart.animating = true;
81139		}
81140
81141		for (i = 0, ilen = animations.length; i < ilen; ++i) {
81142			if (animations[i].chart === chart) {
81143				animations[i] = animation;
81144				return;
81145			}
81146		}
81147
81148		animations.push(animation);
81149
81150		// If there are no animations queued, manually kickstart a digest, for lack of a better word
81151		if (animations.length === 1) {
81152			this.requestAnimationFrame();
81153		}
81154	},
81155
81156	cancelAnimation: function(chart) {
81157		var index = helpers.findIndex(this.animations, function(animation) {
81158			return animation.chart === chart;
81159		});
81160
81161		if (index !== -1) {
81162			this.animations.splice(index, 1);
81163			chart.animating = false;
81164		}
81165	},
81166
81167	requestAnimationFrame: function() {
81168		var me = this;
81169		if (me.request === null) {
81170			// Skip animation frame requests until the active one is executed.
81171			// This can happen when processing mouse events, e.g. 'mousemove'
81172			// and 'mouseout' events will trigger multiple renders.
81173			me.request = helpers.requestAnimFrame.call(window, function() {
81174				me.request = null;
81175				me.startDigest();
81176			});
81177		}
81178	},
81179
81180	/**
81181	 * @private
81182	 */
81183	startDigest: function() {
81184		var me = this;
81185		var startTime = Date.now();
81186		var framesToDrop = 0;
81187
81188		if (me.dropFrames > 1) {
81189			framesToDrop = Math.floor(me.dropFrames);
81190			me.dropFrames = me.dropFrames % 1;
81191		}
81192
81193		me.advance(1 + framesToDrop);
81194
81195		var endTime = Date.now();
81196
81197		me.dropFrames += (endTime - startTime) / me.frameDuration;
81198
81199		// Do we have more stuff to animate?
81200		if (me.animations.length > 0) {
81201			me.requestAnimationFrame();
81202		}
81203	},
81204
81205	/**
81206	 * @private
81207	 */
81208	advance: function(count) {
81209		var animations = this.animations;
81210		var animation, chart;
81211		var i = 0;
81212
81213		while (i < animations.length) {
81214			animation = animations[i];
81215			chart = animation.chart;
81216
81217			animation.currentStep = (animation.currentStep || 0) + count;
81218			animation.currentStep = Math.min(animation.currentStep, animation.numSteps);
81219
81220			helpers.callback(animation.render, [chart, animation], chart);
81221			helpers.callback(animation.onAnimationProgress, [animation], chart);
81222
81223			if (animation.currentStep >= animation.numSteps) {
81224				helpers.callback(animation.onAnimationComplete, [animation], chart);
81225				chart.animating = false;
81226				animations.splice(i, 1);
81227			} else {
81228				++i;
81229			}
81230		}
81231	}
81232};
81233
81234},{"26":26,"46":46}],24:[function(require,module,exports){
81235'use strict';
81236
81237var Animation = require(22);
81238var animations = require(23);
81239var defaults = require(26);
81240var helpers = require(46);
81241var Interaction = require(29);
81242var layouts = require(31);
81243var platform = require(49);
81244var plugins = require(32);
81245var scaleService = require(34);
81246var Tooltip = require(36);
81247
81248module.exports = function(Chart) {
81249
81250	// Create a dictionary of chart types, to allow for extension of existing types
81251	Chart.types = {};
81252
81253	// Store a reference to each instance - allowing us to globally resize chart instances on window resize.
81254	// Destroy method on the chart will remove the instance of the chart from this reference.
81255	Chart.instances = {};
81256
81257	// Controllers available for dataset visualization eg. bar, line, slice, etc.
81258	Chart.controllers = {};
81259
81260	/**
81261	 * Initializes the given config with global and chart default values.
81262	 */
81263	function initConfig(config) {
81264		config = config || {};
81265
81266		// Do NOT use configMerge() for the data object because this method merges arrays
81267		// and so would change references to labels and datasets, preventing data updates.
81268		var data = config.data = config.data || {};
81269		data.datasets = data.datasets || [];
81270		data.labels = data.labels || [];
81271
81272		config.options = helpers.configMerge(
81273			defaults.global,
81274			defaults[config.type],
81275			config.options || {});
81276
81277		return config;
81278	}
81279
81280	/**
81281	 * Updates the config of the chart
81282	 * @param chart {Chart} chart to update the options for
81283	 */
81284	function updateConfig(chart) {
81285		var newOptions = chart.options;
81286
81287		helpers.each(chart.scales, function(scale) {
81288			layouts.removeBox(chart, scale);
81289		});
81290
81291		newOptions = helpers.configMerge(
81292			Chart.defaults.global,
81293			Chart.defaults[chart.config.type],
81294			newOptions);
81295
81296		chart.options = chart.config.options = newOptions;
vendor: 11,649 bytes, lines 81297-81731
81297		chart.ensureScalesHaveIDs();
81298		chart.buildOrUpdateScales();
81299		// Tooltip
81300		chart.tooltip._options = newOptions.tooltips;
81301		chart.tooltip.initialize();
81302	}
81303
81304	function positionIsHorizontal(position) {
81305		return position === 'top' || position === 'bottom';
81306	}
81307
81308	helpers.extend(Chart.prototype, /** @lends Chart */ {
81309		/**
81310		 * @private
81311		 */
81312		construct: function(item, config) {
81313			var me = this;
81314
81315			config = initConfig(config);
81316
81317			var context = platform.acquireContext(item, config);
81318			var canvas = context && context.canvas;
81319			var height = canvas && canvas.height;
81320			var width = canvas && canvas.width;
81321
81322			me.id = helpers.uid();
81323			me.ctx = context;
81324			me.canvas = canvas;
81325			me.config = config;
81326			me.width = width;
81327			me.height = height;
81328			me.aspectRatio = height ? width / height : null;
81329			me.options = config.options;
81330			me._bufferedRender = false;
81331
81332			/**
81333			 * Provided for backward compatibility, Chart and Chart.Controller have been merged,
81334			 * the "instance" still need to be defined since it might be called from plugins.
81335			 * @prop Chart#chart
81336			 * @deprecated since version 2.6.0
81337			 * @todo remove at version 3
81338			 * @private
81339			 */
81340			me.chart = me;
81341			me.controller = me; // chart.chart.controller #inception
81342
81343			// Add the chart instance to the global namespace
81344			Chart.instances[me.id] = me;
81345
81346			// Define alias to the config data: `chart.data === chart.config.data`
81347			Object.defineProperty(me, 'data', {
81348				get: function() {
81349					return me.config.data;
81350				},
81351				set: function(value) {
81352					me.config.data = value;
81353				}
81354			});
81355
81356			if (!context || !canvas) {
81357				// The given item is not a compatible context2d element, let's return before finalizing
81358				// the chart initialization but after setting basic chart / controller properties that
81359				// can help to figure out that the chart is not valid (e.g chart.canvas !== null);
81360				// https://github.com/chartjs/Chart.js/issues/2807
81361				console.error("Failed to create chart: can't acquire context from the given item");
81362				return;
81363			}
81364
81365			me.initialize();
81366			me.update();
81367		},
81368
81369		/**
81370		 * @private
81371		 */
81372		initialize: function() {
81373			var me = this;
81374
81375			// Before init plugin notification
81376			plugins.notify(me, 'beforeInit');
81377
81378			helpers.retinaScale(me, me.options.devicePixelRatio);
81379
81380			me.bindEvents();
81381
81382			if (me.options.responsive) {
81383				// Initial resize before chart draws (must be silent to preserve initial animations).
81384				me.resize(true);
81385			}
81386
81387			// Make sure scales have IDs and are built before we build any controllers.
81388			me.ensureScalesHaveIDs();
81389			me.buildOrUpdateScales();
81390			me.initToolTip();
81391
81392			// After init plugin notification
81393			plugins.notify(me, 'afterInit');
81394
81395			return me;
81396		},
81397
81398		clear: function() {
81399			helpers.canvas.clear(this);
81400			return this;
81401		},
81402
81403		stop: function() {
81404			// Stops any current animation loop occurring
81405			animations.cancelAnimation(this);
81406			return this;
81407		},
81408
81409		resize: function(silent) {
81410			var me = this;
81411			var options = me.options;
81412			var canvas = me.canvas;
81413			var aspectRatio = (options.maintainAspectRatio && me.aspectRatio) || null;
81414
81415			// the canvas render width and height will be casted to integers so make sure that
81416			// the canvas display style uses the same integer values to avoid blurring effect.
81417
81418			// Set to 0 instead of canvas.size because the size defaults to 300x150 if the element is collapsed
81419			var newWidth = Math.max(0, Math.floor(helpers.getMaximumWidth(canvas)));
81420			var newHeight = Math.max(0, Math.floor(aspectRatio ? newWidth / aspectRatio : helpers.getMaximumHeight(canvas)));
81421
81422			if (me.width === newWidth && me.height === newHeight) {
81423				return;
81424			}
81425
81426			canvas.width = me.width = newWidth;
81427			canvas.height = me.height = newHeight;
81428			canvas.style.width = newWidth + 'px';
81429			canvas.style.height = newHeight + 'px';
81430
81431			helpers.retinaScale(me, options.devicePixelRatio);
81432
81433			if (!silent) {
81434				// Notify any plugins about the resize
81435				var newSize = {width: newWidth, height: newHeight};
81436				plugins.notify(me, 'resize', [newSize]);
81437
81438				// Notify of resize
81439				if (me.options.onResize) {
81440					me.options.onResize(me, newSize);
81441				}
81442
81443				me.stop();
81444				me.update({
81445					duration: me.options.responsiveAnimationDuration
81446				});
81447			}
81448		},
81449
81450		ensureScalesHaveIDs: function() {
81451			var options = this.options;
81452			var scalesOptions = options.scales || {};
81453			var scaleOptions = options.scale;
81454
81455			helpers.each(scalesOptions.xAxes, function(xAxisOptions, index) {
81456				xAxisOptions.id = xAxisOptions.id || ('x-axis-' + index);
81457			});
81458
81459			helpers.each(scalesOptions.yAxes, function(yAxisOptions, index) {
81460				yAxisOptions.id = yAxisOptions.id || ('y-axis-' + index);
81461			});
81462
81463			if (scaleOptions) {
81464				scaleOptions.id = scaleOptions.id || 'scale';
81465			}
81466		},
81467
81468		/**
81469		 * Builds a map of scale ID to scale object for future lookup.
81470		 */
81471		buildOrUpdateScales: function() {
81472			var me = this;
81473			var options = me.options;
81474			var scales = me.scales || {};
81475			var items = [];
81476			var updated = Object.keys(scales).reduce(function(obj, id) {
81477				obj[id] = false;
81478				return obj;
81479			}, {});
81480
81481			if (options.scales) {
81482				items = items.concat(
81483					(options.scales.xAxes || []).map(function(xAxisOptions) {
81484						return {options: xAxisOptions, dtype: 'category', dposition: 'bottom'};
81485					}),
81486					(options.scales.yAxes || []).map(function(yAxisOptions) {
81487						return {options: yAxisOptions, dtype: 'linear', dposition: 'left'};
81488					})
81489				);
81490			}
81491
81492			if (options.scale) {
81493				items.push({
81494					options: options.scale,
81495					dtype: 'radialLinear',
81496					isDefault: true,
81497					dposition: 'chartArea'
81498				});
81499			}
81500
81501			helpers.each(items, function(item) {
81502				var scaleOptions = item.options;
81503				var id = scaleOptions.id;
81504				var scaleType = helpers.valueOrDefault(scaleOptions.type, item.dtype);
81505
81506				if (positionIsHorizontal(scaleOptions.position) !== positionIsHorizontal(item.dposition)) {
81507					scaleOptions.position = item.dposition;
81508				}
81509
81510				updated[id] = true;
81511				var scale = null;
81512				if (id in scales && scales[id].type === scaleType) {
81513					scale = scales[id];
81514					scale.options = scaleOptions;
81515					scale.ctx = me.ctx;
81516					scale.chart = me;
81517				} else {
81518					var scaleClass = scaleService.getScaleConstructor(scaleType);
81519					if (!scaleClass) {
81520						return;
81521					}
81522					scale = new scaleClass({
81523						id: id,
81524						type: scaleType,
81525						options: scaleOptions,
81526						ctx: me.ctx,
81527						chart: me
81528					});
81529					scales[scale.id] = scale;
81530				}
81531
81532				scale.mergeTicksOptions();
81533
81534				// TODO(SB): I think we should be able to remove this custom case (options.scale)
81535				// and consider it as a regular scale part of the "scales"" map only! This would
81536				// make the logic easier and remove some useless? custom code.
81537				if (item.isDefault) {
81538					me.scale = scale;
81539				}
81540			});
81541			// clear up discarded scales
81542			helpers.each(updated, function(hasUpdated, id) {
81543				if (!hasUpdated) {
81544					delete scales[id];
81545				}
81546			});
81547
81548			me.scales = scales;
81549
81550			scaleService.addScalesToLayout(this);
81551		},
81552
81553		buildOrUpdateControllers: function() {
81554			var me = this;
81555			var types = [];
81556			var newControllers = [];
81557
81558			helpers.each(me.data.datasets, function(dataset, datasetIndex) {
81559				var meta = me.getDatasetMeta(datasetIndex);
81560				var type = dataset.type || me.config.type;
81561
81562				if (meta.type && meta.type !== type) {
81563					me.destroyDatasetMeta(datasetIndex);
81564					meta = me.getDatasetMeta(datasetIndex);
81565				}
81566				meta.type = type;
81567
81568				types.push(meta.type);
81569
81570				if (meta.controller) {
81571					meta.controller.updateIndex(datasetIndex);
81572					meta.controller.linkScales();
81573				} else {
81574					var ControllerClass = Chart.controllers[meta.type];
81575					if (ControllerClass === undefined) {
81576						throw new Error('"' + meta.type + '" is not a chart type.');
81577					}
81578
81579					meta.controller = new ControllerClass(me, datasetIndex);
81580					newControllers.push(meta.controller);
81581				}
81582			}, me);
81583
81584			return newControllers;
81585		},
81586
81587		/**
81588		 * Reset the elements of all datasets
81589		 * @private
81590		 */
81591		resetElements: function() {
81592			var me = this;
81593			helpers.each(me.data.datasets, function(dataset, datasetIndex) {
81594				me.getDatasetMeta(datasetIndex).controller.reset();
81595			}, me);
81596		},
81597
81598		/**
81599		* Resets the chart back to it's state before the initial animation
81600		*/
81601		reset: function() {
81602			this.resetElements();
81603			this.tooltip.initialize();
81604		},
81605
81606		update: function(config) {
81607			var me = this;
81608
81609			if (!config || typeof config !== 'object') {
81610				// backwards compatibility
81611				config = {
81612					duration: config,
81613					lazy: arguments[1]
81614				};
81615			}
81616
81617			updateConfig(me);
81618
81619			// plugins options references might have change, let's invalidate the cache
81620			// https://github.com/chartjs/Chart.js/issues/5111#issuecomment-355934167
81621			plugins._invalidate(me);
81622
81623			if (plugins.notify(me, 'beforeUpdate') === false) {
81624				return;
81625			}
81626
81627			// In case the entire data object changed
81628			me.tooltip._data = me.data;
81629
81630			// Make sure dataset controllers are updated and new controllers are reset
81631			var newControllers = me.buildOrUpdateControllers();
81632
81633			// Make sure all dataset controllers have correct meta data counts
81634			helpers.each(me.data.datasets, function(dataset, datasetIndex) {
81635				me.getDatasetMeta(datasetIndex).controller.buildOrUpdateElements();
81636			}, me);
81637
81638			me.updateLayout();
81639
81640			// Can only reset the new controllers after the scales have been updated
81641			if (me.options.animation && me.options.animation.duration) {
81642				helpers.each(newControllers, function(controller) {
81643					controller.reset();
81644				});
81645			}
81646
81647			me.updateDatasets();
81648
81649			// Need to reset tooltip in case it is displayed with elements that are removed
81650			// after update.
81651			me.tooltip.initialize();
81652
81653			// Last active contains items that were previously in the tooltip.
81654			// When we reset the tooltip, we need to clear it
81655			me.lastActive = [];
81656
81657			// Do this before render so that any plugins that need final scale updates can use it
81658			plugins.notify(me, 'afterUpdate');
81659
81660			if (me._bufferedRender) {
81661				me._bufferedRequest = {
81662					duration: config.duration,
81663					easing: config.easing,
81664					lazy: config.lazy
81665				};
81666			} else {
81667				me.render(config);
81668			}
81669		},
81670
81671		/**
81672		 * Updates the chart layout unless a plugin returns `false` to the `beforeLayout`
81673		 * hook, in which case, plugins will not be called on `afterLayout`.
81674		 * @private
81675		 */
81676		updateLayout: function() {
81677			var me = this;
81678
81679			if (plugins.notify(me, 'beforeLayout') === false) {
81680				return;
81681			}
81682
81683			layouts.update(this, this.width, this.height);
81684
81685			/**
81686			 * Provided for backward compatibility, use `afterLayout` instead.
81687			 * @method IPlugin#afterScaleUpdate
81688			 * @deprecated since version 2.5.0
81689			 * @todo remove at version 3
81690			 * @private
81691			 */
81692			plugins.notify(me, 'afterScaleUpdate');
81693			plugins.notify(me, 'afterLayout');
81694		},
81695
81696		/**
81697		 * Updates all datasets unless a plugin returns `false` to the `beforeDatasetsUpdate`
81698		 * hook, in which case, plugins will not be called on `afterDatasetsUpdate`.
81699		 * @private
81700		 */
81701		updateDatasets: function() {
81702			var me = this;
81703
81704			if (plugins.notify(me, 'beforeDatasetsUpdate') === false) {
81705				return;
81706			}
81707
81708			for (var i = 0, ilen = me.data.datasets.length; i < ilen; ++i) {
81709				me.updateDataset(i);
81710			}
81711
81712			plugins.notify(me, 'afterDatasetsUpdate');
81713		},
81714
81715		/**
81716		 * Updates dataset at index unless a plugin returns `false` to the `beforeDatasetUpdate`
81717		 * hook, in which case, plugins will not be called on `afterDatasetUpdate`.
81718		 * @private
81719		 */
81720		updateDataset: function(index) {
81721			var me = this;
81722			var meta = me.getDatasetMeta(index);
81723			var args = {
81724				meta: meta,
81725				index: index
81726			};
81727
81728			if (plugins.notify(me, 'beforeDatasetUpdate', [args]) === false) {
81729				return;
81730			}
81731
81732			meta.controller.update();
81733
81734			plugins.notify(me, 'afterDatasetUpdate', [args]);
81735		},
81736
81737		render: function(config) {
81738			var me = this;
81739
81740			if (!config || typeof config !== 'object') {
81741				// backwards compatibility
81742				config = {
81743					duration: config,
81744					lazy: arguments[1]
81745				};
81746			}
81747
81748			var duration = config.duration;
81749			var lazy = config.lazy;
81750
81751			if (plugins.notify(me, 'beforeRender') === false) {
81752				return;
81753			}
81754
81755			var animationOptions = me.options.animation;
81756			var onComplete = function(animation) {
81757				plugins.notify(me, 'afterRender');
81758				helpers.callback(animationOptions && animationOptions.onComplete, [animation], me);
81759			};
81760
81761			if (animationOptions && ((typeof duration !== 'undefined' && duration !== 0) || (typeof duration === 'undefined' && animationOptions.duration !== 0))) {
81762				var animation = new Animation({
81763					numSteps: (duration || animationOptions.duration) / 16.66, // 60 fps
81764					easing: config.easing || animationOptions.easing,
81765
81766					render: function(chart, animationObject) {
81767						var easingFunction = helpers.easing.effects[animationObject.easing];
81768						var currentStep = animationObject.currentStep;
81769						var stepDecimal = currentStep / animationObject.numSteps;
81770
81771						chart.draw(easingFunction(stepDecimal), stepDecimal, currentStep);
81772					},
81773
81774					onAnimationProgress: animationOptions.onProgress,
81775					onAnimationComplete: onComplete
81776				});
81777
81778				animations.addAnimation(me, animation, duration, lazy);
81779			} else {
81780				me.draw();
81781
81782				// See https://github.com/chartjs/Chart.js/issues/3781
81783				onComplete(new Animation({numSteps: 0, chart: me}));
81784			}
81785
81786			return me;
81787		},
81788
81789		draw: function(easingValue) {
81790			var me = this;
81791
81792			me.clear();
81793
81794			if (helpers.isNullOrUndef(easingValue)) {
81795				easingValue = 1;
81796			}
81797
81798			me.transition(easingValue);
81799
81800			if (me.width <= 0 || me.height <= 0) {
81801				return;
81802			}
81803
81804			if (plugins.notify(me, 'beforeDraw', [easingValue]) === false) {
81805				return;
81806			}
81807
81808			// Draw all the scales
81809			helpers.each(me.boxes, function(box) {
81810				box.draw(me.chartArea);
81811			}, me);
81812
81813			if (me.scale) {
81814				me.scale.draw();
81815			}
81816
81817			me.drawDatasets(easingValue);
81818			me._drawTooltip(easingValue);
81819
81820			plugins.notify(me, 'afterDraw', [easingValue]);
81821		},
81822
81823		/**
81824		 * @private
81825		 */
81826		transition: function(easingValue) {
81827			var me = this;
81828
81829			for (var i = 0, ilen = (me.data.datasets || []).length; i < ilen; ++i) {
81830				if (me.isDatasetVisible(i)) {
81831					me.getDatasetMeta(i).controller.transition(easingValue);
81832				}
81833			}
81834
81835			me.tooltip.transition(easingValue);
81836		},
81837
81838		/**
81839		 * Draws all datasets unless a plugin returns `false` to the `beforeDatasetsDraw`
81840		 * hook, in which case, plugins will not be called on `afterDatasetsDraw`.
81841		 * @private
81842		 */
81843		drawDatasets: function(easingValue) {
81844			var me = this;
81845
81846			if (plugins.notify(me, 'beforeDatasetsDraw', [easingValue]) === false) {
81847				return;
81848			}
81849
81850			// Draw datasets reversed to support proper line stacking
81851			for (var i = (me.data.datasets || []).length - 1; i >= 0; --i) {
81852				if (me.isDatasetVisible(i)) {
81853					me.drawDataset(i, easingValue);
81854				}
81855			}
81856
81857			plugins.notify(me, 'afterDatasetsDraw', [easingValue]);
81858		},
81859
81860		/**
81861		 * Draws dataset at index unless a plugin returns `false` to the `beforeDatasetDraw`
81862		 * hook, in which case, plugins will not be called on `afterDatasetDraw`.
81863		 * @private
81864		 */
81865		drawDataset: function(index, easingValue) {
81866			var me = this;
81867			var meta = me.getDatasetMeta(index);
81868			var args = {
81869				meta: meta,
81870				index: index,
81871				easingValue: easingValue
81872			};
81873
81874			if (plugins.notify(me, 'beforeDatasetDraw', [args]) === false) {
81875				return;
81876			}
81877
81878			meta.controller.draw(easingValue);
81879
81880			plugins.notify(me, 'afterDatasetDraw', [args]);
81881		},
81882
81883		/**
81884		 * Draws tooltip unless a plugin returns `false` to the `beforeTooltipDraw`
81885		 * hook, in which case, plugins will not be called on `afterTooltipDraw`.
81886		 * @private
81887		 */
81888		_drawTooltip: function(easingValue) {
81889			var me = this;
81890			var tooltip = me.tooltip;
81891			var args = {
81892				tooltip: tooltip,
81893				easingValue: easingValue
81894			};
81895
81896			if (plugins.notify(me, 'beforeTooltipDraw', [args]) === false) {
81897				return;
81898			}
81899
81900			tooltip.draw();
81901
81902			plugins.notify(me, 'afterTooltipDraw', [args]);
81903		},
81904
81905		// Get the single element that was clicked on
vendor: 46,161 bytes, lines 81906-83535
81906		// @return : An object containing the dataset index and element index of the matching element. Also contains the rectangle that was draw
81907		getElementAtEvent: function(e) {
81908			return Interaction.modes.single(this, e);
81909		},
81910
81911		getElementsAtEvent: function(e) {
81912			return Interaction.modes.label(this, e, {intersect: true});
81913		},
81914
81915		getElementsAtXAxis: function(e) {
81916			return Interaction.modes['x-axis'](this, e, {intersect: true});
81917		},
81918
81919		getElementsAtEventForMode: function(e, mode, options) {
81920			var method = Interaction.modes[mode];
81921			if (typeof method === 'function') {
81922				return method(this, e, options);
81923			}
81924
81925			return [];
81926		},
81927
81928		getDatasetAtEvent: function(e) {
81929			return Interaction.modes.dataset(this, e, {intersect: true});
81930		},
81931
81932		getDatasetMeta: function(datasetIndex) {
81933			var me = this;
81934			var dataset = me.data.datasets[datasetIndex];
81935			if (!dataset._meta) {
81936				dataset._meta = {};
81937			}
81938
81939			var meta = dataset._meta[me.id];
81940			if (!meta) {
81941				meta = dataset._meta[me.id] = {
81942					type: null,
81943					data: [],
81944					dataset: null,
81945					controller: null,
81946					hidden: null,			// See isDatasetVisible() comment
81947					xAxisID: null,
81948					yAxisID: null
81949				};
81950			}
81951
81952			return meta;
81953		},
81954
81955		getVisibleDatasetCount: function() {
81956			var count = 0;
81957			for (var i = 0, ilen = this.data.datasets.length; i < ilen; ++i) {
81958				if (this.isDatasetVisible(i)) {
81959					count++;
81960				}
81961			}
81962			return count;
81963		},
81964
81965		isDatasetVisible: function(datasetIndex) {
81966			var meta = this.getDatasetMeta(datasetIndex);
81967
81968			// meta.hidden is a per chart dataset hidden flag override with 3 states: if true or false,
81969			// the dataset.hidden value is ignored, else if null, the dataset hidden state is returned.
81970			return typeof meta.hidden === 'boolean' ? !meta.hidden : !this.data.datasets[datasetIndex].hidden;
81971		},
81972
81973		generateLegend: function() {
81974			return this.options.legendCallback(this);
81975		},
81976
81977		/**
81978		 * @private
81979		 */
81980		destroyDatasetMeta: function(datasetIndex) {
81981			var id = this.id;
81982			var dataset = this.data.datasets[datasetIndex];
81983			var meta = dataset._meta && dataset._meta[id];
81984
81985			if (meta) {
81986				meta.controller.destroy();
81987				delete dataset._meta[id];
81988			}
81989		},
81990
81991		destroy: function() {
81992			var me = this;
81993			var canvas = me.canvas;
81994			var i, ilen;
81995
81996			me.stop();
81997
81998			// dataset controllers need to cleanup associated data
81999			for (i = 0, ilen = me.data.datasets.length; i < ilen; ++i) {
82000				me.destroyDatasetMeta(i);
82001			}
82002
82003			if (canvas) {
82004				me.unbindEvents();
82005				helpers.canvas.clear(me);
82006				platform.releaseContext(me.ctx);
82007				me.canvas = null;
82008				me.ctx = null;
82009			}
82010
82011			plugins.notify(me, 'destroy');
82012
82013			delete Chart.instances[me.id];
82014		},
82015
82016		toBase64Image: function() {
82017			return this.canvas.toDataURL.apply(this.canvas, arguments);
82018		},
82019
82020		initToolTip: function() {
82021			var me = this;
82022			me.tooltip = new Tooltip({
82023				_chart: me,
82024				_chartInstance: me, // deprecated, backward compatibility
82025				_data: me.data,
82026				_options: me.options.tooltips
82027			}, me);
82028		},
82029
82030		/**
82031		 * @private
82032		 */
82033		bindEvents: function() {
82034			var me = this;
82035			var listeners = me._listeners = {};
82036			var listener = function() {
82037				me.eventHandler.apply(me, arguments);
82038			};
82039
82040			helpers.each(me.options.events, function(type) {
82041				platform.addEventListener(me, type, listener);
82042				listeners[type] = listener;
82043			});
82044
82045			// Elements used to detect size change should not be injected for non responsive charts.
82046			// See https://github.com/chartjs/Chart.js/issues/2210
82047			if (me.options.responsive) {
82048				listener = function() {
82049					me.resize();
82050				};
82051
82052				platform.addEventListener(me, 'resize', listener);
82053				listeners.resize = listener;
82054			}
82055		},
82056
82057		/**
82058		 * @private
82059		 */
82060		unbindEvents: function() {
82061			var me = this;
82062			var listeners = me._listeners;
82063			if (!listeners) {
82064				return;
82065			}
82066
82067			delete me._listeners;
82068			helpers.each(listeners, function(listener, type) {
82069				platform.removeEventListener(me, type, listener);
82070			});
82071		},
82072
82073		updateHoverStyle: function(elements, mode, enabled) {
82074			var method = enabled ? 'setHoverStyle' : 'removeHoverStyle';
82075			var element, i, ilen;
82076
82077			for (i = 0, ilen = elements.length; i < ilen; ++i) {
82078				element = elements[i];
82079				if (element) {
82080					this.getDatasetMeta(element._datasetIndex).controller[method](element);
82081				}
82082			}
82083		},
82084
82085		/**
82086		 * @private
82087		 */
82088		eventHandler: function(e) {
82089			var me = this;
82090			var tooltip = me.tooltip;
82091
82092			if (plugins.notify(me, 'beforeEvent', [e]) === false) {
82093				return;
82094			}
82095
82096			// Buffer any update calls so that renders do not occur
82097			me._bufferedRender = true;
82098			me._bufferedRequest = null;
82099
82100			var changed = me.handleEvent(e);
82101			// for smooth tooltip animations issue #4989
82102			// the tooltip should be the source of change
82103			// Animation check workaround:
82104			// tooltip._start will be null when tooltip isn't animating
82105			if (tooltip) {
82106				changed = tooltip._start
82107					? tooltip.handleEvent(e)
82108					: changed | tooltip.handleEvent(e);
82109			}
82110
82111			plugins.notify(me, 'afterEvent', [e]);
82112
82113			var bufferedRequest = me._bufferedRequest;
82114			if (bufferedRequest) {
82115				// If we have an update that was triggered, we need to do a normal render
82116				me.render(bufferedRequest);
82117			} else if (changed && !me.animating) {
82118				// If entering, leaving, or changing elements, animate the change via pivot
82119				me.stop();
82120
82121				// We only need to render at this point. Updating will cause scales to be
82122				// recomputed generating flicker & using more memory than necessary.
82123				me.render({
82124					duration: me.options.hover.animationDuration,
82125					lazy: true
82126				});
82127			}
82128
82129			me._bufferedRender = false;
82130			me._bufferedRequest = null;
82131
82132			return me;
82133		},
82134
82135		/**
82136		 * Handle an event
82137		 * @private
82138		 * @param {IEvent} event the event to handle
82139		 * @return {Boolean} true if the chart needs to re-render
82140		 */
82141		handleEvent: function(e) {
82142			var me = this;
82143			var options = me.options || {};
82144			var hoverOptions = options.hover;
82145			var changed = false;
82146
82147			me.lastActive = me.lastActive || [];
82148
82149			// Find Active Elements for hover and tooltips
82150			if (e.type === 'mouseout') {
82151				me.active = [];
82152			} else {
82153				me.active = me.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions);
82154			}
82155
82156			// Invoke onHover hook
82157			// Need to call with native event here to not break backwards compatibility
82158			helpers.callback(options.onHover || options.hover.onHover, [e.native, me.active], me);
82159
82160			if (e.type === 'mouseup' || e.type === 'click') {
82161				if (options.onClick) {
82162					// Use e.native here for backwards compatibility
82163					options.onClick.call(me, e.native, me.active);
82164				}
82165			}
82166
82167			// Remove styling for last active (even if it may still be active)
82168			if (me.lastActive.length) {
82169				me.updateHoverStyle(me.lastActive, hoverOptions.mode, false);
82170			}
82171
82172			// Built in hover styling
82173			if (me.active.length && hoverOptions.mode) {
82174				me.updateHoverStyle(me.active, hoverOptions.mode, true);
82175			}
82176
82177			changed = !helpers.arrayEquals(me.active, me.lastActive);
82178
82179			// Remember Last Actives
82180			me.lastActive = me.active;
82181
82182			return changed;
82183		}
82184	});
82185
82186	/**
82187	 * Provided for backward compatibility, use Chart instead.
82188	 * @class Chart.Controller
82189	 * @deprecated since version 2.6.0
82190	 * @todo remove at version 3
82191	 * @private
82192	 */
82193	Chart.Controller = Chart;
82194};
82195
82196},{"22":22,"23":23,"26":26,"29":29,"31":31,"32":32,"34":34,"36":36,"46":46,"49":49}],25:[function(require,module,exports){
82197'use strict';
82198
82199var helpers = require(46);
82200
82201module.exports = function(Chart) {
82202
82203	var arrayEvents = ['push', 'pop', 'shift', 'splice', 'unshift'];
82204
82205	/**
82206	 * Hooks the array methods that add or remove values ('push', pop', 'shift', 'splice',
82207	 * 'unshift') and notify the listener AFTER the array has been altered. Listeners are
82208	 * called on the 'onData*' callbacks (e.g. onDataPush, etc.) with same arguments.
82209	 */
82210	function listenArrayEvents(array, listener) {
82211		if (array._chartjs) {
82212			array._chartjs.listeners.push(listener);
82213			return;
82214		}
82215
82216		Object.defineProperty(array, '_chartjs', {
82217			configurable: true,
82218			enumerable: false,
82219			value: {
82220				listeners: [listener]
82221			}
82222		});
82223
82224		arrayEvents.forEach(function(key) {
82225			var method = 'onData' + key.charAt(0).toUpperCase() + key.slice(1);
82226			var base = array[key];
82227
82228			Object.defineProperty(array, key, {
82229				configurable: true,
82230				enumerable: false,
82231				value: function() {
82232					var args = Array.prototype.slice.call(arguments);
82233					var res = base.apply(this, args);
82234
82235					helpers.each(array._chartjs.listeners, function(object) {
82236						if (typeof object[method] === 'function') {
82237							object[method].apply(object, args);
82238						}
82239					});
82240
82241					return res;
82242				}
82243			});
82244		});
82245	}
82246
82247	/**
82248	 * Removes the given array event listener and cleanup extra attached properties (such as
82249	 * the _chartjs stub and overridden methods) if array doesn't have any more listeners.
82250	 */
82251	function unlistenArrayEvents(array, listener) {
82252		var stub = array._chartjs;
82253		if (!stub) {
82254			return;
82255		}
82256
82257		var listeners = stub.listeners;
82258		var index = listeners.indexOf(listener);
82259		if (index !== -1) {
82260			listeners.splice(index, 1);
82261		}
82262
82263		if (listeners.length > 0) {
82264			return;
82265		}
82266
82267		arrayEvents.forEach(function(key) {
82268			delete array[key];
82269		});
82270
82271		delete array._chartjs;
82272	}
82273
82274	// Base class for all dataset controllers (line, bar, etc)
82275	Chart.DatasetController = function(chart, datasetIndex) {
82276		this.initialize(chart, datasetIndex);
82277	};
82278
82279	helpers.extend(Chart.DatasetController.prototype, {
82280
82281		/**
82282		 * Element type used to generate a meta dataset (e.g. Chart.element.Line).
82283		 * @type {Chart.core.element}
82284		 */
82285		datasetElementType: null,
82286
82287		/**
82288		 * Element type used to generate a meta data (e.g. Chart.element.Point).
82289		 * @type {Chart.core.element}
82290		 */
82291		dataElementType: null,
82292
82293		initialize: function(chart, datasetIndex) {
82294			var me = this;
82295			me.chart = chart;
82296			me.index = datasetIndex;
82297			me.linkScales();
82298			me.addElements();
82299		},
82300
82301		updateIndex: function(datasetIndex) {
82302			this.index = datasetIndex;
82303		},
82304
82305		linkScales: function() {
82306			var me = this;
82307			var meta = me.getMeta();
82308			var dataset = me.getDataset();
82309
82310			if (meta.xAxisID === null || !(meta.xAxisID in me.chart.scales)) {
82311				meta.xAxisID = dataset.xAxisID || me.chart.options.scales.xAxes[0].id;
82312			}
82313			if (meta.yAxisID === null || !(meta.yAxisID in me.chart.scales)) {
82314				meta.yAxisID = dataset.yAxisID || me.chart.options.scales.yAxes[0].id;
82315			}
82316		},
82317
82318		getDataset: function() {
82319			return this.chart.data.datasets[this.index];
82320		},
82321
82322		getMeta: function() {
82323			return this.chart.getDatasetMeta(this.index);
82324		},
82325
82326		getScaleForId: function(scaleID) {
82327			return this.chart.scales[scaleID];
82328		},
82329
82330		reset: function() {
82331			this.update(true);
82332		},
82333
82334		/**
82335		 * @private
82336		 */
82337		destroy: function() {
82338			if (this._data) {
82339				unlistenArrayEvents(this._data, this);
82340			}
82341		},
82342
82343		createMetaDataset: function() {
82344			var me = this;
82345			var type = me.datasetElementType;
82346			return type && new type({
82347				_chart: me.chart,
82348				_datasetIndex: me.index
82349			});
82350		},
82351
82352		createMetaData: function(index) {
82353			var me = this;
82354			var type = me.dataElementType;
82355			return type && new type({
82356				_chart: me.chart,
82357				_datasetIndex: me.index,
82358				_index: index
82359			});
82360		},
82361
82362		addElements: function() {
82363			var me = this;
82364			var meta = me.getMeta();
82365			var data = me.getDataset().data || [];
82366			var metaData = meta.data;
82367			var i, ilen;
82368
82369			for (i = 0, ilen = data.length; i < ilen; ++i) {
82370				metaData[i] = metaData[i] || me.createMetaData(i);
82371			}
82372
82373			meta.dataset = meta.dataset || me.createMetaDataset();
82374		},
82375
82376		addElementAndReset: function(index) {
82377			var element = this.createMetaData(index);
82378			this.getMeta().data.splice(index, 0, element);
82379			this.updateElement(element, index, true);
82380		},
82381
82382		buildOrUpdateElements: function() {
82383			var me = this;
82384			var dataset = me.getDataset();
82385			var data = dataset.data || (dataset.data = []);
82386
82387			// In order to correctly handle data addition/deletion animation (an thus simulate
82388			// real-time charts), we need to monitor these data modifications and synchronize
82389			// the internal meta data accordingly.
82390			if (me._data !== data) {
82391				if (me._data) {
82392					// This case happens when the user replaced the data array instance.
82393					unlistenArrayEvents(me._data, me);
82394				}
82395
82396				listenArrayEvents(data, me);
82397				me._data = data;
82398			}
82399
82400			// Re-sync meta data in case the user replaced the data array or if we missed
82401			// any updates and so make sure that we handle number of datapoints changing.
82402			me.resyncElements();
82403		},
82404
82405		update: helpers.noop,
82406
82407		transition: function(easingValue) {
82408			var meta = this.getMeta();
82409			var elements = meta.data || [];
82410			var ilen = elements.length;
82411			var i = 0;
82412
82413			for (; i < ilen; ++i) {
82414				elements[i].transition(easingValue);
82415			}
82416
82417			if (meta.dataset) {
82418				meta.dataset.transition(easingValue);
82419			}
82420		},
82421
82422		draw: function() {
82423			var meta = this.getMeta();
82424			var elements = meta.data || [];
82425			var ilen = elements.length;
82426			var i = 0;
82427
82428			if (meta.dataset) {
82429				meta.dataset.draw();
82430			}
82431
82432			for (; i < ilen; ++i) {
82433				elements[i].draw();
82434			}
82435		},
82436
82437		removeHoverStyle: function(element) {
82438			helpers.merge(element._model, element.$previousStyle || {});
82439			delete element.$previousStyle;
82440		},
82441
82442		setHoverStyle: function(element) {
82443			var dataset = this.chart.data.datasets[element._datasetIndex];
82444			var index = element._index;
82445			var custom = element.custom || {};
82446			var valueOrDefault = helpers.valueAtIndexOrDefault;
82447			var getHoverColor = helpers.getHoverColor;
82448			var model = element._model;
82449
82450			element.$previousStyle = {
82451				backgroundColor: model.backgroundColor,
82452				borderColor: model.borderColor,
82453				borderWidth: model.borderWidth
82454			};
82455
82456			model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : valueOrDefault(dataset.hoverBackgroundColor, index, getHoverColor(model.backgroundColor));
82457			model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : valueOrDefault(dataset.hoverBorderColor, index, getHoverColor(model.borderColor));
82458			model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : valueOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);
82459		},
82460
82461		/**
82462		 * @private
82463		 */
82464		resyncElements: function() {
82465			var me = this;
82466			var meta = me.getMeta();
82467			var data = me.getDataset().data;
82468			var numMeta = meta.data.length;
82469			var numData = data.length;
82470
82471			if (numData < numMeta) {
82472				meta.data.splice(numData, numMeta - numData);
82473			} else if (numData > numMeta) {
82474				me.insertElements(numMeta, numData - numMeta);
82475			}
82476		},
82477
82478		/**
82479		 * @private
82480		 */
82481		insertElements: function(start, count) {
82482			for (var i = 0; i < count; ++i) {
82483				this.addElementAndReset(start + i);
82484			}
82485		},
82486
82487		/**
82488		 * @private
82489		 */
82490		onDataPush: function() {
82491			this.insertElements(this.getDataset().data.length - 1, arguments.length);
82492		},
82493
82494		/**
82495		 * @private
82496		 */
82497		onDataPop: function() {
82498			this.getMeta().data.pop();
82499		},
82500
82501		/**
82502		 * @private
82503		 */
82504		onDataShift: function() {
82505			this.getMeta().data.shift();
82506		},
82507
82508		/**
82509		 * @private
82510		 */
82511		onDataSplice: function(start, count) {
82512			this.getMeta().data.splice(start, count);
82513			this.insertElements(start, arguments.length - 2);
82514		},
82515
82516		/**
82517		 * @private
82518		 */
82519		onDataUnshift: function() {
82520			this.insertElements(0, arguments.length);
82521		}
82522	});
82523
82524	Chart.DatasetController.extend = helpers.inherits;
82525};
82526
82527},{"46":46}],26:[function(require,module,exports){
82528'use strict';
82529
82530var helpers = require(46);
82531
82532module.exports = {
82533	/**
82534	 * @private
82535	 */
82536	_set: function(scope, values) {
82537		return helpers.merge(this[scope] || (this[scope] = {}), values);
82538	}
82539};
82540
82541},{"46":46}],27:[function(require,module,exports){
82542'use strict';
82543
82544var color = require(2);
82545var helpers = require(46);
82546
82547function interpolate(start, view, model, ease) {
82548	var keys = Object.keys(model);
82549	var i, ilen, key, actual, origin, target, type, c0, c1;
82550
82551	for (i = 0, ilen = keys.length; i < ilen; ++i) {
82552		key = keys[i];
82553
82554		target = model[key];
82555
82556		// if a value is added to the model after pivot() has been called, the view
82557		// doesn't contain it, so let's initialize the view to the target value.
82558		if (!view.hasOwnProperty(key)) {
82559			view[key] = target;
82560		}
82561
82562		actual = view[key];
82563
82564		if (actual === target || key[0] === '_') {
82565			continue;
82566		}
82567
82568		if (!start.hasOwnProperty(key)) {
82569			start[key] = actual;
82570		}
82571
82572		origin = start[key];
82573
82574		type = typeof target;
82575
82576		if (type === typeof origin) {
82577			if (type === 'string') {
82578				c0 = color(origin);
82579				if (c0.valid) {
82580					c1 = color(target);
82581					if (c1.valid) {
82582						view[key] = c1.mix(c0, ease).rgbString();
82583						continue;
82584					}
82585				}
82586			} else if (type === 'number' && isFinite(origin) && isFinite(target)) {
82587				view[key] = origin + (target - origin) * ease;
82588				continue;
82589			}
82590		}
82591
82592		view[key] = target;
82593	}
82594}
82595
82596var Element = function(configuration) {
82597	helpers.extend(this, configuration);
82598	this.initialize.apply(this, arguments);
82599};
82600
82601helpers.extend(Element.prototype, {
82602
82603	initialize: function() {
82604		this.hidden = false;
82605	},
82606
82607	pivot: function() {
82608		var me = this;
82609		if (!me._view) {
82610			me._view = helpers.clone(me._model);
82611		}
82612		me._start = {};
82613		return me;
82614	},
82615
82616	transition: function(ease) {
82617		var me = this;
82618		var model = me._model;
82619		var start = me._start;
82620		var view = me._view;
82621
82622		// No animation -> No Transition
82623		if (!model || ease === 1) {
82624			me._view = model;
82625			me._start = null;
82626			return me;
82627		}
82628
82629		if (!view) {
82630			view = me._view = {};
82631		}
82632
82633		if (!start) {
82634			start = me._start = {};
82635		}
82636
82637		interpolate(start, view, model, ease);
82638
82639		return me;
82640	},
82641
82642	tooltipPosition: function() {
82643		return {
82644			x: this._model.x,
82645			y: this._model.y
82646		};
82647	},
82648
82649	hasValue: function() {
82650		return helpers.isNumber(this._model.x) && helpers.isNumber(this._model.y);
82651	}
82652});
82653
82654Element.extend = helpers.inherits;
82655
82656module.exports = Element;
82657
82658},{"2":2,"46":46}],28:[function(require,module,exports){
82659/* global window: false */
82660/* global document: false */
82661'use strict';
82662
82663var color = require(2);
82664var defaults = require(26);
82665var helpers = require(46);
82666var scaleService = require(34);
82667
82668module.exports = function() {
82669
82670	// -- Basic js utility methods
82671
82672	helpers.configMerge = function(/* objects ... */) {
82673		return helpers.merge(helpers.clone(arguments[0]), [].slice.call(arguments, 1), {
82674			merger: function(key, target, source, options) {
82675				var tval = target[key] || {};
82676				var sval = source[key];
82677
82678				if (key === 'scales') {
82679					// scale config merging is complex. Add our own function here for that
82680					target[key] = helpers.scaleMerge(tval, sval);
82681				} else if (key === 'scale') {
82682					// used in polar area & radar charts since there is only one scale
82683					target[key] = helpers.merge(tval, [scaleService.getScaleDefaults(sval.type), sval]);
82684				} else {
82685					helpers._merger(key, target, source, options);
82686				}
82687			}
82688		});
82689	};
82690
82691	helpers.scaleMerge = function(/* objects ... */) {
82692		return helpers.merge(helpers.clone(arguments[0]), [].slice.call(arguments, 1), {
82693			merger: function(key, target, source, options) {
82694				if (key === 'xAxes' || key === 'yAxes') {
82695					var slen = source[key].length;
82696					var i, type, scale;
82697
82698					if (!target[key]) {
82699						target[key] = [];
82700					}
82701
82702					for (i = 0; i < slen; ++i) {
82703						scale = source[key][i];
82704						type = helpers.valueOrDefault(scale.type, key === 'xAxes' ? 'category' : 'linear');
82705
82706						if (i >= target[key].length) {
82707							target[key].push({});
82708						}
82709
82710						if (!target[key][i].type || (scale.type && scale.type !== target[key][i].type)) {
82711							// new/untyped scale or type changed: let's apply the new defaults
82712							// then merge source scale to correctly overwrite the defaults.
82713							helpers.merge(target[key][i], [scaleService.getScaleDefaults(type), scale]);
82714						} else {
82715							// scales type are the same
82716							helpers.merge(target[key][i], scale);
82717						}
82718					}
82719				} else {
82720					helpers._merger(key, target, source, options);
82721				}
82722			}
82723		});
82724	};
82725
82726	helpers.where = function(collection, filterCallback) {
82727		if (helpers.isArray(collection) && Array.prototype.filter) {
82728			return collection.filter(filterCallback);
82729		}
82730		var filtered = [];
82731
82732		helpers.each(collection, function(item) {
82733			if (filterCallback(item)) {
82734				filtered.push(item);
82735			}
82736		});
82737
82738		return filtered;
82739	};
82740	helpers.findIndex = Array.prototype.findIndex ?
82741		function(array, callback, scope) {
82742			return array.findIndex(callback, scope);
82743		} :
82744		function(array, callback, scope) {
82745			scope = scope === undefined ? array : scope;
82746			for (var i = 0, ilen = array.length; i < ilen; ++i) {
82747				if (callback.call(scope, array[i], i, array)) {
82748					return i;
82749				}
82750			}
82751			return -1;
82752		};
82753	helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex) {
82754		// Default to start of the array
82755		if (helpers.isNullOrUndef(startIndex)) {
82756			startIndex = -1;
82757		}
82758		for (var i = startIndex + 1; i < arrayToSearch.length; i++) {
82759			var currentItem = arrayToSearch[i];
82760			if (filterCallback(currentItem)) {
82761				return currentItem;
82762			}
82763		}
82764	};
82765	helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex) {
82766		// Default to end of the array
82767		if (helpers.isNullOrUndef(startIndex)) {
82768			startIndex = arrayToSearch.length;
82769		}
82770		for (var i = startIndex - 1; i >= 0; i--) {
82771			var currentItem = arrayToSearch[i];
82772			if (filterCallback(currentItem)) {
82773				return currentItem;
82774			}
82775		}
82776	};
82777
82778	// -- Math methods
82779	helpers.isNumber = function(n) {
82780		return !isNaN(parseFloat(n)) && isFinite(n);
82781	};
82782	helpers.almostEquals = function(x, y, epsilon) {
82783		return Math.abs(x - y) < epsilon;
82784	};
82785	helpers.almostWhole = function(x, epsilon) {
82786		var rounded = Math.round(x);
82787		return (((rounded - epsilon) < x) && ((rounded + epsilon) > x));
82788	};
82789	helpers.max = function(array) {
82790		return array.reduce(function(max, value) {
82791			if (!isNaN(value)) {
82792				return Math.max(max, value);
82793			}
82794			return max;
82795		}, Number.NEGATIVE_INFINITY);
82796	};
82797	helpers.min = function(array) {
82798		return array.reduce(function(min, value) {
82799			if (!isNaN(value)) {
82800				return Math.min(min, value);
82801			}
82802			return min;
82803		}, Number.POSITIVE_INFINITY);
82804	};
82805	helpers.sign = Math.sign ?
82806		function(x) {
82807			return Math.sign(x);
82808		} :
82809		function(x) {
82810			x = +x; // convert to a number
82811			if (x === 0 || isNaN(x)) {
82812				return x;
82813			}
82814			return x > 0 ? 1 : -1;
82815		};
82816	helpers.log10 = Math.log10 ?
82817		function(x) {
82818			return Math.log10(x);
82819		} :
82820		function(x) {
82821			var exponent = Math.log(x) * Math.LOG10E; // Math.LOG10E = 1 / Math.LN10.
82822			// Check for whole powers of 10,
82823			// which due to floating point rounding error should be corrected.
82824			var powerOf10 = Math.round(exponent);
82825			var isPowerOf10 = x === Math.pow(10, powerOf10);
82826
82827			return isPowerOf10 ? powerOf10 : exponent;
82828		};
82829	helpers.toRadians = function(degrees) {
82830		return degrees * (Math.PI / 180);
82831	};
82832	helpers.toDegrees = function(radians) {
82833		return radians * (180 / Math.PI);
82834	};
82835	// Gets the angle from vertical upright to the point about a centre.
82836	helpers.getAngleFromPoint = function(centrePoint, anglePoint) {
82837		var distanceFromXCenter = anglePoint.x - centrePoint.x;
82838		var distanceFromYCenter = anglePoint.y - centrePoint.y;
82839		var radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);
82840
82841		var angle = Math.atan2(distanceFromYCenter, distanceFromXCenter);
82842
82843		if (angle < (-0.5 * Math.PI)) {
82844			angle += 2.0 * Math.PI; // make sure the returned angle is in the range of (-PI/2, 3PI/2]
82845		}
82846
82847		return {
82848			angle: angle,
82849			distance: radialDistanceFromCenter
82850		};
82851	};
82852	helpers.distanceBetweenPoints = function(pt1, pt2) {
82853		return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2));
82854	};
82855	helpers.aliasPixel = function(pixelWidth) {
82856		return (pixelWidth % 2 === 0) ? 0 : 0.5;
82857	};
82858	helpers.splineCurve = function(firstPoint, middlePoint, afterPoint, t) {
82859		// Props to Rob Spencer at scaled innovation for his post on splining between points
82860		// http://scaledinnovation.com/analytics/splines/aboutSplines.html
82861
82862		// This function must also respect "skipped" points
82863
82864		var previous = firstPoint.skip ? middlePoint : firstPoint;
82865		var current = middlePoint;
82866		var next = afterPoint.skip ? middlePoint : afterPoint;
82867
82868		var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2));
82869		var d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2));
82870
82871		var s01 = d01 / (d01 + d12);
82872		var s12 = d12 / (d01 + d12);
82873
82874		// If all points are the same, s01 & s02 will be inf
82875		s01 = isNaN(s01) ? 0 : s01;
82876		s12 = isNaN(s12) ? 0 : s12;
82877
82878		var fa = t * s01; // scaling factor for triangle Ta
82879		var fb = t * s12;
82880
82881		return {
82882			previous: {
82883				x: current.x - fa * (next.x - previous.x),
82884				y: current.y - fa * (next.y - previous.y)
82885			},
82886			next: {
82887				x: current.x + fb * (next.x - previous.x),
82888				y: current.y + fb * (next.y - previous.y)
82889			}
82890		};
82891	};
82892	helpers.EPSILON = Number.EPSILON || 1e-14;
82893	helpers.splineCurveMonotone = function(points) {
82894		// This function calculates Bézier control points in a similar way than |splineCurve|,
82895		// but preserves monotonicity of the provided data and ensures no local extremums are added
82896		// between the dataset discrete points due to the interpolation.
82897		// See : https://en.wikipedia.org/wiki/Monotone_cubic_interpolation
82898
82899		var pointsWithTangents = (points || []).map(function(point) {
82900			return {
82901				model: point._model,
82902				deltaK: 0,
82903				mK: 0
82904			};
82905		});
82906
82907		// Calculate slopes (deltaK) and initialize tangents (mK)
82908		var pointsLen = pointsWithTangents.length;
82909		var i, pointBefore, pointCurrent, pointAfter;
82910		for (i = 0; i < pointsLen; ++i) {
82911			pointCurrent = pointsWithTangents[i];
82912			if (pointCurrent.model.skip) {
82913				continue;
82914			}
82915
82916			pointBefore = i > 0 ? pointsWithTangents[i - 1] : null;
82917			pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null;
82918			if (pointAfter && !pointAfter.model.skip) {
82919				var slopeDeltaX = (pointAfter.model.x - pointCurrent.model.x);
82920
82921				// In the case of two points that appear at the same x pixel, slopeDeltaX is 0
82922				pointCurrent.deltaK = slopeDeltaX !== 0 ? (pointAfter.model.y - pointCurrent.model.y) / slopeDeltaX : 0;
82923			}
82924
82925			if (!pointBefore || pointBefore.model.skip) {
82926				pointCurrent.mK = pointCurrent.deltaK;
82927			} else if (!pointAfter || pointAfter.model.skip) {
82928				pointCurrent.mK = pointBefore.deltaK;
82929			} else if (this.sign(pointBefore.deltaK) !== this.sign(pointCurrent.deltaK)) {
82930				pointCurrent.mK = 0;
82931			} else {
82932				pointCurrent.mK = (pointBefore.deltaK + pointCurrent.deltaK) / 2;
82933			}
82934		}
82935
82936		// Adjust tangents to ensure monotonic properties
82937		var alphaK, betaK, tauK, squaredMagnitude;
82938		for (i = 0; i < pointsLen - 1; ++i) {
82939			pointCurrent = pointsWithTangents[i];
82940			pointAfter = pointsWithTangents[i + 1];
82941			if (pointCurrent.model.skip || pointAfter.model.skip) {
82942				continue;
82943			}
82944
82945			if (helpers.almostEquals(pointCurrent.deltaK, 0, this.EPSILON)) {
82946				pointCurrent.mK = pointAfter.mK = 0;
82947				continue;
82948			}
82949
82950			alphaK = pointCurrent.mK / pointCurrent.deltaK;
82951			betaK = pointAfter.mK / pointCurrent.deltaK;
82952			squaredMagnitude = Math.pow(alphaK, 2) + Math.pow(betaK, 2);
82953			if (squaredMagnitude <= 9) {
82954				continue;
82955			}
82956
82957			tauK = 3 / Math.sqrt(squaredMagnitude);
82958			pointCurrent.mK = alphaK * tauK * pointCurrent.deltaK;
82959			pointAfter.mK = betaK * tauK * pointCurrent.deltaK;
82960		}
82961
82962		// Compute control points
82963		var deltaX;
82964		for (i = 0; i < pointsLen; ++i) {
82965			pointCurrent = pointsWithTangents[i];
82966			if (pointCurrent.model.skip) {
82967				continue;
82968			}
82969
82970			pointBefore = i > 0 ? pointsWithTangents[i - 1] : null;
82971			pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null;
82972			if (pointBefore && !pointBefore.model.skip) {
82973				deltaX = (pointCurrent.model.x - pointBefore.model.x) / 3;
82974				pointCurrent.model.controlPointPreviousX = pointCurrent.model.x - deltaX;
82975				pointCurrent.model.controlPointPreviousY = pointCurrent.model.y - deltaX * pointCurrent.mK;
82976			}
82977			if (pointAfter && !pointAfter.model.skip) {
82978				deltaX = (pointAfter.model.x - pointCurrent.model.x) / 3;
82979				pointCurrent.model.controlPointNextX = pointCurrent.model.x + deltaX;
82980				pointCurrent.model.controlPointNextY = pointCurrent.model.y + deltaX * pointCurrent.mK;
82981			}
82982		}
82983	};
82984	helpers.nextItem = function(collection, index, loop) {
82985		if (loop) {
82986			return index >= collection.length - 1 ? collection[0] : collection[index + 1];
82987		}
82988		return index >= collection.length - 1 ? collection[collection.length - 1] : collection[index + 1];
82989	};
82990	helpers.previousItem = function(collection, index, loop) {
82991		if (loop) {
82992			return index <= 0 ? collection[collection.length - 1] : collection[index - 1];
82993		}
82994		return index <= 0 ? collection[0] : collection[index - 1];
82995	};
82996	// Implementation of the nice number algorithm used in determining where axis labels will go
82997	helpers.niceNum = function(range, round) {
82998		var exponent = Math.floor(helpers.log10(range));
82999		var fraction = range / Math.pow(10, exponent);
83000		var niceFraction;
83001
83002		if (round) {
83003			if (fraction < 1.5) {
83004				niceFraction = 1;
83005			} else if (fraction < 3) {
83006				niceFraction = 2;
83007			} else if (fraction < 7) {
83008				niceFraction = 5;
83009			} else {
83010				niceFraction = 10;
83011			}
83012		} else if (fraction <= 1.0) {
83013			niceFraction = 1;
83014		} else if (fraction <= 2) {
83015			niceFraction = 2;
83016		} else if (fraction <= 5) {
83017			niceFraction = 5;
83018		} else {
83019			niceFraction = 10;
83020		}
83021
83022		return niceFraction * Math.pow(10, exponent);
83023	};
83024	// Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
83025	helpers.requestAnimFrame = (function() {
83026		if (typeof window === 'undefined') {
83027			return function(callback) {
83028				callback();
83029			};
83030		}
83031		return window.requestAnimationFrame ||
83032			window.webkitRequestAnimationFrame ||
83033			window.mozRequestAnimationFrame ||
83034			window.oRequestAnimationFrame ||
83035			window.msRequestAnimationFrame ||
83036			function(callback) {
83037				return window.setTimeout(callback, 1000 / 60);
83038			};
83039	}());
83040	// -- DOM methods
83041	helpers.getRelativePosition = function(evt, chart) {
83042		var mouseX, mouseY;
83043		var e = evt.originalEvent || evt;
83044		var canvas = evt.target || evt.srcElement;
83045		var boundingRect = canvas.getBoundingClientRect();
83046
83047		var touches = e.touches;
83048		if (touches && touches.length > 0) {
83049			mouseX = touches[0].clientX;
83050			mouseY = touches[0].clientY;
83051
83052		} else {
83053			mouseX = e.clientX;
83054			mouseY = e.clientY;
83055		}
83056
83057		// Scale mouse coordinates into canvas coordinates
83058		// by following the pattern laid out by 'jerryj' in the comments of
83059		// http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/
83060		var paddingLeft = parseFloat(helpers.getStyle(canvas, 'padding-left'));
83061		var paddingTop = parseFloat(helpers.getStyle(canvas, 'padding-top'));
83062		var paddingRight = parseFloat(helpers.getStyle(canvas, 'padding-right'));
83063		var paddingBottom = parseFloat(helpers.getStyle(canvas, 'padding-bottom'));
83064		var width = boundingRect.right - boundingRect.left - paddingLeft - paddingRight;
83065		var height = boundingRect.bottom - boundingRect.top - paddingTop - paddingBottom;
83066
83067		// We divide by the current device pixel ratio, because the canvas is scaled up by that amount in each direction. However
83068		// the backend model is in unscaled coordinates. Since we are going to deal with our model coordinates, we go back here
83069		mouseX = Math.round((mouseX - boundingRect.left - paddingLeft) / (width) * canvas.width / chart.currentDevicePixelRatio);
83070		mouseY = Math.round((mouseY - boundingRect.top - paddingTop) / (height) * canvas.height / chart.currentDevicePixelRatio);
83071
83072		return {
83073			x: mouseX,
83074			y: mouseY
83075		};
83076
83077	};
83078
83079	// Private helper function to convert max-width/max-height values that may be percentages into a number
83080	function parseMaxStyle(styleValue, node, parentProperty) {
83081		var valueInPixels;
83082		if (typeof styleValue === 'string') {
83083			valueInPixels = parseInt(styleValue, 10);
83084
83085			if (styleValue.indexOf('%') !== -1) {
83086				// percentage * size in dimension
83087				valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty];
83088			}
83089		} else {
83090			valueInPixels = styleValue;
83091		}
83092
83093		return valueInPixels;
83094	}
83095
83096	/**
83097	 * Returns if the given value contains an effective constraint.
83098	 * @private
83099	 */
83100	function isConstrainedValue(value) {
83101		return value !== undefined && value !== null && value !== 'none';
83102	}
83103
83104	// Private helper to get a constraint dimension
83105	// @param domNode : the node to check the constraint on
83106	// @param maxStyle : the style that defines the maximum for the direction we are using (maxWidth / maxHeight)
83107	// @param percentageProperty : property of parent to use when calculating width as a percentage
83108	// @see http://www.nathanaeljones.com/blog/2013/reading-max-width-cross-browser
83109	function getConstraintDimension(domNode, maxStyle, percentageProperty) {
83110		var view = document.defaultView;
83111		var parentNode = helpers._getParentNode(domNode);
83112		var constrainedNode = view.getComputedStyle(domNode)[maxStyle];
83113		var constrainedContainer = view.getComputedStyle(parentNode)[maxStyle];
83114		var hasCNode = isConstrainedValue(constrainedNode);
83115		var hasCContainer = isConstrainedValue(constrainedContainer);
83116		var infinity = Number.POSITIVE_INFINITY;
83117
83118		if (hasCNode || hasCContainer) {
83119			return Math.min(
83120				hasCNode ? parseMaxStyle(constrainedNode, domNode, percentageProperty) : infinity,
83121				hasCContainer ? parseMaxStyle(constrainedContainer, parentNode, percentageProperty) : infinity);
83122		}
83123
83124		return 'none';
83125	}
83126	// returns Number or undefined if no constraint
83127	helpers.getConstraintWidth = function(domNode) {
83128		return getConstraintDimension(domNode, 'max-width', 'clientWidth');
83129	};
83130	// returns Number or undefined if no constraint
83131	helpers.getConstraintHeight = function(domNode) {
83132		return getConstraintDimension(domNode, 'max-height', 'clientHeight');
83133	};
83134	/**
83135	 * @private
83136 	 */
83137	helpers._calculatePadding = function(container, padding, parentDimension) {
83138		padding = helpers.getStyle(container, padding);
83139
83140		return padding.indexOf('%') > -1 ? parentDimension / parseInt(padding, 10) : parseInt(padding, 10);
83141	};
83142	/**
83143	 * @private
83144	 */
83145	helpers._getParentNode = function(domNode) {
83146		var parent = domNode.parentNode;
83147		if (parent && parent.host) {
83148			parent = parent.host;
83149		}
83150		return parent;
83151	};
83152	helpers.getMaximumWidth = function(domNode) {
83153		var container = helpers._getParentNode(domNode);
83154		if (!container) {
83155			return domNode.clientWidth;
83156		}
83157
83158		var clientWidth = container.clientWidth;
83159		var paddingLeft = helpers._calculatePadding(container, 'padding-left', clientWidth);
83160		var paddingRight = helpers._calculatePadding(container, 'padding-right', clientWidth);
83161
83162		var w = clientWidth - paddingLeft - paddingRight;
83163		var cw = helpers.getConstraintWidth(domNode);
83164		return isNaN(cw) ? w : Math.min(w, cw);
83165	};
83166	helpers.getMaximumHeight = function(domNode) {
83167		var container = helpers._getParentNode(domNode);
83168		if (!container) {
83169			return domNode.clientHeight;
83170		}
83171
83172		var clientHeight = container.clientHeight;
83173		var paddingTop = helpers._calculatePadding(container, 'padding-top', clientHeight);
83174		var paddingBottom = helpers._calculatePadding(container, 'padding-bottom', clientHeight);
83175
83176		var h = clientHeight - paddingTop - paddingBottom;
83177		var ch = helpers.getConstraintHeight(domNode);
83178		return isNaN(ch) ? h : Math.min(h, ch);
83179	};
83180	helpers.getStyle = function(el, property) {
83181		return el.currentStyle ?
83182			el.currentStyle[property] :
83183			document.defaultView.getComputedStyle(el, null).getPropertyValue(property);
83184	};
83185	helpers.retinaScale = function(chart, forceRatio) {
83186		var pixelRatio = chart.currentDevicePixelRatio = forceRatio || (typeof window !== 'undefined' && window.devicePixelRatio) || 1;
83187		if (pixelRatio === 1) {
83188			return;
83189		}
83190
83191		var canvas = chart.canvas;
83192		var height = chart.height;
83193		var width = chart.width;
83194
83195		canvas.height = height * pixelRatio;
83196		canvas.width = width * pixelRatio;
83197		chart.ctx.scale(pixelRatio, pixelRatio);
83198
83199		// If no style has been set on the canvas, the render size is used as display size,
83200		// making the chart visually bigger, so let's enforce it to the "correct" values.
83201		// See https://github.com/chartjs/Chart.js/issues/3575
83202		if (!canvas.style.height && !canvas.style.width) {
83203			canvas.style.height = height + 'px';
83204			canvas.style.width = width + 'px';
83205		}
83206	};
83207	// -- Canvas methods
83208	helpers.fontString = function(pixelSize, fontStyle, fontFamily) {
83209		return fontStyle + ' ' + pixelSize + 'px ' + fontFamily;
83210	};
83211	helpers.longestText = function(ctx, font, arrayOfThings, cache) {
83212		cache = cache || {};
83213		var data = cache.data = cache.data || {};
83214		var gc = cache.garbageCollect = cache.garbageCollect || [];
83215
83216		if (cache.font !== font) {
83217			data = cache.data = {};
83218			gc = cache.garbageCollect = [];
83219			cache.font = font;
83220		}
83221
83222		ctx.font = font;
83223		var longest = 0;
83224		helpers.each(arrayOfThings, function(thing) {
83225			// Undefined strings and arrays should not be measured
83226			if (thing !== undefined && thing !== null && helpers.isArray(thing) !== true) {
83227				longest = helpers.measureText(ctx, data, gc, longest, thing);
83228			} else if (helpers.isArray(thing)) {
83229				// if it is an array lets measure each element
83230				// to do maybe simplify this function a bit so we can do this more recursively?
83231				helpers.each(thing, function(nestedThing) {
83232					// Undefined strings and arrays should not be measured
83233					if (nestedThing !== undefined && nestedThing !== null && !helpers.isArray(nestedThing)) {
83234						longest = helpers.measureText(ctx, data, gc, longest, nestedThing);
83235					}
83236				});
83237			}
83238		});
83239
83240		var gcLen = gc.length / 2;
83241		if (gcLen > arrayOfThings.length) {
83242			for (var i = 0; i < gcLen; i++) {
83243				delete data[gc[i]];
83244			}
83245			gc.splice(0, gcLen);
83246		}
83247		return longest;
83248	};
83249	helpers.measureText = function(ctx, data, gc, longest, string) {
83250		var textWidth = data[string];
83251		if (!textWidth) {
83252			textWidth = data[string] = ctx.measureText(string).width;
83253			gc.push(string);
83254		}
83255		if (textWidth > longest) {
83256			longest = textWidth;
83257		}
83258		return longest;
83259	};
83260	helpers.numberOfLabelLines = function(arrayOfThings) {
83261		var numberOfLines = 1;
83262		helpers.each(arrayOfThings, function(thing) {
83263			if (helpers.isArray(thing)) {
83264				if (thing.length > numberOfLines) {
83265					numberOfLines = thing.length;
83266				}
83267			}
83268		});
83269		return numberOfLines;
83270	};
83271
83272	helpers.color = !color ?
83273		function(value) {
83274			console.error('Color.js not found!');
83275			return value;
83276		} :
83277		function(value) {
83278			/* global CanvasGradient */
83279			if (value instanceof CanvasGradient) {
83280				value = defaults.global.defaultColor;
83281			}
83282
83283			return color(value);
83284		};
83285
83286	helpers.getHoverColor = function(colorValue) {
83287		/* global CanvasPattern */
83288		return (colorValue instanceof CanvasPattern) ?
83289			colorValue :
83290			helpers.color(colorValue).saturate(0.5).darken(0.1).rgbString();
83291	};
83292};
83293
83294},{"2":2,"26":26,"34":34,"46":46}],29:[function(require,module,exports){
83295'use strict';
83296
83297var helpers = require(46);
83298
83299/**
83300 * Helper function to get relative position for an event
83301 * @param {Event|IEvent} event - The event to get the position for
83302 * @param {Chart} chart - The chart
83303 * @returns {Point} the event position
83304 */
83305function getRelativePosition(e, chart) {
83306	if (e.native) {
83307		return {
83308			x: e.x,
83309			y: e.y
83310		};
83311	}
83312
83313	return helpers.getRelativePosition(e, chart);
83314}
83315
83316/**
83317 * Helper function to traverse all of the visible elements in the chart
83318 * @param chart {chart} the chart
83319 * @param handler {Function} the callback to execute for each visible item
83320 */
83321function parseVisibleItems(chart, handler) {
83322	var datasets = chart.data.datasets;
83323	var meta, i, j, ilen, jlen;
83324
83325	for (i = 0, ilen = datasets.length; i < ilen; ++i) {
83326		if (!chart.isDatasetVisible(i)) {
83327			continue;
83328		}
83329
83330		meta = chart.getDatasetMeta(i);
83331		for (j = 0, jlen = meta.data.length; j < jlen; ++j) {
83332			var element = meta.data[j];
83333			if (!element._view.skip) {
83334				handler(element);
83335			}
83336		}
83337	}
83338}
83339
83340/**
83341 * Helper function to get the items that intersect the event position
83342 * @param items {ChartElement[]} elements to filter
83343 * @param position {Point} the point to be nearest to
83344 * @return {ChartElement[]} the nearest items
83345 */
83346function getIntersectItems(chart, position) {
83347	var elements = [];
83348
83349	parseVisibleItems(chart, function(element) {
83350		if (element.inRange(position.x, position.y)) {
83351			elements.push(element);
83352		}
83353	});
83354
83355	return elements;
83356}
83357
83358/**
83359 * Helper function to get the items nearest to the event position considering all visible items in teh chart
83360 * @param chart {Chart} the chart to look at elements from
83361 * @param position {Point} the point to be nearest to
83362 * @param intersect {Boolean} if true, only consider items that intersect the position
83363 * @param distanceMetric {Function} function to provide the distance between points
83364 * @return {ChartElement[]} the nearest items
83365 */
83366function getNearestItems(chart, position, intersect, distanceMetric) {
83367	var minDistance = Number.POSITIVE_INFINITY;
83368	var nearestItems = [];
83369
83370	parseVisibleItems(chart, function(element) {
83371		if (intersect && !element.inRange(position.x, position.y)) {
83372			return;
83373		}
83374
83375		var center = element.getCenterPoint();
83376		var distance = distanceMetric(position, center);
83377
83378		if (distance < minDistance) {
83379			nearestItems = [element];
83380			minDistance = distance;
83381		} else if (distance === minDistance) {
83382			// Can have multiple items at the same distance in which case we sort by size
83383			nearestItems.push(element);
83384		}
83385	});
83386
83387	return nearestItems;
83388}
83389
83390/**
83391 * Get a distance metric function for two points based on the
83392 * axis mode setting
83393 * @param {String} axis the axis mode. x|y|xy
83394 */
83395function getDistanceMetricForAxis(axis) {
83396	var useX = axis.indexOf('x') !== -1;
83397	var useY = axis.indexOf('y') !== -1;
83398
83399	return function(pt1, pt2) {
83400		var deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0;
83401		var deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0;
83402		return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
83403	};
83404}
83405
83406function indexMode(chart, e, options) {
83407	var position = getRelativePosition(e, chart);
83408	// Default axis for index mode is 'x' to match old behaviour
83409	options.axis = options.axis || 'x';
83410	var distanceMetric = getDistanceMetricForAxis(options.axis);
83411	var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric);
83412	var elements = [];
83413
83414	if (!items.length) {
83415		return [];
83416	}
83417
83418	chart.data.datasets.forEach(function(dataset, datasetIndex) {
83419		if (chart.isDatasetVisible(datasetIndex)) {
83420			var meta = chart.getDatasetMeta(datasetIndex);
83421			var element = meta.data[items[0]._index];
83422
83423			// don't count items that are skipped (null data)
83424			if (element && !element._view.skip) {
83425				elements.push(element);
83426			}
83427		}
83428	});
83429
83430	return elements;
83431}
83432
83433/**
83434 * @interface IInteractionOptions
83435 */
83436/**
83437 * If true, only consider items that intersect the point
83438 * @name IInterfaceOptions#boolean
83439 * @type Boolean
83440 */
83441
83442/**
83443 * Contains interaction related functions
83444 * @namespace Chart.Interaction
83445 */
83446module.exports = {
83447	// Helper function for different modes
83448	modes: {
83449		single: function(chart, e) {
83450			var position = getRelativePosition(e, chart);
83451			var elements = [];
83452
83453			parseVisibleItems(chart, function(element) {
83454				if (element.inRange(position.x, position.y)) {
83455					elements.push(element);
83456					return elements;
83457				}
83458			});
83459
83460			return elements.slice(0, 1);
83461		},
83462
83463		/**
83464		 * @function Chart.Interaction.modes.label
83465		 * @deprecated since version 2.4.0
83466		 * @todo remove at version 3
83467		 * @private
83468		 */
83469		label: indexMode,
83470
83471		/**
83472		 * Returns items at the same index. If the options.intersect parameter is true, we only return items if we intersect something
83473		 * If the options.intersect mode is false, we find the nearest item and return the items at the same index as that item
83474		 * @function Chart.Interaction.modes.index
83475		 * @since v2.4.0
83476		 * @param chart {chart} the chart we are returning items from
83477		 * @param e {Event} the event we are find things at
83478		 * @param options {IInteractionOptions} options to use during interaction
83479		 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
83480		 */
83481		index: indexMode,
83482
83483		/**
83484		 * Returns items in the same dataset. If the options.intersect parameter is true, we only return items if we intersect something
83485		 * If the options.intersect is false, we find the nearest item and return the items in that dataset
83486		 * @function Chart.Interaction.modes.dataset
83487		 * @param chart {chart} the chart we are returning items from
83488		 * @param e {Event} the event we are find things at
83489		 * @param options {IInteractionOptions} options to use during interaction
83490		 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
83491		 */
83492		dataset: function(chart, e, options) {
83493			var position = getRelativePosition(e, chart);
83494			options.axis = options.axis || 'xy';
83495			var distanceMetric = getDistanceMetricForAxis(options.axis);
83496			var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric);
83497
83498			if (items.length > 0) {
83499				items = chart.getDatasetMeta(items[0]._datasetIndex).data;
83500			}
83501
83502			return items;
83503		},
83504
83505		/**
83506		 * @function Chart.Interaction.modes.x-axis
83507		 * @deprecated since version 2.4.0. Use index mode and intersect == true
83508		 * @todo remove at version 3
83509		 * @private
83510		 */
83511		'x-axis': function(chart, e) {
83512			return indexMode(chart, e, {intersect: false});
83513		},
83514
83515		/**
83516		 * Point mode returns all elements that hit test based on the event position
83517		 * of the event
83518		 * @function Chart.Interaction.modes.intersect
83519		 * @param chart {chart} the chart we are returning items from
83520		 * @param e {Event} the event we are find things at
83521		 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
83522		 */
83523		point: function(chart, e) {
83524			var position = getRelativePosition(e, chart);
83525			return getIntersectItems(chart, position);
83526		},
83527
83528		/**
83529		 * nearest mode returns the element closest to the point
83530		 * @function Chart.Interaction.modes.intersect
83531		 * @param chart {chart} the chart we are returning items from
83532		 * @param e {Event} the event we are find things at
83533		 * @param options {IInteractionOptions} options to use
83534		 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
83535		 */
83536		nearest: function(chart, e, options) {
83537			var position = getRelativePosition(e, chart);
83538			options.axis = options.axis || 'xy';
83539			var distanceMetric = getDistanceMetricForAxis(options.axis);
83540			var nearestItems = getNearestItems(chart, position, options.intersect, distanceMetric);
83541
83542			// We have multiple items at the same distance from the event. Now sort by smallest
83543			if (nearestItems.length > 1) {
83544				nearestItems.sort(function(a, b) {
83545					var sizeA = a.getArea();
83546					var sizeB = b.getArea();
83547					var ret = sizeA - sizeB;
83548
83549					if (ret === 0) {
83550						// if equal sort by dataset index
83551						ret = a._datasetIndex - b._datasetIndex;
83552					}
83553
83554					return ret;
83555				});
83556			}
83557
83558			// Return only 1 item
83559			return nearestItems.slice(0, 1);
83560		},
83561
83562		/**
83563		 * x mode returns the elements that hit-test at the current x coordinate
83564		 * @function Chart.Interaction.modes.x
83565		 * @param chart {chart} the chart we are returning items from
83566		 * @param e {Event} the event we are find things at
83567		 * @param options {IInteractionOptions} options to use
83568		 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
83569		 */
83570		x: function(chart, e, options) {
83571			var position = getRelativePosition(e, chart);
83572			var items = [];
83573			var intersectsItem = false;
83574
83575			parseVisibleItems(chart, function(element) {
83576				if (element.inXRange(position.x)) {
83577					items.push(element);
83578				}
83579
83580				if (element.inRange(position.x, position.y)) {
83581					intersectsItem = true;
83582				}
83583			});
83584
83585			// If we want to trigger on an intersect and we don't have any items
83586			// that intersect the position, return nothing
83587			if (options.intersect && !intersectsItem) {
83588				items = [];
83589			}
83590			return items;
83591		},
83592
83593		/**
83594		 * y mode returns the elements that hit-test at the current y coordinate
83595		 * @function Chart.Interaction.modes.y
83596		 * @param chart {chart} the chart we are returning items from
83597		 * @param e {Event} the event we are find things at
83598		 * @param options {IInteractionOptions} options to use
83599		 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
83600		 */
83601		y: function(chart, e, options) {
83602			var position = getRelativePosition(e, chart);
83603			var items = [];
83604			var intersectsItem = false;
83605
83606			parseVisibleItems(chart, function(element) {
83607				if (element.inYRange(position.y)) {
83608					items.push(element);
83609				}
83610
83611				if (element.inRange(position.x, position.y)) {
83612					intersectsItem = true;
83613				}
83614			});
83615
83616			// If we want to trigger on an intersect and we don't have any items
83617			// that intersect the position, return nothing
83618			if (options.intersect && !intersectsItem) {
83619				items = [];
83620			}
83621			return items;
83622		}
83623	}
83624};
83625
83626},{"46":46}],30:[function(require,module,exports){
83627'use strict';
83628
83629var defaults = require(26);
83630
83631defaults._set('global', {
83632	responsive: true,
83633	responsiveAnimationDuration: 0,
83634	maintainAspectRatio: true,
83635	events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'],
83636	hover: {
83637		onHover: null,
83638		mode: 'nearest',
83639		intersect: true,
83640		animationDuration: 400
83641	},
83642	onClick: null,
83643	defaultColor: 'rgba(0,0,0,0.1)',
83644	defaultFontColor: '#666',
83645	defaultFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
83646	defaultFontSize: 12,
83647	defaultFontStyle: 'normal',
83648	showLines: true,
83649
83650	// Element defaults defined in element extensions
83651	elements: {},
83652
83653	// Layout options such as padding
83654	layout: {
83655		padding: {
83656			top: 0,
83657			right: 0,
83658			bottom: 0,
83659			left: 0
83660		}
83661	}
83662});
83663
83664module.exports = function() {
83665
83666	// Occupy the global variable of Chart, and create a simple base class
83667	var Chart = function(item, config) {
83668		this.construct(item, config);
83669		return this;
83670	};
83671
83672	Chart.Chart = Chart;
83673
83674	return Chart;
83675};
83676
83677},{"26":26}],31:[function(require,module,exports){
83678'use strict';
83679
83680var helpers = require(46);
83681
83682function filterByPosition(array, position) {
83683	return helpers.where(array, function(v) {
83684		return v.position === position;
83685	});
83686}
83687
83688function sortByWeight(array, reverse) {
83689	array.forEach(function(v, i) {
83690		v._tmpIndex_ = i;
83691		return v;
83692	});
83693	array.sort(function(a, b) {
83694		var v0 = reverse ? b : a;
83695		var v1 = reverse ? a : b;
83696		return v0.weight === v1.weight ?
83697			v0._tmpIndex_ - v1._tmpIndex_ :
83698			v0.weight - v1.weight;
83699	});
83700	array.forEach(function(v) {
83701		delete v._tmpIndex_;
83702	});
83703}
83704
83705/**
83706 * @interface ILayoutItem
83707 * @prop {String} position - The position of the item in the chart layout. Possible values are
83708 * 'left', 'top', 'right', 'bottom', and 'chartArea'
83709 * @prop {Number} weight - The weight used to sort the item. Higher weights are further away from the chart area
83710 * @prop {Boolean} fullWidth - if true, and the item is horizontal, then push vertical boxes down
83711 * @prop {Function} isHorizontal - returns true if the layout item is horizontal (ie. top or bottom)
83712 * @prop {Function} update - Takes two parameters: width and height. Returns size of item
83713 * @prop {Function} getPadding -  Returns an object with padding on the edges
83714 * @prop {Number} width - Width of item. Must be valid after update()
83715 * @prop {Number} height - Height of item. Must be valid after update()
83716 * @prop {Number} left - Left edge of the item. Set by layout system and cannot be used in update
83717 * @prop {Number} top - Top edge of the item. Set by layout system and cannot be used in update
83718 * @prop {Number} right - Right edge of the item. Set by layout system and cannot be used in update
83719 * @prop {Number} bottom - Bottom edge of the item. Set by layout system and cannot be used in update
83720 */
83721
83722// The layout service is very self explanatory.  It's responsible for the layout within a chart.
83723// Scales, Legends and Plugins all rely on the layout service and can easily register to be placed anywhere they need
83724// It is this service's responsibility of carrying out that layout.
83725module.exports = {
83726	defaults: {},
83727
83728	/**
83729	 * Register a box to a chart.
83730	 * A box is simply a reference to an object that requires layout. eg. Scales, Legend, Title.
83731	 * @param {Chart} chart - the chart to use
83732	 * @param {ILayoutItem} item - the item to add to be layed out
83733	 */
vendor: 4,520 bytes, lines 83734-83848
83734	addBox: function(chart, item) {
83735		if (!chart.boxes) {
83736			chart.boxes = [];
83737		}
83738
83739		// initialize item with default values
83740		item.fullWidth = item.fullWidth || false;
83741		item.position = item.position || 'top';
83742		item.weight = item.weight || 0;
83743
83744		chart.boxes.push(item);
83745	},
83746
83747	/**
83748	 * Remove a layoutItem from a chart
83749	 * @param {Chart} chart - the chart to remove the box from
83750	 * @param {Object} layoutItem - the item to remove from the layout
83751	 */
83752	removeBox: function(chart, layoutItem) {
83753		var index = chart.boxes ? chart.boxes.indexOf(layoutItem) : -1;
83754		if (index !== -1) {
83755			chart.boxes.splice(index, 1);
83756		}
83757	},
83758
83759	/**
83760	 * Sets (or updates) options on the given `item`.
83761	 * @param {Chart} chart - the chart in which the item lives (or will be added to)
83762	 * @param {Object} item - the item to configure with the given options
83763	 * @param {Object} options - the new item options.
83764	 */
83765	configure: function(chart, item, options) {
83766		var props = ['fullWidth', 'position', 'weight'];
83767		var ilen = props.length;
83768		var i = 0;
83769		var prop;
83770
83771		for (; i < ilen; ++i) {
83772			prop = props[i];
83773			if (options.hasOwnProperty(prop)) {
83774				item[prop] = options[prop];
83775			}
83776		}
83777	},
83778
83779	/**
83780	 * Fits boxes of the given chart into the given size by having each box measure itself
83781	 * then running a fitting algorithm
83782	 * @param {Chart} chart - the chart
83783	 * @param {Number} width - the width to fit into
83784	 * @param {Number} height - the height to fit into
83785	 */
83786	update: function(chart, width, height) {
83787		if (!chart) {
83788			return;
83789		}
83790
83791		var layoutOptions = chart.options.layout || {};
83792		var padding = helpers.options.toPadding(layoutOptions.padding);
83793		var leftPadding = padding.left;
83794		var rightPadding = padding.right;
83795		var topPadding = padding.top;
83796		var bottomPadding = padding.bottom;
83797
83798		var leftBoxes = filterByPosition(chart.boxes, 'left');
83799		var rightBoxes = filterByPosition(chart.boxes, 'right');
83800		var topBoxes = filterByPosition(chart.boxes, 'top');
83801		var bottomBoxes = filterByPosition(chart.boxes, 'bottom');
83802		var chartAreaBoxes = filterByPosition(chart.boxes, 'chartArea');
83803
83804		// Sort boxes by weight. A higher weight is further away from the chart area
83805		sortByWeight(leftBoxes, true);
83806		sortByWeight(rightBoxes, false);
83807		sortByWeight(topBoxes, true);
83808		sortByWeight(bottomBoxes, false);
83809
83810		// Essentially we now have any number of boxes on each of the 4 sides.
83811		// Our canvas looks like the following.
83812		// The areas L1 and L2 are the left axes. R1 is the right axis, T1 is the top axis and
83813		// B1 is the bottom axis
83814		// There are also 4 quadrant-like locations (left to right instead of clockwise) reserved for chart overlays
83815		// These locations are single-box locations only, when trying to register a chartArea location that is already taken,
83816		// an error will be thrown.
83817		//
83818		// |----------------------------------------------------|
83819		// |                  T1 (Full Width)                   |
83820		// |----------------------------------------------------|
83821		// |    |    |                 T2                  |    |
83822		// |    |----|-------------------------------------|----|
83823		// |    |    | C1 |                           | C2 |    |
83824		// |    |    |----|                           |----|    |
83825		// |    |    |                                     |    |
83826		// | L1 | L2 |           ChartArea (C0)            | R1 |
83827		// |    |    |                                     |    |
83828		// |    |    |----|                           |----|    |
83829		// |    |    | C3 |                           | C4 |    |
83830		// |    |----|-------------------------------------|----|
83831		// |    |    |                 B1                  |    |
83832		// |----------------------------------------------------|
83833		// |                  B2 (Full Width)                   |
83834		// |----------------------------------------------------|
83835		//
83836		// What we do to find the best sizing, we do the following
83837		// 1. Determine the minimum size of the chart area.
83838		// 2. Split the remaining width equally between each vertical axis
83839		// 3. Split the remaining height equally between each horizontal axis
83840		// 4. Give each layout the maximum size it can be. The layout will return it's minimum size
83841		// 5. Adjust the sizes of each axis based on it's minimum reported size.
83842		// 6. Refit each axis
83843		// 7. Position each axis in the final location
83844		// 8. Tell the chart the final location of the chart area
83845		// 9. Tell any axes that overlay the chart area the positions of the chart area
83846
83847		// Step 1
83848		var chartWidth = width - leftPadding - rightPadding;
83849		var chartHeight = height - topPadding - bottomPadding;
83850		var chartAreaWidth = chartWidth / 2; // min 50%
83851		var chartAreaHeight = chartHeight / 2; // min 50%
83852
83853		// Step 2
83854		var verticalBoxWidth = (width - chartAreaWidth) / (leftBoxes.length + rightBoxes.length);
83855
83856		// Step 3
83857		var horizontalBoxHeight = (height - chartAreaHeight) / (topBoxes.length + bottomBoxes.length);
83858
83859		// Step 4
83860		var maxChartAreaWidth = chartWidth;
83861		var maxChartAreaHeight = chartHeight;
83862		var minBoxSizes = [];
83863
83864		function getMinimumBoxSize(box) {
83865			var minSize;
83866			var isHorizontal = box.isHorizontal();
83867
83868			if (isHorizontal) {
83869				minSize = box.update(box.fullWidth ? chartWidth : maxChartAreaWidth, horizontalBoxHeight);
83870				maxChartAreaHeight -= minSize.height;
83871			} else {
83872				minSize = box.update(verticalBoxWidth, maxChartAreaHeight);
83873				maxChartAreaWidth -= minSize.width;
83874			}
83875
83876			minBoxSizes.push({
83877				horizontal: isHorizontal,
83878				minSize: minSize,
83879				box: box,
83880			});
83881		}
83882
83883		helpers.each(leftBoxes.concat(rightBoxes, topBoxes, bottomBoxes), getMinimumBoxSize);
83884
83885		// If a horizontal box has padding, we move the left boxes over to avoid ugly charts (see issue #2478)
83886		var maxHorizontalLeftPadding = 0;
83887		var maxHorizontalRightPadding = 0;
83888		var maxVerticalTopPadding = 0;
83889		var maxVerticalBottomPadding = 0;
83890
83891		helpers.each(topBoxes.concat(bottomBoxes), function(horizontalBox) {
83892			if (horizontalBox.getPadding) {
83893				var boxPadding = horizontalBox.getPadding();
83894				maxHorizontalLeftPadding = Math.max(maxHorizontalLeftPadding, boxPadding.left);
83895				maxHorizontalRightPadding = Math.max(maxHorizontalRightPadding, boxPadding.right);
83896			}
83897		});
83898
83899		helpers.each(leftBoxes.concat(rightBoxes), function(verticalBox) {
83900			if (verticalBox.getPadding) {
83901				var boxPadding = verticalBox.getPadding();
83902				maxVerticalTopPadding = Math.max(maxVerticalTopPadding, boxPadding.top);
83903				maxVerticalBottomPadding = Math.max(maxVerticalBottomPadding, boxPadding.bottom);
83904			}
83905		});
83906
83907		// At this point, maxChartAreaHeight and maxChartAreaWidth are the size the chart area could
83908		// be if the axes are drawn at their minimum sizes.
83909		// Steps 5 & 6
83910		var totalLeftBoxesWidth = leftPadding;
83911		var totalRightBoxesWidth = rightPadding;
83912		var totalTopBoxesHeight = topPadding;
83913		var totalBottomBoxesHeight = bottomPadding;
83914
83915		// Function to fit a box
83916		function fitBox(box) {
83917			var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minBox) {
83918				return minBox.box === box;
83919			});
83920
83921			if (minBoxSize) {
83922				if (box.isHorizontal()) {
83923					var scaleMargin = {
83924						left: Math.max(totalLeftBoxesWidth, maxHorizontalLeftPadding),
83925						right: Math.max(totalRightBoxesWidth, maxHorizontalRightPadding),
83926						top: 0,
83927						bottom: 0
83928					};
83929
83930					// Don't use min size here because of label rotation. When the labels are rotated, their rotation highly depends
83931					// on the margin. Sometimes they need to increase in size slightly
83932					box.update(box.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2, scaleMargin);
83933				} else {
83934					box.update(minBoxSize.minSize.width, maxChartAreaHeight);
83935				}
83936			}
83937		}
83938
83939		// Update, and calculate the left and right margins for the horizontal boxes
83940		helpers.each(leftBoxes.concat(rightBoxes), fitBox);
83941
83942		helpers.each(leftBoxes, function(box) {
83943			totalLeftBoxesWidth += box.width;
83944		});
83945
83946		helpers.each(rightBoxes, function(box) {
83947			totalRightBoxesWidth += box.width;
83948		});
83949
83950		// Set the Left and Right margins for the horizontal boxes
83951		helpers.each(topBoxes.concat(bottomBoxes), fitBox);
83952
83953		// Figure out how much margin is on the top and bottom of the vertical boxes
83954		helpers.each(topBoxes, function(box) {
83955			totalTopBoxesHeight += box.height;
83956		});
83957
83958		helpers.each(bottomBoxes, function(box) {
83959			totalBottomBoxesHeight += box.height;
83960		});
83961
83962		function finalFitVerticalBox(box) {
83963			var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minSize) {
83964				return minSize.box === box;
83965			});
83966
83967			var scaleMargin = {
83968				left: 0,
83969				right: 0,
83970				top: totalTopBoxesHeight,
83971				bottom: totalBottomBoxesHeight
83972			};
83973
83974			if (minBoxSize) {
83975				box.update(minBoxSize.minSize.width, maxChartAreaHeight, scaleMargin);
83976			}
83977		}
83978
83979		// Let the left layout know the final margin
83980		helpers.each(leftBoxes.concat(rightBoxes), finalFitVerticalBox);
83981
83982		// Recalculate because the size of each layout might have changed slightly due to the margins (label rotation for instance)
83983		totalLeftBoxesWidth = leftPadding;
83984		totalRightBoxesWidth = rightPadding;
83985		totalTopBoxesHeight = topPadding;
83986		totalBottomBoxesHeight = bottomPadding;
83987
83988		helpers.each(leftBoxes, function(box) {
83989			totalLeftBoxesWidth += box.width;
83990		});
83991
83992		helpers.each(rightBoxes, function(box) {
83993			totalRightBoxesWidth += box.width;
83994		});
83995
83996		helpers.each(topBoxes, function(box) {
83997			totalTopBoxesHeight += box.height;
83998		});
83999		helpers.each(bottomBoxes, function(box) {
84000			totalBottomBoxesHeight += box.height;
84001		});
84002
84003		// We may be adding some padding to account for rotated x axis labels
84004		var leftPaddingAddition = Math.max(maxHorizontalLeftPadding - totalLeftBoxesWidth, 0);
84005		totalLeftBoxesWidth += leftPaddingAddition;
84006		totalRightBoxesWidth += Math.max(maxHorizontalRightPadding - totalRightBoxesWidth, 0);
84007
84008		var topPaddingAddition = Math.max(maxVerticalTopPadding - totalTopBoxesHeight, 0);
84009		totalTopBoxesHeight += topPaddingAddition;
84010		totalBottomBoxesHeight += Math.max(maxVerticalBottomPadding - totalBottomBoxesHeight, 0);
84011
84012		// Figure out if our chart area changed. This would occur if the dataset layout label rotation
84013		// changed due to the application of the margins in step 6. Since we can only get bigger, this is safe to do
84014		// without calling `fit` again
84015		var newMaxChartAreaHeight = height - totalTopBoxesHeight - totalBottomBoxesHeight;
84016		var newMaxChartAreaWidth = width - totalLeftBoxesWidth - totalRightBoxesWidth;
84017
84018		if (newMaxChartAreaWidth !== maxChartAreaWidth || newMaxChartAreaHeight !== maxChartAreaHeight) {
84019			helpers.each(leftBoxes, function(box) {
84020				box.height = newMaxChartAreaHeight;
84021			});
84022
84023			helpers.each(rightBoxes, function(box) {
84024				box.height = newMaxChartAreaHeight;
84025			});
84026
84027			helpers.each(topBoxes, function(box) {
84028				if (!box.fullWidth) {
84029					box.width = newMaxChartAreaWidth;
84030				}
84031			});
84032
84033			helpers.each(bottomBoxes, function(box) {
84034				if (!box.fullWidth) {
84035					box.width = newMaxChartAreaWidth;
84036				}
84037			});
84038
84039			maxChartAreaHeight = newMaxChartAreaHeight;
84040			maxChartAreaWidth = newMaxChartAreaWidth;
84041		}
84042
84043		// Step 7 - Position the boxes
84044		var left = leftPadding + leftPaddingAddition;
84045		var top = topPadding + topPaddingAddition;
84046
84047		function placeBox(box) {
84048			if (box.isHorizontal()) {
84049				box.left = box.fullWidth ? leftPadding : totalLeftBoxesWidth;
84050				box.right = box.fullWidth ? width - rightPadding : totalLeftBoxesWidth + maxChartAreaWidth;
84051				box.top = top;
84052				box.bottom = top + box.height;
84053
84054				// Move to next point
84055				top = box.bottom;
84056
84057			} else {
84058
84059				box.left = left;
84060				box.right = left + box.width;
vendor: 13,547 bytes, lines 84061-84460
84061				box.top = totalTopBoxesHeight;
84062				box.bottom = totalTopBoxesHeight + maxChartAreaHeight;
84063
84064				// Move to next point
84065				left = box.right;
84066			}
84067		}
84068
84069		helpers.each(leftBoxes.concat(topBoxes), placeBox);
84070
84071		// Account for chart width and height
84072		left += maxChartAreaWidth;
84073		top += maxChartAreaHeight;
84074
84075		helpers.each(rightBoxes, placeBox);
84076		helpers.each(bottomBoxes, placeBox);
84077
84078		// Step 8
84079		chart.chartArea = {
84080			left: totalLeftBoxesWidth,
84081			top: totalTopBoxesHeight,
84082			right: totalLeftBoxesWidth + maxChartAreaWidth,
84083			bottom: totalTopBoxesHeight + maxChartAreaHeight
84084		};
84085
84086		// Step 9
84087		helpers.each(chartAreaBoxes, function(box) {
84088			box.left = chart.chartArea.left;
84089			box.top = chart.chartArea.top;
84090			box.right = chart.chartArea.right;
84091			box.bottom = chart.chartArea.bottom;
84092
84093			box.update(maxChartAreaWidth, maxChartAreaHeight);
84094		});
84095	}
84096};
84097
84098},{"46":46}],32:[function(require,module,exports){
84099'use strict';
84100
84101var defaults = require(26);
84102var helpers = require(46);
84103
84104defaults._set('global', {
84105	plugins: {}
84106});
84107
84108/**
84109 * The plugin service singleton
84110 * @namespace Chart.plugins
84111 * @since 2.1.0
84112 */
84113module.exports = {
84114	/**
84115	 * Globally registered plugins.
84116	 * @private
84117	 */
84118	_plugins: [],
84119
84120	/**
84121	 * This identifier is used to invalidate the descriptors cache attached to each chart
84122	 * when a global plugin is registered or unregistered. In this case, the cache ID is
84123	 * incremented and descriptors are regenerated during following API calls.
84124	 * @private
84125	 */
84126	_cacheId: 0,
84127
84128	/**
84129	 * Registers the given plugin(s) if not already registered.
84130	 * @param {Array|Object} plugins plugin instance(s).
84131	 */
84132	register: function(plugins) {
84133		var p = this._plugins;
84134		([]).concat(plugins).forEach(function(plugin) {
84135			if (p.indexOf(plugin) === -1) {
84136				p.push(plugin);
84137			}
84138		});
84139
84140		this._cacheId++;
84141	},
84142
84143	/**
84144	 * Unregisters the given plugin(s) only if registered.
84145	 * @param {Array|Object} plugins plugin instance(s).
84146	 */
84147	unregister: function(plugins) {
84148		var p = this._plugins;
84149		([]).concat(plugins).forEach(function(plugin) {
84150			var idx = p.indexOf(plugin);
84151			if (idx !== -1) {
84152				p.splice(idx, 1);
84153			}
84154		});
84155
84156		this._cacheId++;
84157	},
84158
84159	/**
84160	 * Remove all registered plugins.
84161	 * @since 2.1.5
84162	 */
84163	clear: function() {
84164		this._plugins = [];
84165		this._cacheId++;
84166	},
84167
84168	/**
84169	 * Returns the number of registered plugins?
84170	 * @returns {Number}
84171	 * @since 2.1.5
84172	 */
84173	count: function() {
84174		return this._plugins.length;
84175	},
84176
84177	/**
84178	 * Returns all registered plugin instances.
84179	 * @returns {Array} array of plugin objects.
84180	 * @since 2.1.5
84181	 */
84182	getAll: function() {
84183		return this._plugins;
84184	},
84185
84186	/**
84187	 * Calls enabled plugins for `chart` on the specified hook and with the given args.
84188	 * This method immediately returns as soon as a plugin explicitly returns false. The
84189	 * returned value can be used, for instance, to interrupt the current action.
84190	 * @param {Object} chart - The chart instance for which plugins should be called.
84191	 * @param {String} hook - The name of the plugin method to call (e.g. 'beforeUpdate').
84192	 * @param {Array} [args] - Extra arguments to apply to the hook call.
84193	 * @returns {Boolean} false if any of the plugins return false, else returns true.
84194	 */
84195	notify: function(chart, hook, args) {
84196		var descriptors = this.descriptors(chart);
84197		var ilen = descriptors.length;
84198		var i, descriptor, plugin, params, method;
84199
84200		for (i = 0; i < ilen; ++i) {
84201			descriptor = descriptors[i];
84202			plugin = descriptor.plugin;
84203			method = plugin[hook];
84204			if (typeof method === 'function') {
84205				params = [chart].concat(args || []);
84206				params.push(descriptor.options);
84207				if (method.apply(plugin, params) === false) {
84208					return false;
84209				}
84210			}
84211		}
84212
84213		return true;
84214	},
84215
84216	/**
84217	 * Returns descriptors of enabled plugins for the given chart.
84218	 * @returns {Array} [{ plugin, options }]
84219	 * @private
84220	 */
84221	descriptors: function(chart) {
84222		var cache = chart.$plugins || (chart.$plugins = {});
84223		if (cache.id === this._cacheId) {
84224			return cache.descriptors;
84225		}
84226
84227		var plugins = [];
84228		var descriptors = [];
84229		var config = (chart && chart.config) || {};
84230		var options = (config.options && config.options.plugins) || {};
84231
84232		this._plugins.concat(config.plugins || []).forEach(function(plugin) {
84233			var idx = plugins.indexOf(plugin);
84234			if (idx !== -1) {
84235				return;
84236			}
84237
84238			var id = plugin.id;
84239			var opts = options[id];
84240			if (opts === false) {
84241				return;
84242			}
84243
84244			if (opts === true) {
84245				opts = helpers.clone(defaults.global.plugins[id]);
84246			}
84247
84248			plugins.push(plugin);
84249			descriptors.push({
84250				plugin: plugin,
84251				options: opts || {}
84252			});
84253		});
84254
84255		cache.descriptors = descriptors;
84256		cache.id = this._cacheId;
84257		return descriptors;
84258	},
84259
84260	/**
84261	 * Invalidates cache for the given chart: descriptors hold a reference on plugin option,
84262	 * but in some cases, this reference can be changed by the user when updating options.
84263	 * https://github.com/chartjs/Chart.js/issues/5111#issuecomment-355934167
84264	 * @private
84265	 */
84266	_invalidate: function(chart) {
84267		delete chart.$plugins;
84268	}
84269};
84270
84271/**
84272 * Plugin extension hooks.
84273 * @interface IPlugin
84274 * @since 2.1.0
84275 */
84276/**
84277 * @method IPlugin#beforeInit
84278 * @desc Called before initializing `chart`.
84279 * @param {Chart.Controller} chart - The chart instance.
84280 * @param {Object} options - The plugin options.
84281 */
84282/**
84283 * @method IPlugin#afterInit
84284 * @desc Called after `chart` has been initialized and before the first update.
84285 * @param {Chart.Controller} chart - The chart instance.
84286 * @param {Object} options - The plugin options.
84287 */
84288/**
84289 * @method IPlugin#beforeUpdate
84290 * @desc Called before updating `chart`. If any plugin returns `false`, the update
84291 * is cancelled (and thus subsequent render(s)) until another `update` is triggered.
84292 * @param {Chart.Controller} chart - The chart instance.
84293 * @param {Object} options - The plugin options.
84294 * @returns {Boolean} `false` to cancel the chart update.
84295 */
84296/**
84297 * @method IPlugin#afterUpdate
84298 * @desc Called after `chart` has been updated and before rendering. Note that this
84299 * hook will not be called if the chart update has been previously cancelled.
84300 * @param {Chart.Controller} chart - The chart instance.
84301 * @param {Object} options - The plugin options.
84302 */
84303/**
84304 * @method IPlugin#beforeDatasetsUpdate
84305 * @desc Called before updating the `chart` datasets. If any plugin returns `false`,
84306 * the datasets update is cancelled until another `update` is triggered.
84307 * @param {Chart.Controller} chart - The chart instance.
84308 * @param {Object} options - The plugin options.
84309 * @returns {Boolean} false to cancel the datasets update.
84310 * @since version 2.1.5
84311*/
84312/**
84313 * @method IPlugin#afterDatasetsUpdate
84314 * @desc Called after the `chart` datasets have been updated. Note that this hook
84315 * will not be called if the datasets update has been previously cancelled.
84316 * @param {Chart.Controller} chart - The chart instance.
84317 * @param {Object} options - The plugin options.
84318 * @since version 2.1.5
84319 */
84320/**
84321 * @method IPlugin#beforeDatasetUpdate
84322 * @desc Called before updating the `chart` dataset at the given `args.index`. If any plugin
84323 * returns `false`, the datasets update is cancelled until another `update` is triggered.
84324 * @param {Chart} chart - The chart instance.
84325 * @param {Object} args - The call arguments.
84326 * @param {Number} args.index - The dataset index.
84327 * @param {Object} args.meta - The dataset metadata.
84328 * @param {Object} options - The plugin options.
84329 * @returns {Boolean} `false` to cancel the chart datasets drawing.
84330 */
84331/**
84332 * @method IPlugin#afterDatasetUpdate
84333 * @desc Called after the `chart` datasets at the given `args.index` has been updated. Note
84334 * that this hook will not be called if the datasets update has been previously cancelled.
84335 * @param {Chart} chart - The chart instance.
84336 * @param {Object} args - The call arguments.
84337 * @param {Number} args.index - The dataset index.
84338 * @param {Object} args.meta - The dataset metadata.
84339 * @param {Object} options - The plugin options.
84340 */
84341/**
84342 * @method IPlugin#beforeLayout
84343 * @desc Called before laying out `chart`. If any plugin returns `false`,
84344 * the layout update is cancelled until another `update` is triggered.
84345 * @param {Chart.Controller} chart - The chart instance.
84346 * @param {Object} options - The plugin options.
84347 * @returns {Boolean} `false` to cancel the chart layout.
84348 */
84349/**
84350 * @method IPlugin#afterLayout
84351 * @desc Called after the `chart` has been layed out. Note that this hook will not
84352 * be called if the layout update has been previously cancelled.
84353 * @param {Chart.Controller} chart - The chart instance.
84354 * @param {Object} options - The plugin options.
84355 */
84356/**
84357 * @method IPlugin#beforeRender
84358 * @desc Called before rendering `chart`. If any plugin returns `false`,
84359 * the rendering is cancelled until another `render` is triggered.
84360 * @param {Chart.Controller} chart - The chart instance.
84361 * @param {Object} options - The plugin options.
84362 * @returns {Boolean} `false` to cancel the chart rendering.
84363 */
84364/**
84365 * @method IPlugin#afterRender
84366 * @desc Called after the `chart` has been fully rendered (and animation completed). Note
84367 * that this hook will not be called if the rendering has been previously cancelled.
84368 * @param {Chart.Controller} chart - The chart instance.
84369 * @param {Object} options - The plugin options.
84370 */
84371/**
84372 * @method IPlugin#beforeDraw
84373 * @desc Called before drawing `chart` at every animation frame specified by the given
84374 * easing value. If any plugin returns `false`, the frame drawing is cancelled until
84375 * another `render` is triggered.
84376 * @param {Chart.Controller} chart - The chart instance.
84377 * @param {Number} easingValue - The current animation value, between 0.0 and 1.0.
84378 * @param {Object} options - The plugin options.
84379 * @returns {Boolean} `false` to cancel the chart drawing.
84380 */
84381/**
84382 * @method IPlugin#afterDraw
84383 * @desc Called after the `chart` has been drawn for the specific easing value. Note
84384 * that this hook will not be called if the drawing has been previously cancelled.
84385 * @param {Chart.Controller} chart - The chart instance.
84386 * @param {Number} easingValue - The current animation value, between 0.0 and 1.0.
84387 * @param {Object} options - The plugin options.
84388 */
84389/**
84390 * @method IPlugin#beforeDatasetsDraw
84391 * @desc Called before drawing the `chart` datasets. If any plugin returns `false`,
84392 * the datasets drawing is cancelled until another `render` is triggered.
84393 * @param {Chart.Controller} chart - The chart instance.
84394 * @param {Number} easingValue - The current animation value, between 0.0 and 1.0.
84395 * @param {Object} options - The plugin options.
84396 * @returns {Boolean} `false` to cancel the chart datasets drawing.
84397 */
84398/**
84399 * @method IPlugin#afterDatasetsDraw
84400 * @desc Called after the `chart` datasets have been drawn. Note that this hook
84401 * will not be called if the datasets drawing has been previously cancelled.
84402 * @param {Chart.Controller} chart - The chart instance.
84403 * @param {Number} easingValue - The current animation value, between 0.0 and 1.0.
84404 * @param {Object} options - The plugin options.
84405 */
84406/**
84407 * @method IPlugin#beforeDatasetDraw
84408 * @desc Called before drawing the `chart` dataset at the given `args.index` (datasets
84409 * are drawn in the reverse order). If any plugin returns `false`, the datasets drawing
84410 * is cancelled until another `render` is triggered.
84411 * @param {Chart} chart - The chart instance.
84412 * @param {Object} args - The call arguments.
84413 * @param {Number} args.index - The dataset index.
84414 * @param {Object} args.meta - The dataset metadata.
84415 * @param {Number} args.easingValue - The current animation value, between 0.0 and 1.0.
84416 * @param {Object} options - The plugin options.
84417 * @returns {Boolean} `false` to cancel the chart datasets drawing.
84418 */
84419/**
84420 * @method IPlugin#afterDatasetDraw
84421 * @desc Called after the `chart` datasets at the given `args.index` have been drawn
84422 * (datasets are drawn in the reverse order). Note that this hook will not be called
84423 * if the datasets drawing has been previously cancelled.
84424 * @param {Chart} chart - The chart instance.
84425 * @param {Object} args - The call arguments.
84426 * @param {Number} args.index - The dataset index.
84427 * @param {Object} args.meta - The dataset metadata.
84428 * @param {Number} args.easingValue - The current animation value, between 0.0 and 1.0.
84429 * @param {Object} options - The plugin options.
84430 */
84431/**
84432 * @method IPlugin#beforeTooltipDraw
84433 * @desc Called before drawing the `tooltip`. If any plugin returns `false`,
84434 * the tooltip drawing is cancelled until another `render` is triggered.
84435 * @param {Chart} chart - The chart instance.
84436 * @param {Object} args - The call arguments.
84437 * @param {Object} args.tooltip - The tooltip.
84438 * @param {Number} args.easingValue - The current animation value, between 0.0 and 1.0.
84439 * @param {Object} options - The plugin options.
84440 * @returns {Boolean} `false` to cancel the chart tooltip drawing.
84441 */
84442/**
84443 * @method IPlugin#afterTooltipDraw
84444 * @desc Called after drawing the `tooltip`. Note that this hook will not
84445 * be called if the tooltip drawing has been previously cancelled.
84446 * @param {Chart} chart - The chart instance.
84447 * @param {Object} args - The call arguments.
84448 * @param {Object} args.tooltip - The tooltip.
84449 * @param {Number} args.easingValue - The current animation value, between 0.0 and 1.0.
84450 * @param {Object} options - The plugin options.
84451 */
84452/**
84453 * @method IPlugin#beforeEvent
84454 * @desc Called before processing the specified `event`. If any plugin returns `false`,
84455 * the event will be discarded.
84456 * @param {Chart.Controller} chart - The chart instance.
84457 * @param {IEvent} event - The event object.
84458 * @param {Object} options - The plugin options.
84459 */
84460/**
84461 * @method IPlugin#afterEvent
84462 * @desc Called after the `event` has been consumed. Note that this hook
84463 * will not be called if the `event` has been previously discarded.
84464 * @param {Chart.Controller} chart - The chart instance.
84465 * @param {IEvent} event - The event object.
84466 * @param {Object} options - The plugin options.
84467 */
84468/**
84469 * @method IPlugin#resize
84470 * @desc Called after the chart as been resized.
84471 * @param {Chart.Controller} chart - The chart instance.
84472 * @param {Number} size - The new canvas display size (eq. canvas.style width & height).
84473 * @param {Object} options - The plugin options.
84474 */
84475/**
84476 * @method IPlugin#destroy
84477 * @desc Called after the chart as been destroyed.
84478 * @param {Chart.Controller} chart - The chart instance.
84479 * @param {Object} options - The plugin options.
84480 */
84481
84482},{"26":26,"46":46}],33:[function(require,module,exports){
84483'use strict';
84484
84485var defaults = require(26);
84486var Element = require(27);
84487var helpers = require(46);
84488var Ticks = require(35);
84489
84490defaults._set('scale', {
84491	display: true,
84492	position: 'left',
84493	offset: false,
84494
84495	// grid line settings
84496	gridLines: {
84497		display: true,
84498		color: 'rgba(0, 0, 0, 0.1)',
84499		lineWidth: 1,
84500		drawBorder: true,
84501		drawOnChartArea: true,
84502		drawTicks: true,
84503		tickMarkLength: 10,
84504		zeroLineWidth: 1,
84505		zeroLineColor: 'rgba(0,0,0,0.25)',
84506		zeroLineBorderDash: [],
84507		zeroLineBorderDashOffset: 0.0,
84508		offsetGridLines: false,
84509		borderDash: [],
84510		borderDashOffset: 0.0
84511	},
84512
84513	// scale label
84514	scaleLabel: {
84515		// display property
84516		display: false,
84517
84518		// actual label
84519		labelString: '',
84520
84521		// line height
84522		lineHeight: 1.2,
84523
84524		// top/bottom padding
84525		padding: {
84526			top: 4,
84527			bottom: 4
84528		}
84529	},
84530
84531	// label settings
84532	ticks: {
84533		beginAtZero: false,
84534		minRotation: 0,
84535		maxRotation: 50,
84536		mirror: false,
84537		padding: 0,
84538		reverse: false,
84539		display: true,
84540		autoSkip: true,
84541		autoSkipPadding: 0,
84542		labelOffset: 0,
84543		// We pass through arrays to be rendered as multiline labels, we convert Others to strings here.
84544		callback: Ticks.formatters.values,
84545		minor: {},
84546		major: {}
84547	}
84548});
84549
84550function labelsFromTicks(ticks) {
84551	var labels = [];
84552	var i, ilen;
84553
84554	for (i = 0, ilen = ticks.length; i < ilen; ++i) {
84555		labels.push(ticks[i].label);
84556	}
84557
84558	return labels;
84559}
84560
84561function getLineValue(scale, index, offsetGridLines) {
84562	var lineValue = scale.getPixelForTick(index);
84563
84564	if (offsetGridLines) {
84565		if (index === 0) {
84566			lineValue -= (scale.getPixelForTick(1) - lineValue) / 2;
84567		} else {
84568			lineValue -= (lineValue - scale.getPixelForTick(index - 1)) / 2;
84569		}
84570	}
84571	return lineValue;
84572}
84573
84574function computeTextSize(context, tick, font) {
84575	return helpers.isArray(tick) ?
84576		helpers.longestText(context, font, tick) :
84577		context.measureText(tick).width;
84578}
84579
84580function parseFontOptions(options) {
84581	var valueOrDefault = helpers.valueOrDefault;
84582	var globalDefaults = defaults.global;
84583	var size = valueOrDefault(options.fontSize, globalDefaults.defaultFontSize);
84584	var style = valueOrDefault(options.fontStyle, globalDefaults.defaultFontStyle);
84585	var family = valueOrDefault(options.fontFamily, globalDefaults.defaultFontFamily);
84586
84587	return {
84588		size: size,
84589		style: style,
84590		family: family,
84591		font: helpers.fontString(size, style, family)
84592	};
84593}
84594
84595function parseLineHeight(options) {
84596	return helpers.options.toLineHeight(
84597		helpers.valueOrDefault(options.lineHeight, 1.2),
84598		helpers.valueOrDefault(options.fontSize, defaults.global.defaultFontSize));
84599}
84600
84601module.exports = Element.extend({
84602	/**
84603	 * Get the padding needed for the scale
84604	 * @method getPadding
84605	 * @private
84606	 * @returns {Padding} the necessary padding
84607	 */
84608	getPadding: function() {
84609		var me = this;
84610		return {
84611			left: me.paddingLeft || 0,
84612			top: me.paddingTop || 0,
84613			right: me.paddingRight || 0,
84614			bottom: me.paddingBottom || 0
84615		};
84616	},
84617
84618	/**
84619	 * Returns the scale tick objects ({label, major})
84620	 * @since 2.7
84621	 */
84622	getTicks: function() {
84623		return this._ticks;
84624	},
84625
84626	// These methods are ordered by lifecyle. Utilities then follow.
84627	// Any function defined here is inherited by all scale types.
84628	// Any function can be extended by the scale type
84629
84630	mergeTicksOptions: function() {
84631		var ticks = this.options.ticks;
84632		if (ticks.minor === false) {
84633			ticks.minor = {
84634				display: false
84635			};
84636		}
84637		if (ticks.major === false) {
84638			ticks.major = {
84639				display: false
84640			};
84641		}
84642		for (var key in ticks) {
84643			if (key !== 'major' && key !== 'minor') {
84644				if (typeof ticks.minor[key] === 'undefined') {
84645					ticks.minor[key] = ticks[key];
84646				}
84647				if (typeof ticks.major[key] === 'undefined') {
84648					ticks.major[key] = ticks[key];
84649				}
84650			}
84651		}
84652	},
84653	beforeUpdate: function() {
84654		helpers.callback(this.options.beforeUpdate, [this]);
84655	},
84656
84657	update: function(maxWidth, maxHeight, margins) {
84658		var me = this;
84659		var i, ilen, labels, label, ticks, tick;
84660
84661		// Update Lifecycle - Probably don't want to ever extend or over
vendor: 4,252 bytes, lines 84661-84821
84661write this function ;)
84662		me.beforeUpdate();
84663
84664		// Absorb the master measurements
84665		me.maxWidth = maxWidth;
84666		me.maxHeight = maxHeight;
84667		me.margins = helpers.extend({
84668			left: 0,
84669			right: 0,
84670			top: 0,
84671			bottom: 0
84672		}, margins);
84673		me.longestTextCache = me.longestTextCache || {};
84674
84675		// Dimensions
84676		me.beforeSetDimensions();
84677		me.setDimensions();
84678		me.afterSetDimensions();
84679
84680		// Data min/max
84681		me.beforeDataLimits();
84682		me.determineDataLimits();
84683		me.afterDataLimits();
84684
84685		// Ticks - `this.ticks` is now DEPRECATED!
84686		// Internal ticks are now stored as objects in the PRIVATE `this._ticks` member
84687		// and must not be accessed directly from outside this class. `this.ticks` being
84688		// around for long time and not marked as private, we can't change its structure
84689		// without unexpected breaking changes. If you need to access the scale ticks,
84690		// use scale.getTicks() instead.
84691
84692		me.beforeBuildTicks();
84693
84694		// New implementations should return an array of objects but for BACKWARD COMPAT,
84695		// we still support no return (`this.ticks` internally set by calling this method).
84696		ticks = me.buildTicks() || [];
84697
84698		me.afterBuildTicks();
84699
84700		me.beforeTickToLabelConversion();
84701
84702		// New implementations should return the formatted tick labels but for BACKWARD
84703		// COMPAT, we still support no return (`this.ticks` internally changed by calling
84704		// this method and supposed to contain only string values).
84705		labels = me.convertTicksToLabels(ticks) || me.ticks;
84706
84707		me.afterTickToLabelConversion();
84708
84709		me.ticks = labels;   // BACKWARD COMPATIBILITY
84710
84711		// IMPORTANT: from this point, we consider that `this.ticks` will NEVER change!
84712
84713		// BACKWARD COMPAT: synchronize `_ticks` with labels (so potentially `this.ticks`)
84714		for (i = 0, ilen = labels.length; i < ilen; ++i) {
84715			label = labels[i];
84716			tick = ticks[i];
84717			if (!tick) {
84718				ticks.push(tick = {
84719					label: label,
84720					major: false
84721				});
84722			} else {
84723				tick.label = label;
84724			}
84725		}
84726
84727		me._ticks = ticks;
84728
84729		// Tick Rotation
84730		me.beforeCalculateTickRotation();
84731		me.calculateTickRotation();
84732		me.afterCalculateTickRotation();
84733		// Fit
84734		me.beforeFit();
84735		me.fit();
84736		me.afterFit();
84737		//
84738		me.afterUpdate();
84739
84740		return me.minSize;
84741
84742	},
84743	afterUpdate: function() {
84744		helpers.callback(this.options.afterUpdate, [this]);
84745	},
84746
84747	//
84748
84749	beforeSetDimensions: function() {
84750		helpers.callback(this.options.beforeSetDimensions, [this]);
84751	},
84752	setDimensions: function() {
84753		var me = this;
84754		// Set the unconstrained dimension before label rotation
84755		if (me.isHorizontal()) {
84756			// Reset position before calculating rotation
84757			me.width = me.maxWidth;
84758			me.left = 0;
84759			me.right = me.width;
84760		} else {
84761			me.height = me.maxHeight;
84762
84763			// Reset position before calculating rotation
84764			me.top = 0;
84765			me.bottom = me.height;
84766		}
84767
84768		// Reset padding
84769		me.paddingLeft = 0;
84770		me.paddingTop = 0;
84771		me.paddingRight = 0;
84772		me.paddingBottom = 0;
84773	},
84774	afterSetDimensions: function() {
84775		helpers.callback(this.options.afterSetDimensions, [this]);
84776	},
84777
84778	// Data limits
84779	beforeDataLimits: function() {
84780		helpers.callback(this.options.beforeDataLimits, [this]);
84781	},
84782	determineDataLimits: helpers.noop,
84783	afterDataLimits: function() {
84784		helpers.callback(this.options.afterDataLimits, [this]);
84785	},
84786
84787	//
84788	beforeBuildTicks: function() {
84789		helpers.callback(this.options.beforeBuildTicks, [this]);
84790	},
84791	buildTicks: helpers.noop,
84792	afterBuildTicks: function() {
84793		helpers.callback(this.options.afterBuildTicks, [this]);
84794	},
84795
84796	beforeTickToLabelConversion: function() {
84797		helpers.callback(this.options.beforeTickToLabelConversion, [this]);
84798	},
84799	convertTicksToLabels: function() {
84800		var me = this;
84801		// Convert ticks to strings
84802		var tickOpts = me.options.ticks;
84803		me.ticks = me.ticks.map(tickOpts.userCallback || tickOpts.callback, this);
84804	},
84805	afterTickToLabelConversion: function() {
84806		helpers.callback(this.options.afterTickToLabelConversion, [this]);
84807	},
84808
84809	//
84810
84811	beforeCalculateTickRotation: function() {
84812		helpers.callback(this.options.beforeCalculateTickRotation, [this]);
84813	},
84814	calculateTickRotation: function() {
84815		var me = this;
84816		var context = me.ctx;
84817		var tickOpts = me.options.ticks;
84818		var labels = labelsFromTicks(me._ticks);
84819
84820		// Get the width of each grid by calculating the difference
84821		// between x offsets between 0 and 1.
84822		var tickFont = parseFontOptions(tickOpts);
84823		context.font = tickFont.font;
84824
84825		var labelRotation = tickOpts.minRotation || 0;
84826
84827		if (labels.length && me.options.display && me.isHorizontal()) {
84828			var originalLabelWidth = helpers.longestText(context, tickFont.font, labels, me.longestTextCache);
84829			var labelWidth = originalLabelWidth;
84830			var cosRotation, sinRotation;
84831
84832			// Allow 3 pixels x2 padding either side for label readability
84833			var tickWidth = me.getPixelForTick(1) - me.getPixelForTick(0) - 6;
84834
84835			// Max label rotation can be set or default to 90 - also act as a loop counter
84836			while (labelWidth > tickWidth && labelRotation < tickOpts.maxRotation) {
84837				var angleRadians = helpers.toRadians(labelRotation);
84838				cosRotation = Math.cos(angleRadians);
84839				sinRotation = Math.sin(angleRadians);
84840
84841				if (sinRotation * originalLabelWidth > me.maxHeight) {
84842					// go back one step
84843					labelRotation--;
84844					break;
84845				}
84846
84847				labelRotation++;
84848				labelWidth = cosRotation * originalLabelWidth;
84849			}
84850		}
84851
84852		me.labelRotation = labelRotation;
84853	},
84854	afterCalculateTickRotation: function() {
84855		helpers.callback(this.options.afterCalculateTickRotation, [this]);
84856	},
84857
84858	//
84859
84860	beforeFit: function() {
84861		helpers.callback(this.options.beforeFit, [this]);
84862	},
84863	fit: function() {
84864		var me = this;
84865		// Reset
84866		var minSize = me.minSize = {
84867			width: 0,
84868			height: 0
84869		};
84870
84871		var labels = labelsFromTicks(me._ticks);
84872
84873		var opts = me.options;
84874		var tickOpts = opts.ticks;
84875		var scaleLabelOpts = opts.scaleLabel;
84876		var gridLineOpts = opts.gridLines;
84877		var display = opts.display;
84878		var isHorizontal = me.isHorizontal();
84879
84880		var tickFont = parseFontOptions(tickOpts);
84881		var tickMarkLength = opts.gridLines.tickMarkLength;
84882
84883		// Width
84884		if (isHorizontal) {
84885			// subtract the margins to line up with the chartArea if we are a full width scale
84886			minSize.width = me.isFullWidth() ? me.maxWidth - me.margins.left - me.margins.right : me.maxWidth;
84887		} else {
84888			minSize.width = display && gridLineOpts.drawTicks ? tickMarkLength : 0;
84889		}
84890
84891		// height
84892		if (isHorizontal) {
84893			minSize.height = display && gridLineOpts.drawTicks ? tickMarkLength : 0;
84894		} else {
84895			minSize.height = me.maxHeight; // fill all the height
84896		}
84897
84898		// Are we showing a title for the scale?
84899		if (scaleLabelOpts.display && display) {
84900			var scaleLabelLineHeight = parseLineHeight(scaleLabelOpts);
84901			var scaleLabelPadding = helpers.options.toPadding(scaleLabelOpts.padding);
84902			var deltaHeight = scaleLabelLineHeight + scaleLabelPadding.height;
84903
84904			if (isHorizontal) {
84905				minSize.height += deltaHeight;
84906			} else {
84907				minSize.width += deltaHeight;
84908			}
84909		}
84910
84911		// Don't bother fitting the ticks if we are not showing them
84912		if (tickOpts.display && display) {
84913			var largestTextWidth = helpers.longestText(me.ctx, tickFont.font, labels, me.longestTextCache);
84914			var tallestLabelHeightInLines = helpers.numberOfLabelLines(labels);
84915			var lineSpace = tickFont.size * 0.5;
84916			var tickPadding = me.options.ticks.padding;
84917
84918			if (isHorizontal) {
84919				// A horizontal axis is more constrained by the height.
84920				me.longestLabelWidth = largestTextWidth;
84921
84922				var angleRadians = helpers.toRadians(me.labelRotation);
84923				var cosRotation = Math.cos(angleRadians);
84924				var sinRotation = Math.sin(angleRadians);
84925
84926				// TODO - improve this calculation
84927				var labelHeight = (sinRotation * largestTextWidth)
84928					+ (tickFont.size * tallestLabelHeightInLines)
84929					+ (lineSpace * (tallestLabelHeightInLines - 1))
84930					+ lineSpace; // padding
84931
84932				minSize.height = Math.min(me.maxHeight, minSize.height + labelHeight + tickPadding);
84933
84934				me.ctx.font = tickFont.font;
84935				var firstLabelWidth = computeTextSize(me.ctx, labels[0], tickFont.font);
84936				var lastLabelWidth = computeTextSize(me.ctx, labels[labels.length - 1], tickFont.font);
84937
84938				// Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned
84939				// which means that the right padding is dominated by the font height
84940				if (me.labelRotation !== 0) {
84941					me.paddingLeft = opts.position === 'bottom' ? (cosRotation * firstLabelWidth) + 3 : (cosRotation * lineSpace) + 3; // add 3 px to move away from canvas edges
84942					me.paddingRight = opts.position === 'bottom' ? (cosRotation * lineSpace) + 3 : (cosRotation * lastLabelWidth) + 3;
84943				} else {
84944					me.paddingLeft = firstLabelWidth / 2 + 3; // add 3 px to move away from canvas edges
84945					me.paddingRight = lastLabelWidth / 2 + 3;
84946				}
84947			} else {
84948				// A vertical axis is more constrained by the width. Labels are the
84949				// dominant factor here, so get that length first and account for padding
84950				if (tickOpts.mirror) {
84951					largestTextWidth = 0;
84952				} else {
84953					// use lineSpace for consistency with horizontal axis
84954					// tickPadding is not implemented for horizontal
84955					largestTextWidth += tickPadding + lineSpace;
84956				}
84957
84958				minSize.width = Math.min(me.maxWidth, minSize.width + largestTextWidth);
84959
84960				me.paddingTop = tickFont.size / 2;
84961				me.paddingBottom = tickFont.size / 2;
84962			}
84963		}
84964
84965		me.handleMargins();
84966
84967		me.width = minSize.width;
84968		me.height = minSize.height;
84969	},
84970
84971	/**
84972	 * Handle margins and padding interactions
84973	 * @private
84974	 */
84975	handleMargins: function() {
84976		var me = this;
84977		if (me.margins) {
84978			me.paddingLeft = Math.max(me.paddingLeft - me.margins.left, 0);
84979			me.paddingTop = Math.max(me.paddingTop - me.margins.top, 0);
84980			me.paddingRight = Math.max(me.paddingRight - me.margins.right, 0);
84981			me.paddingBottom = Math.max(me.paddingBottom - me.margins.bottom, 0);
84982		}
84983	},
84984
84985	afterFit: function() {
84986		helpers.callback(this.options.afterFit, [this]);
84987	},
84988
84989	// Shared Methods
84990	isHorizontal: function() {
84991		return this.options.position === 'top' || this.options.position === 'bottom';
84992	},
84993	isFullWidth: function() {
84994		return (this.options.fullWidth);
84995	},
84996
84997	// Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not
84998	getRightValue: function(rawValue) {
84999		// Null and undefined values first
85000		if (helpers.isNullOrUndef(rawValue)) {
85001			return NaN;
85002		}
85003		// isNaN(object) returns true, so make sure NaN is checking for a number; Discard Infinite values
85004		if (typeof rawValue === 'number' && !isFinite(rawValue)) {
85005			return NaN;
85006		}
85007		// If it is in fact an object, dive in one more level
85008		if (rawValue) {
85009			if (this.isHorizontal()) {
85010				if (rawValue.x !== undefined) {
85011					return this.getRightValue(rawValue.x);
85012				}
85013			} else if (rawValue.y !== undefined) {
85014				return this.getRightValue(rawValue.y);
85015			}
85016		}
85017
85018		// Value is good, return it
85019		return rawValue;
85020	},
85021
85022	/**
85023	 * Used to get the value to display in the tooltip for the data at the given index
85024	 * @param index
85025	 * @param datasetIndex
85026	 */
85027	getLabelForIndex: helpers.noop,
85028
85029	/**
85030	 * Returns the location of the given data point. Value can either be an index or a numerical value
85031	 * The coordinate (0, 0) is at the upper-left corner of the canvas
85032	 * @param value
85033	 * @param index
85034	 * @param datasetIndex
85035	 */
85036	getPixelForValue: helpers.noop,
85037
85038	/**
85039	 * Used to get the data value from a given pixel. This is the inverse of getPixelForValue
85040	 * The coordinate (0, 0) is at the upper-left corner of the canvas
85041	 * @param pixel
85042	 */
85043	getValueForPixel: helpers.noop,
85044
85045	/**
85046	 * Returns the location of the tick at the given index
85047	 * The coordinate (0, 0) is at the upper-left corner of the canvas
85048	 */
85049	getPixelForTick: function(index) {
85050		var me = this;
85051		var offset = me.options.offset;
85052		if (me.isHorizontal()) {
85053			var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
85054			var tickWidth = innerWidth / Math.max((me._ticks.length - (offset ? 0 : 1)), 1);
85055			var pixel = (tickWidth * index) + me.paddingLeft;
85056
85057			if (offset) {
85058				pixel += tickWidth / 2;
85059			}
85060
85061			var finalVal = me.left + Math.round(pixel);
85062			finalVal += me.isFullWidth() ? me.margins.left : 0;
85063			return finalVal;
85064		}
85065		var innerHeight = me.height - (me.paddingTop + me.paddingBottom);
85066		return me.top + (index * (innerHeight / (me._ticks.length - 1)));
85067	},
85068
85069	/**
85070	 * Utility for getting the pixel location of a percentage of scale
85071	 * The coordinate (0, 0) is at the upper-left corner of the canvas
85072	 */
85073	getPixelForDecimal: function(decimal) {
85074		var me = this;
85075		if (me.isHorizontal()) {
85076			var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
85077			var valueOffset = (innerWidth * decimal) + me.paddingLeft;
85078
85079			var finalVal = me.left + Math.round(valueOffset);
85080			finalVal += me.isFullWidth() ? me.margins.left : 0;
85081			return finalVal;
85082		}
85083		return me.top + (decimal * me.height);
85084	},
85085
85086	/**
85087	 * Returns the pixel for the minimum chart value
85088	 * The coordinate (0, 0) is at the upper-left corner of the canvas
85089	 */
85090	getBasePixel: function() {
85091		return this.getPixelForValue(this.getBaseValue());
85092	},
85093
85094	getBaseValue: function() {
85095		var me = this;
85096		var min = me.min;
85097		var max = me.max;
85098
85099		return me.beginAtZero ? 0 :
85100			min < 0 && max < 0 ? max :
85101			min > 0 && max > 0 ? min :
85102			0;
85103	},
85104
85105	/**
85106	 * Returns a subset of ticks to be plotted to avoid overlapping labels.
85107	 * @private
85108	 */
85109	_autoSkip: function(ticks) {
85110		var skipRatio;
85111		var me = this;
85112		var isHorizontal = me.isHorizontal();
85113		var optionTicks = me.options.ticks.minor;
85114		var tickCount = ticks.length;
85115		var labelRotationRadians = helpers.toRadians(me.labelRotation);
85116		var cosRotation = Math.cos(labelRotationRadians);
85117		var longestRotatedLabel = me.longestLabelWidth * cosRotation;
85118		var result = [];
85119		var i, tick, shouldSkip;
85120
85121		// figure out the maximum number of gridlines to show
85122		var maxTicks;
85123		if (optionTicks.maxTicksLimit) {
85124			maxTicks = optionTicks.maxTicksLimit;
85125		}
85126
85127		if (isHorizontal) {
85128			skipRatio = false;
85129
85130			if ((longestRotatedLabel + optionTicks.autoSkipPadding) * tickCount > (me.width - (me.paddingLeft + me.paddingRight))) {
85131				skipRatio = 1 + Math.floor(((longestRotatedLabel + optionTicks.autoSkipPadding) * tickCount) / (me.width - (me.paddingLeft + me.paddingRight)));
85132			}
85133
85134			// if they defined a max number of optionTicks,
85135			// increase skipRatio until that number is met
85136			if (maxTicks && tickCount > maxTicks) {
85137				skipRatio = Math.max(skipRatio, Math.floor(tickCount / maxTicks));
85138			}
85139		}
85140
85141		for (i = 0; i < tickCount; i++) {
85142			tick = ticks[i];
85143
85144			// Since we always show the last tick,we need may need to hide the last shown one before
85145			shouldSkip = (skipRatio > 1 && i % skipRatio > 0) || (i % skipRatio === 0 && i + skipRatio >= tickCount);
85146			if (shouldSkip && i !== tickCount - 1) {
85147				// leave tick in place but make sure it's not displayed (#4635)
85148				delete tick.label;
85149			}
85150			result.push(tick);
85151		}
85152		return result;
85153	},
85154
85155	// Actually draw the scale on the canvas
85156	// @param {rectangle} chartArea : the area of the chart to draw full grid lines on
85157	draw: function(chartArea) {
85158		var me = this;
85159		var options = me.options;
85160		if (!options.display) {
85161			return;
85162		}
85163
85164		var context = me.ctx;
85165		var globalDefaults = defaults.global;
85166		var optionTicks = options.ticks.minor;
85167		var optionMajorTicks = options.ticks.major || optionTicks;
85168		var gridLines = options.gridLines;
85169		var scaleLabel = options.scaleLabel;
85170
85171		var isRotated = me.labelRotation !== 0;
85172		var isHorizontal = me.isHorizontal();
85173
85174		var ticks = optionTicks.autoSkip ? me._autoSkip(me.getTicks()) : me.getTicks();
85175		var tickFontColor = helpers.valueOrDefault(optionTicks.fontColor, globalDefaults.defaultFontColor);
85176		var tickFont = parseFontOptions(optionTicks);
85177		var majorTickFontColor = helpers.valueOrDefault(optionMajorTicks.fontColor, globalDefaults.defaultFontColor);
85178		var majorTickFont = parseFontOptions(optionMajorTicks);
85179
85180		var tl = gridLines.drawTicks ? gridLines.tickMarkLength : 0;
85181
85182		var scaleLabelFontColor = helpers.valueOrDefault(scaleLabel.fontColor, globalDefaults.defaultFontColor);
85183		var scaleLabelFont = parseFontOptions(scaleLabel);
85184		var scaleLabelPadding = helpers.options.toPadding(scaleLabel.padding);
85185		var labelRotationRadians = helpers.toRadians(me.labelRotation);
85186
85187		var itemsToDraw = [];
85188
85189		var axisWidth = me.options.gridLines.lineWidth;
85190		var xTickStart = options.position === 'right' ? me.left : me.right - axisWidth - tl;
85191		var xTickEnd = options.position === 'right' ? me.left + tl : me.right;
85192		var yTickStart = options.position === 'bottom' ? me.top + axisWidth : me.bottom - tl - axisWidth;
85193		var yTickEnd = options.position === 'bottom' ? me.top + axisWidth + tl : me.bottom + axisWidth;
85194
85195		helpers.each(ticks, function(tick, index) {
85196			// autoskipper skipped this tick (#4635)
85197			if (helpers.isNullOrUndef(tick.label)) {
85198				return;
85199			}
85200
85201			var label = tick.label;
85202			var lineWidth, lineColor, borderDash, borderDashOffset;
85203			if (index === me.zeroLineIndex && options.offset === gridLines.offsetGridLines) {
85204				// Draw the first index specially
85205				lineWidth = gridLines.zeroLineWidth;
85206				lineColor = gridLines.zeroLineColor;
85207				borderDash = gridLines.zeroLineBorderDash;
85208				borderDashOffset = gridLines.zeroLineBorderDashOffset;
85209			} else {
85210				lineWidth = helpers.valueAtIndexOrDefault(gridLines.lineWidth, index);
85211				lineColor = helpers.valueAtIndexOrDefault(gridLines.color, index);
85212				borderDash = helpers.valueOrDefault(gridLines.borderDash, globalDefaults.borderDash);
85213				borderDashOffset = helpers.valueOrDefault(gridLines.borderDashOffset, globalDefaults.borderDashOffset);
85214			}
85215
85216			// Common properties
85217			var tx1, ty1, tx2, ty2, x1, y1, x2, y2, labelX, labelY;
85218			var textAlign = 'middle';
85219			var textBaseline = 'middle';
85220			var tickPadding = optionTicks.padding;
85221
85222			if (isHorizontal) {
85223				var labelYOffset = tl + tickPadding;
85224
85225				if (options.position === 'bottom') {
85226					// bottom
85227					textBaseline = !isRotated ? 'top' : 'middle';
85228					textAlign = !isRotated ? 'center' : 'right';
85229					labelY = me.top + labelYOffset;
85230				} else {
85231					// top
85232					textBaseline = !isRotated ? 'bottom' : 'middle';
85233					textAlign = !isRotated ? 'center' : 'left';
85234					labelY = me.bottom - labelYOffset;
85235				}
85236
85237				var xLineValue = getLineValue(me, index, gridLines.offsetGridLines && ticks.length > 1);
85238				if (xLineValue < me.left) {
85239					lineColor = 'rgba(0,0,0,0)';
85240				}
85241				xLineValue += helpers.aliasPixel(lineWidth);
85242
85243				labelX = me.getPixelForTick(index) + optionTicks.labelOffset; // x values for optionTicks (need to consider offsetLabel option)
85244
85245				tx1 = tx2 = x1 = x2 = xLineValue;
85246				ty1 = yTickStart;
85247				ty2 = yTickEnd;
85248				y1 = chartArea.top;
85249				y2 = chartArea.bottom + axisWidth;
85250			} else {
85251				var isLeft = options.position === 'left';
85252				var labelXOffset;
85253
85254				if (optionTicks.mirror) {
85255					textAlign = isLeft ? 'left' : 'right';
85256					labelXOffset = tickPadding;
85257				} else {
85258					textAlign = isLeft ? 'right' : 'left';
85259					labelXOffset = tl + tickPadding;
85260				}
85261
85262				labelX = isLeft ? me.right - labelXOffset : me.left + labelXOffset;
85263
85264				var yLineValue = getLineValue(me, index, gridLines.offsetGridLines && ticks.length > 1);
85265				if (yLineValue < me.top) {
85266					lineColor = 'rgba(0,0,0,0)';
85267				}
85268				yLineValue += helpers.aliasPixel(lineWidth);
85269
85270				labelY = me.getPixelForTick(index) + optionTicks.labelOffset;
85271
85272				tx1 = xTickStart;
85273				tx2 = xTickEnd;
85274				x1 = chartArea.left;
85275				x2 = chartArea.right + axisWidth;
85276				ty1 = ty2 = y1 = y2 = yLineValue;
85277			}
85278
85279			itemsToDraw.push({
85280				tx1: tx1,
85281				ty1: ty1,
85282				tx2: tx2,
85283				ty2: ty2,
85284				x1: x1,
85285				y1: y1,
85286				x2: x2,
85287				y2: y2,
85288				labelX: labelX,
85289				labelY: labelY,
85290				glWidth: lineWidth,
85291				glColor: lineColor,
85292				glBorderDash: borderDash,
85293				glBorderDashOffset: borderDashOffset,
85294				rotation: -1 * labelRotationRadians,
85295				label: label,
85296				major: tick.major,
85297				textBaseline: textBaseline,
85298				textAlign: textAlign
85299			});
85300		});
85301
85302		// Draw all of the tick labels, tick marks, and grid lines at the correct places
85303		helpers.each(itemsToDraw, function(itemToDraw) {
85304			if (gridLines.display) {
85305				context.save();
85306				context.lineWidth = itemToDraw.glWidth;
85307				context.strokeStyle = itemToDraw.glColor;
85308				if (context.setLineDash) {
85309					context.setLineDash(itemToDraw.glBorderDash);
85310					context.lineDashOffset = itemToDraw.glBorderDashOffset;
85311				}
85312
85313				context.beginPath();
85314
85315				if (gridLines.drawTicks) {
85316					context.moveTo(itemToDraw.tx1, itemToDraw.ty1);
85317					context.lineTo(itemToDraw.tx2, itemToDraw.ty2);
85318				}
85319
85320				if (gridLines.drawOnChartArea) {
85321					context.moveTo(itemToDraw.x1, itemToDraw.y1);
85322					context.lineTo(itemToDraw.x2, itemToDraw.y2);
85323				}
85324
85325				context.stroke();
85326				context.restore();
85327			}
85328
85329			if (optionTicks.display) {
85330				// Make sure we draw text in the correct color and font
85331				context.save();
85332				context.translate(itemToDraw.labelX, itemToDraw.labelY);
85333				context.rotate(itemToDraw.rotation);
85334				context.font = itemToDraw.major ? majorTickFont.font : tickFont.font;
85335				context.fillStyle = itemToDraw.major ? majorTickFontColor : tickFontColor;
85336				context.textBaseline = itemToDraw.textBaseline;
85337				context.textAlign = itemToDraw.textAlign;
85338
85339				var label = itemToDraw.label;
85340				if (helpers.isArray(label)) {
85341					var lineCount = label.length;
85342					var lineHeight = tickFont.size * 1.5;
85343					var y = me.isHorizontal() ? 0 : -lineHeight * (lineCount - 1) / 2;
85344
85345					for (var i = 0; i < lineCount; ++i) {
85346						// We just make sure the multiline element is a string here..
85347						context.fillText('' + label[i], 0, y);
85348						// apply same lineSpacing as calculated @ L#320
85349						y += lineHeight;
85350					}
85351				} else {
85352					context.fillText(label, 0, 0);
85353				}
85354				context.restore();
85355			}
85356		});
85357
85358		if (scaleLabel.display) {
85359			// Draw the scale label
85360			var scaleLabelX;
85361			var scaleLabelY;
85362			var rotation = 0;
85363			var halfLineHeight = parseLineHeight(scaleLabel) / 2;
85364
85365			if (isHorizontal) {
85366				scaleLabelX = me.left + ((me.right - me.left) / 2); // midpoint of the width
85367				scaleLabelY = options.position === 'bottom'
85368					? me.bottom - halfLineHeight - scaleLabelPadding.bottom
85369					: me.top + halfLineHeight + scaleLabelPadding.top;
85370			} else {
85371				var isLeft = options.position === 'left';
85372				scaleLabelX = isLeft
85373					? me.left + halfLineHeight + scaleLabelPadding.top
85374					: me.right - halfLineHeight - scaleLabelPadding.top;
85375				scaleLabelY = me.top + ((me.bottom - me.top) / 2);
85376				rotation = isLeft ? -0.5 * Math.PI : 0.5 * Math.PI;
85377			}
85378
85379			context.save();
85380			context.translate(scaleLabelX, scaleLabelY);
85381			context.rotate(rotation);
85382			context.textAlign = 'center';
85383			context.textBaseline = 'middle';
85384			context.fillStyle = scaleLabelFontColor; // render in correct colour
85385			context.font = scaleLabelFont.font;
85386			context.fillText(scaleLabel.labelString, 0, 0);
85387			context.restore();
85388		}
85389
85390		if (gridLines.drawBorder) {
85391			// Draw the line at the edge of the axis
85392			context.lineWidth = helpers.valueAtIndexOrDefault(gridLines.lineWidth, 0);
85393			context.strokeStyle = helpers.valueAtIndexOrDefault(gridLines.color, 0);
85394			var x1 = me.left;
85395			var x2 = me.right + axisWidth;
85396			var y1 = me.top;
85397			var y2 = me.bottom + axisWidth;
85398
85399			var aliasPixel = helpers.aliasPixel(context.lineWidth);
85400			if (isHorizontal) {
85401				y1 = y2 = options.position === 'top' ? me.bottom : me.top;
85402				y1 += aliasPixel;
85403				y2 += aliasPixel;
85404			} else {
85405				x1 = x2 = options.position === 'left' ? me.right : me.left;
85406				x1 += aliasPixel;
85407				x2 += aliasPixel;
85408			}
85409
85410			context.beginPath();
85411			context.moveTo(x1, y1);
85412			context.lineTo(x2, y2);
85413			context.stroke();
85414		}
85415	}
85416});
85417
85418},{"26":26,"27":27,"35":35,"46":46}],34:[function(require,module,exports){
85419'use strict';
85420
85421var defaults = require(26);
85422var helpers = require(46);
85423var layouts = require(31);
85424
85425module.exports = {
85426	// Scale registration object. Extensions can register new scale types (such as log or DB scales) and then
85427	// use the new chart options to grab the correct scale
85428	constructors: {},
85429	// Use a registration function so that we can move to an ES6 map when we no longer need to support
85430	// old browsers
85431
85432	// Scale config defaults
85433	defaults: {},
85434	registerScaleType: function(type, scaleConstructor, scaleDefaults) {
85435		this.constructors[type] = scaleConstructor;
85436		this.defaults[type] = helpers.clone(scaleDefaults);
85437	},
85438	getScaleConstructor: function(type) {
85439		return this.constructors.hasOwnProperty(type) ? this.constructors[type] : undefined;
85440	},
85441	getScaleDefaults: function(type) {
85442		// Return the scale defaults merged with the global settings so that we always use the latest ones
85443		return this.defaults.hasOwnProperty(type) ? helpers.merge({}, [defaults.scale, this.defaults[type]]) : {};
85444	},
85445	updateScaleDefaults: function(type, additions) {
85446		var me = this;
85447		if (me.defaults.hasOwnProperty(type)) {
85448			me.defaults[type] = helpers.extend(me.defaults[type], additions);
85449		}
85450	},
85451	addScalesToLayout: function(chart) {
85452		// Adds each scale to the chart.boxes array to be sized accordingly
85453		helpers.each(chart.scales, function(scale) {
85454			// Set ILayoutItem parameters for backwards compatibility
85455			scale.fullWidth = scale.options.fullWidth;
85456			scale.position = scale.options.position;
85457			scale.weight = scale.options.weight;
85458			layouts.addBox(chart, scale);
85459		});
85460	}
85461};
85462
85463},{"26":26,"31":31,"46":46}],35:[function(require,module,exports){
85464'use strict';
85465
85466var helpers = require(46);
85467
85468/**
85469 * Namespace to hold static tick generation functions
85470 * @namespace Chart.Ticks
85471 */
85472module.exports = {
85473	/**
85474	 * Namespace to hold formatters for different types of ticks
85475	 * @namespace Chart.Ticks.formatters
85476	 */
85477	formatters: {
85478		/**
85479		 * Formatter for value labels
85480		 * @method Chart.Ticks.formatters.values
85481		 * @param value the value to display
85482		 * @return {String|Array} the label to display
85483		 */
85484		values: function(value) {
85485			return helpers.isArray(value) ? value : '' + value;
85486		},
85487
85488		/**
85489		 * Formatter for linear numeric ticks
85490		 * @method Chart.Ticks.formatters.linear
85491		 * @param tickValue {Number} the value to be formatted
85492		 * @param index {Number} the position of the tickValue parameter in the ticks array
85493		 * @param ticks {Array<Number>} the list of ticks being converted
85494		 * @return {String} string representation of the tickValue parameter
85495		 */
85496		linear: function(tickValue, index, ticks) {
85497			// If we have lots of ticks, don't use the ones
85498			var delta = ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0];
85499
85500			// If we have a number like 2.5 as the delta, figure out how many decimal places we need
85501			if (Math.abs(delta) > 1) {
85502				if (tickValue !== Math.floor(tickValue)) {
85503					// not an integer
85504					delta = tickValue - Math.floor(tickValue);
85505				}
85506			}
85507
85508			var logDelta = helpers.log10(Math.abs(delta));
85509			var tickString = '';
85510
85511			if (tickValue !== 0) {
85512				var maxTick = Math.max(Math.abs(ticks[0]), Math.abs(ticks[ticks.length - 1]));
85513				if (maxTick < 1e-4) { // all ticks are small numbers; use scientific notation
85514					var logTick = helpers.log10(Math.abs(tickValue));
85515					tickString = tickValue.toExponential(Math.floor(logTick) - Math.floor(logDelta));
85516				} else {
85517					var numDecimal = -1 * Math.floor(logDelta);
85518					numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places
85519					tickString = tickValue.toFixed(numDecimal);
85520				}
85521			} else {
85522				tickString = '0'; // never show decimal places for 0
85523			}
85524
85525			return tickString;
85526		},
85527
85528		logarithmic: function(tickValue, index, ticks) {
85529			var remain = tickValue / (Math.pow(10, Math.floor(helpers.log10(tickValue))));
85530
85531			if (tickValue === 0) {
85532				return '0';
85533			} else if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === ticks.length - 1) {
85534				return tickValue.toExponential();
85535			}
85536			return '';
85537		}
85538	}
85539};
85540
85541},{"46":46}],36:[function(require,module,exports){
85542'use strict';
85543
85544var defaults = require(26);
85545var Element = require(27);
85546var helpers = require(46);
85547
85548defaults._set('global', {
85549	tooltips: {
85550		enabled: true,
85551		custom: null,
85552		mode: 'nearest',
85553		position: 'average',
85554		intersect: true,
85555		backgroundColor: 'rgba(0,0,0,0.8)',
85556		titleFontStyle: 'bold',
85557		titleSpacing: 2,
85558		titleMarginBottom: 6,
85559		titleFontColor: '#fff',
85560		titleAlign: 'left',
85561		bodySpacing: 2,
85562		bodyFontColor: '#fff',
85563		bodyAlign: 'left',
85564		footerFontStyle: 'bold',
85565		footerSpacing: 2,
85566		footerMarginTop: 6,
85567		footerFontColor: '#fff',
85568		footerAlign: 'left',
85569		yPadding: 6,
85570		xPadding: 6,
85571		caretPadding: 2,
85572		caretSize: 5,
85573		cornerRadius: 6,
vendor: 17,376 bytes, lines 85574-86183
85574		multiKeyBackground: '#fff',
85575		displayColors: true,
85576		borderColor: 'rgba(0,0,0,0)',
85577		borderWidth: 0,
85578		callbacks: {
85579			// Args are: (tooltipItems, data)
85580			beforeTitle: helpers.noop,
85581			title: function(tooltipItems, data) {
85582				// Pick first xLabel for now
85583				var title = '';
85584				var labels = data.labels;
85585				var labelCount = labels ? labels.length : 0;
85586
85587				if (tooltipItems.length > 0) {
85588					var item = tooltipItems[0];
85589
85590					if (item.xLabel) {
85591						title = item.xLabel;
85592					} else if (labelCount > 0 && item.index < labelCount) {
85593						title = labels[item.index];
85594					}
85595				}
85596
85597				return title;
85598			},
85599			afterTitle: helpers.noop,
85600
85601			// Args are: (tooltipItems, data)
85602			beforeBody: helpers.noop,
85603
85604			// Args are: (tooltipItem, data)
85605			beforeLabel: helpers.noop,
85606			label: function(tooltipItem, data) {
85607				var label = data.datasets[tooltipItem.datasetIndex].label || '';
85608
85609				if (label) {
85610					label += ': ';
85611				}
85612				label += tooltipItem.yLabel;
85613				return label;
85614			},
85615			labelColor: function(tooltipItem, chart) {
85616				var meta = chart.getDatasetMeta(tooltipItem.datasetIndex);
85617				var activeElement = meta.data[tooltipItem.index];
85618				var view = activeElement._view;
85619				return {
85620					borderColor: view.borderColor,
85621					backgroundColor: view.backgroundColor
85622				};
85623			},
85624			labelTextColor: function() {
85625				return this._options.bodyFontColor;
85626			},
85627			afterLabel: helpers.noop,
85628
85629			// Args are: (tooltipItems, data)
85630			afterBody: helpers.noop,
85631
85632			// Args are: (tooltipItems, data)
85633			beforeFooter: helpers.noop,
85634			footer: helpers.noop,
85635			afterFooter: helpers.noop
85636		}
85637	}
85638});
85639
85640var positioners = {
85641	/**
85642	 * Average mode places the tooltip at the average position of the elements shown
85643	 * @function Chart.Tooltip.positioners.average
85644	 * @param elements {ChartElement[]} the elements being displayed in the tooltip
85645	 * @returns {Point} tooltip position
85646	 */
85647	average: function(elements) {
85648		if (!elements.length) {
85649			return false;
85650		}
85651
85652		var i, len;
85653		var x = 0;
85654		var y = 0;
85655		var count = 0;
85656
85657		for (i = 0, len = elements.length; i < len; ++i) {
85658			var el = elements[i];
85659			if (el && el.hasValue()) {
85660				var pos = el.tooltipPosition();
85661				x += pos.x;
85662				y += pos.y;
85663				++count;
85664			}
85665		}
85666
85667		return {
85668			x: Math.round(x / count),
85669			y: Math.round(y / count)
85670		};
85671	},
85672
85673	/**
85674	 * Gets the tooltip position nearest of the item nearest to the event position
85675	 * @function Chart.Tooltip.positioners.nearest
85676	 * @param elements {Chart.Element[]} the tooltip elements
85677	 * @param eventPosition {Point} the position of the event in canvas coordinates
85678	 * @returns {Point} the tooltip position
85679	 */
85680	nearest: function(elements, eventPosition) {
85681		var x = eventPosition.x;
85682		var y = eventPosition.y;
85683		var minDistance = Number.POSITIVE_INFINITY;
85684		var i, len, nearestElement;
85685
85686		for (i = 0, len = elements.length; i < len; ++i) {
85687			var el = elements[i];
85688			if (el && el.hasValue()) {
85689				var center = el.getCenterPoint();
85690				var d = helpers.distanceBetweenPoints(eventPosition, center);
85691
85692				if (d < minDistance) {
85693					minDistance = d;
85694					nearestElement = el;
85695				}
85696			}
85697		}
85698
85699		if (nearestElement) {
85700			var tp = nearestElement.tooltipPosition();
85701			x = tp.x;
85702			y = tp.y;
85703		}
85704
85705		return {
85706			x: x,
85707			y: y
85708		};
85709	}
85710};
85711
85712/**
85713 * Helper method to merge the opacity into a color
85714 */
85715function mergeOpacity(colorString, opacity) {
85716	var color = helpers.color(colorString);
85717	return color.alpha(opacity * color.alpha()).rgbaString();
85718}
85719
85720// Helper to push or concat based on if the 2nd parameter is an array or not
85721function pushOrConcat(base, toPush) {
85722	if (toPush) {
85723		if (helpers.isArray(toPush)) {
85724			// base = base.concat(toPush);
85725			Array.prototype.push.apply(base, toPush);
85726		} else {
85727			base.push(toPush);
85728		}
85729	}
85730
85731	return base;
85732}
85733
85734/**
85735 * Returns array of strings split by newline
85736 * @param {String} value - The value to split by newline.
85737 * @returns {Array} value if newline present - Returned from String split() method
85738 * @function
85739 */
85740function splitNewlines(str) {
85741	if ((typeof str === 'string' || str instanceof String) && str.indexOf('\n') > -1) {
85742		return str.split('\n');
85743	}
85744	return str;
85745}
85746
85747
85748// Private helper to create a tooltip item model
85749// @param element : the chart element (point, arc, bar) to create the tooltip item for
85750// @return : new tooltip item
85751function createTooltipItem(element) {
85752	var xScale = element._xScale;
85753	var yScale = element._yScale || element._scale; // handle radar || polarArea charts
85754	var index = element._index;
85755	var datasetIndex = element._datasetIndex;
85756
85757	return {
85758		xLabel: xScale ? xScale.getLabelForIndex(index, datasetIndex) : '',
85759		yLabel: yScale ? yScale.getLabelForIndex(index, datasetIndex) : '',
85760		index: index,
85761		datasetIndex: datasetIndex,
85762		x: element._model.x,
85763		y: element._model.y
85764	};
85765}
85766
85767/**
85768 * Helper to get the reset model for the tooltip
85769 * @param tooltipOpts {Object} the tooltip options
85770 */
85771function getBaseModel(tooltipOpts) {
85772	var globalDefaults = defaults.global;
85773	var valueOrDefault = helpers.valueOrDefault;
85774
85775	return {
85776		// Positioning
85777		xPadding: tooltipOpts.xPadding,
85778		yPadding: tooltipOpts.yPadding,
85779		xAlign: tooltipOpts.xAlign,
85780		yAlign: tooltipOpts.yAlign,
85781
85782		// Body
85783		bodyFontColor: tooltipOpts.bodyFontColor,
85784		_bodyFontFamily: valueOrDefault(tooltipOpts.bodyFontFamily, globalDefaults.defaultFontFamily),
85785		_bodyFontStyle: valueOrDefault(tooltipOpts.bodyFontStyle, globalDefaults.defaultFontStyle),
85786		_bodyAlign: tooltipOpts.bodyAlign,
85787		bodyFontSize: valueOrDefault(tooltipOpts.bodyFontSize, globalDefaults.defaultFontSize),
85788		bodySpacing: tooltipOpts.bodySpacing,
85789
85790		// Title
85791		titleFontColor: tooltipOpts.titleFontColor,
85792		_titleFontFamily: valueOrDefault(tooltipOpts.titleFontFamily, globalDefaults.defaultFontFamily),
85793		_titleFontStyle: valueOrDefault(tooltipOpts.titleFontStyle, globalDefaults.defaultFontStyle),
85794		titleFontSize: valueOrDefault(tooltipOpts.titleFontSize, globalDefaults.defaultFontSize),
85795		_titleAlign: tooltipOpts.titleAlign,
85796		titleSpacing: tooltipOpts.titleSpacing,
85797		titleMarginBottom: tooltipOpts.titleMarginBottom,
85798
85799		// Footer
85800		footerFontColor: tooltipOpts.footerFontColor,
85801		_footerFontFamily: valueOrDefault(tooltipOpts.footerFontFamily, globalDefaults.defaultFontFamily),
85802		_footerFontStyle: valueOrDefault(tooltipOpts.footerFontStyle, globalDefaults.defaultFontStyle),
85803		footerFontSize: valueOrDefault(tooltipOpts.footerFontSize, globalDefaults.defaultFontSize),
85804		_footerAlign: tooltipOpts.footerAlign,
85805		footerSpacing: tooltipOpts.footerSpacing,
85806		footerMarginTop: tooltipOpts.footerMarginTop,
85807
85808		// Appearance
85809		caretSize: tooltipOpts.caretSize,
85810		cornerRadius: tooltipOpts.cornerRadius,
85811		backgroundColor: tooltipOpts.backgroundColor,
85812		opacity: 0,
85813		legendColorBackground: tooltipOpts.multiKeyBackground,
85814		displayColors: tooltipOpts.displayColors,
85815		borderColor: tooltipOpts.borderColor,
85816		borderWidth: tooltipOpts.borderWidth
85817	};
85818}
85819
85820/**
85821 * Get the size of the tooltip
85822 */
85823function getTooltipSize(tooltip, model) {
85824	var ctx = tooltip._chart.ctx;
85825
85826	var height = model.yPadding * 2; // Tooltip Padding
85827	var width = 0;
85828
85829	// Count of all lines in the body
85830	var body = model.body;
85831	var combinedBodyLength = body.reduce(function(count, bodyItem) {
85832		return count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length;
85833	}, 0);
85834	combinedBodyLength += model.beforeBody.length + model.afterBody.length;
85835
85836	var titleLineCount = model.title.length;
85837	var footerLineCount = model.footer.length;
85838	var titleFontSize = model.titleFontSize;
85839	var bodyFontSize = model.bodyFontSize;
85840	var footerFontSize = model.footerFontSize;
85841
85842	height += titleLineCount * titleFontSize; // Title Lines
85843	height += titleLineCount ? (titleLineCount - 1) * model.titleSpacing : 0; // Title Line Spacing
85844	height += titleLineCount ? model.titleMarginBottom : 0; // Title's bottom Margin
85845	height += combinedBodyLength * bodyFontSize; // Body Lines
85846	height += combinedBodyLength ? (combinedBodyLength - 1) * model.bodySpacing : 0; // Body Line Spacing
85847	height += footerLineCount ? model.footerMarginTop : 0; // Footer Margin
85848	height += footerLineCount * (footerFontSize); // Footer Lines
85849	height += footerLineCount ? (footerLineCount - 1) * model.footerSpacing : 0; // Footer Line Spacing
85850
85851	// Title width
85852	var widthPadding = 0;
85853	var maxLineWidth = function(line) {
85854		width = Math.max(width, ctx.measureText(line).width + widthPadding);
85855	};
85856
85857	ctx.font = helpers.fontString(titleFontSize, model._titleFontStyle, model._titleFontFamily);
85858	helpers.each(model.title, maxLineWidth);
85859
85860	// Body width
85861	ctx.font = helpers.fontString(bodyFontSize, model._bodyFontStyle, model._bodyFontFamily);
85862	helpers.each(model.beforeBody.concat(model.afterBody), maxLineWidth);
85863
85864	// Body lines may include some extra width due to the color box
85865	widthPadding = model.displayColors ? (bodyFontSize + 2) : 0;
85866	helpers.each(body, function(bodyItem) {
85867		helpers.each(bodyItem.before, maxLineWidth);
85868		helpers.each(bodyItem.lines, maxLineWidth);
85869		helpers.each(bodyItem.after, maxLineWidth);
85870	});
85871
85872	// Reset back to 0
85873	widthPadding = 0;
85874
85875	// Footer width
85876	ctx.font = helpers.fontString(footerFontSize, model._footerFontStyle, model._footerFontFamily);
85877	helpers.each(model.footer, maxLineWidth);
85878
85879	// Add padding
85880	width += 2 * model.xPadding;
85881
85882	return {
85883		width: width,
85884		height: height
85885	};
85886}
85887
85888/**
85889 * Helper to get the alignment of a tooltip given the size
85890 */
85891function determineAlignment(tooltip, size) {
85892	var model = tooltip._model;
85893	var chart = tooltip._chart;
85894	var chartArea = tooltip._chart.chartArea;
85895	var xAlign = 'center';
85896	var yAlign = 'center';
85897
85898	if (model.y < size.height) {
85899		yAlign = 'top';
85900	} else if (model.y > (chart.height - size.height)) {
85901		yAlign = 'bottom';
85902	}
85903
85904	var lf, rf; // functions to determine left, right alignment
85905	var olf, orf; // functions to determine if left/right alignment causes tooltip to go outside chart
85906	var yf; // function to get the y alignment if the tooltip goes outside of the left or right edges
85907	var midX = (chartArea.left + chartArea.right) / 2;
85908	var midY = (chartArea.top + chartArea.bottom) / 2;
85909
85910	if (yAlign === 'center') {
85911		lf = function(x) {
85912			return x <= midX;
85913		};
85914		rf = function(x) {
85915			return x > midX;
85916		};
85917	} else {
85918		lf = function(x) {
85919			return x <= (size.width / 2);
85920		};
85921		rf = function(x) {
85922			return x >= (chart.width - (size.width / 2));
85923		};
85924	}
85925
85926	olf = function(x) {
85927		return x + size.width + model.caretSize + model.caretPadding > chart.width;
85928	};
85929	orf = function(x) {
85930		return x - size.width - model.caretSize - model.caretPadding < 0;
85931	};
85932	yf = function(y) {
85933		return y <= midY ? 'top' : 'bottom';
85934	};
85935
85936	if (lf(model.x)) {
85937		xAlign = 'left';
85938
85939		// Is tooltip too wide and goes over the right side of the chart.?
85940		if (olf(model.x)) {
85941			xAlign = 'center';
85942			yAlign = yf(model.y);
85943		}
85944	} else if (rf(model.x)) {
85945		xAlign = 'right';
85946
85947		// Is tooltip too wide and goes outside left edge of canvas?
85948		if (orf(model.x)) {
85949			xAlign = 'center';
85950			yAlign = yf(model.y);
85951		}
85952	}
85953
85954	var opts = tooltip._options;
85955	return {
85956		xAlign: opts.xAlign ? opts.xAlign : xAlign,
85957		yAlign: opts.yAlign ? opts.yAlign : yAlign
85958	};
85959}
85960
85961/**
85962 * Helper to get the location a tooltip needs to be placed at given the initial position (via the vm) and the size and alignment
85963 */
85964function getBackgroundPoint(vm, size, alignment, chart) {
85965	// Background Position
85966	var x = vm.x;
85967	var y = vm.y;
85968
85969	var caretSize = vm.caretSize;
85970	var caretPadding = vm.caretPadding;
85971	var cornerRadius = vm.cornerRadius;
85972	var xAlign = alignment.xAlign;
85973	var yAlign = alignment.yAlign;
85974	var paddingAndSize = caretSize + caretPadding;
85975	var radiusAndPadding = cornerRadius + caretPadding;
85976
85977	if (xAlign === 'right') {
85978		x -= size.width;
85979	} else if (xAlign === 'center') {
85980		x -= (size.width / 2);
85981		if (x + size.width > chart.width) {
85982			x = chart.width - size.width;
85983		}
85984		if (x < 0) {
85985			x = 0;
85986		}
85987	}
85988
85989	if (yAlign === 'top') {
85990		y += paddingAndSize;
85991	} else if (yAlign === 'bottom') {
85992		y -= size.height + paddingAndSize;
85993	} else {
85994		y -= (size.height / 2);
85995	}
85996
85997	if (yAlign === 'center') {
85998		if (xAlign === 'left') {
85999			x += paddingAndSize;
86000		} else if (xAlign === 'right') {
86001			x -= paddingAndSize;
86002		}
86003	} else if (xAlign === 'left') {
86004		x -= radiusAndPadding;
86005	} else if (xAlign === 'right') {
86006		x += radiusAndPadding;
86007	}
86008
86009	return {
86010		x: x,
86011		y: y
86012	};
86013}
86014
86015/**
86016 * Helper to build before and after body lines
86017 */
86018function getBeforeAfterBodyLines(callback) {
86019	return pushOrConcat([], splitNewlines(callback));
86020}
86021
86022var exports = module.exports = Element.extend({
86023	initialize: function() {
86024		this._model = getBaseModel(this._options);
86025		this._lastActive = [];
86026	},
86027
86028	// Get the title
86029	// Args are: (tooltipItem, data)
86030	getTitle: function() {
86031		var me = this;
86032		var opts = me._options;
86033		var callbacks = opts.callbacks;
86034
86035		var beforeTitle = callbacks.beforeTitle.apply(me, arguments);
86036		var title = callbacks.title.apply(me, arguments);
86037		var afterTitle = callbacks.afterTitle.apply(me, arguments);
86038
86039		var lines = [];
86040		lines = pushOrConcat(lines, splitNewlines(beforeTitle));
86041		lines = pushOrConcat(lines, splitNewlines(title));
86042		lines = pushOrConcat(lines, splitNewlines(afterTitle));
86043
86044		return lines;
86045	},
86046
86047	// Args are: (tooltipItem, data)
86048	getBeforeBody: function() {
86049		return getBeforeAfterBodyLines(this._options.callbacks.beforeBody.apply(this, arguments));
86050	},
86051
86052	// Args are: (tooltipItem, data)
86053	getBody: function(tooltipItems, data) {
86054		var me = this;
86055		var callbacks = me._options.callbacks;
86056		var bodyItems = [];
86057
86058		helpers.each(tooltipItems, function(tooltipItem) {
86059			var bodyItem = {
86060				before: [],
86061				lines: [],
86062				after: []
86063			};
86064			pushOrConcat(bodyItem.before, splitNewlines(callbacks.beforeLabel.call(me, tooltipItem, data)));
86065			pushOrConcat(bodyItem.lines, callbacks.label.call(me, tooltipItem, data));
86066			pushOrConcat(bodyItem.after, splitNewlines(callbacks.afterLabel.call(me, tooltipItem, data)));
86067
86068			bodyItems.push(bodyItem);
86069		});
86070
86071		return bodyItems;
86072	},
86073
86074	// Args are: (tooltipItem, data)
86075	getAfterBody: function() {
86076		return getBeforeAfterBodyLines(this._options.callbacks.afterBody.apply(this, arguments));
86077	},
86078
86079	// Get the footer and beforeFooter and afterFooter lines
86080	// Args are: (tooltipItem, data)
86081	getFooter: function() {
86082		var me = this;
86083		var callbacks = me._options.callbacks;
86084
86085		var beforeFooter = callbacks.beforeFooter.apply(me, arguments);
86086		var footer = callbacks.footer.apply(me, arguments);
86087		var afterFooter = callbacks.afterFooter.apply(me, arguments);
86088
86089		var lines = [];
86090		lines = pushOrConcat(lines, splitNewlines(beforeFooter));
86091		lines = pushOrConcat(lines, splitNewlines(footer));
86092		lines = pushOrConcat(lines, splitNewlines(afterFooter));
86093
86094		return lines;
86095	},
86096
86097	update: function(changed) {
86098		var me = this;
86099		var opts = me._options;
86100
86101		// Need to regenerate the model because its faster than using extend and it is necessary due to the optimization in Chart.Element.transition
86102		// that does _view = _model if ease === 1. This causes the 2nd tooltip update to set properties in both the view and model at the same time
86103		// which breaks any animations.
86104		var existingModel = me._model;
86105		var model = me._model = getBaseModel(opts);
86106		var active = me._active;
86107
86108		var data = me._data;
86109
86110		// In the case where active.length === 0 we need to keep these at existing values for good animations
86111		var alignment = {
86112			xAlign: existingModel.xAlign,
86113			yAlign: existingModel.yAlign
86114		};
86115		var backgroundPoint = {
86116			x: existingModel.x,
86117			y: existingModel.y
86118		};
86119		var tooltipSize = {
86120			width: existingModel.width,
86121			height: existingModel.height
86122		};
86123		var tooltipPosition = {
86124			x: existingModel.caretX,
86125			y: existingModel.caretY
86126		};
86127
86128		var i, len;
86129
86130		if (active.length) {
86131			model.opacity = 1;
86132
86133			var labelColors = [];
86134			var labelTextColors = [];
86135			tooltipPosition = positioners[opts.position].call(me, active, me._eventPosition);
86136
86137			var tooltipItems = [];
86138			for (i = 0, len = active.length; i < len; ++i) {
86139				tooltipItems.push(createTooltipItem(active[i]));
86140			}
86141
86142			// If the user provided a filter function, use it to modify the tooltip items
86143			if (opts.filter) {
86144				tooltipItems = tooltipItems.filter(function(a) {
86145					return opts.filter(a, data);
86146				});
86147			}
86148
86149			// If the user provided a sorting function, use it to modify the tooltip items
86150			if (opts.itemSort) {
86151				tooltipItems = tooltipItems.sort(function(a, b) {
86152					return opts.itemSort(a, b, data);
86153				});
86154			}
86155
86156			// Determine colors for boxes
86157			helpers.each(tooltipItems, function(tooltipItem) {
86158				labelColors.push(opts.callbacks.labelColor.call(me, tooltipItem, me._chart));
86159				labelTextColors.push(opts.callbacks.labelTextColor.call(me, tooltipItem, me._chart));
86160			});
86161
86162
86163			// Build the Text Lines
86164			model.title = me.getTitle(tooltipItems, data);
86165			model.beforeBody = me.getBeforeBody(tooltipItems, data);
86166			model.body = me.getBody(tooltipItems, data);
86167			model.afterBody = me.getAfterBody(tooltipItems, data);
86168			model.footer = me.getFooter(tooltipItems, data);
86169
86170			// Initial positioning and colors
86171			model.x = Math.round(tooltipPosition.x);
86172			model.y = Math.round(tooltipPosition.y);
86173			model.caretPadding = opts.caretPadding;
86174			model.labelColors = labelColors;
86175			model.labelTextColors = labelTextColors;
86176
86177			// data points
86178			model.dataPoints = tooltipItems;
86179
86180			// We need to determine alignment of the tooltip
86181			tooltipSize = getTooltipSize(this, model);
86182			alignment = determineAlignment(this, tooltipSize);
86183			// Final Size and Position
86184			backgroundPoint = getBackgroundPoint(model, tooltipSize, alignment, me._chart);
86185		} else {
86186			model.opacity = 0;
86187		}
86188
86189		model.xAlign = alignment.xAlign;
86190		model.yAlign = alignment.yAlign;
86191		model.x = backgroundPoint.x;
86192		model.y = backgroundPoint.y;
86193		model.width = tooltipSize.width;
86194		model.height = tooltipSize.height;
86195
86196		// Point where the caret on the tooltip points to
86197		model.caretX = tooltipPosition.x;
86198		model.caretY = tooltipPosition.y;
86199
86200		me._model = model;
86201
86202		if (changed && opts.custom) {
86203			opts.custom.call(me, model);
86204		}
86205
86206		return me;
86207	},
86208
86209	drawCaret: function(tooltipPoint, size) {
86210		var ctx = this._chart.ctx;
86211		var vm = this._view;
86212		var caretPosition = this.getCaretPosition(tooltipPoint, size, vm);
86213
86214		ctx.lineTo(caretPosition.x1, caretPosition.y1);
86215		ctx.lineTo(caretPosition.x2, caretPosition.y2);
86216		ctx.lineTo(caretPosition.x3, caretPosition.y3);
86217	},
86218	getCaretPosition: function(tooltipPoint, size, vm) {
86219		var x1, x2, x3, y1, y2, y3;
86220		var caretSize = vm.caretSize;
86221		var cornerRadius = vm.cornerRadius;
86222		var xAlign = vm.xAlign;
86223		var yAlign = vm.yAlign;
86224		var ptX = tooltipPoint.x;
86225		var ptY = tooltipPoint.y;
86226		var width = size.width;
86227		var height = size.height;
86228
86229		if (yAlign === 'center') {
86230			y2 = ptY + (height / 2);
86231
86232			if (xAlign === 'left') {
86233				x1 = ptX;
86234				x2 = x1 - caretSize;
86235				x3 = x1;
86236
86237				y1 = y2 + caretSize;
86238				y3 = y2 - caretSize;
86239			} else {
86240				x1 = ptX + width;
86241				x2 = x1 + caretSize;
86242				x3 = x1;
86243
86244				y1 = y2 - caretSize;
86245				y3 = y2 + caretSize;
86246			}
86247		} else {
86248			if (xAlign === 'left') {
86249				x2 = ptX + cornerRadius + (caretSize);
86250				x1 = x2 - caretSize;
86251				x3 = x2 + caretSize;
86252			} else if (xAlign === 'right') {
86253				x2 = ptX + width - cornerRadius - caretSize;
86254				x1 = x2 - caretSize;
86255				x3 = x2 + caretSize;
86256			} else {
86257				x2 = vm.caretX;
86258				x1 = x2 - caretSize;
86259				x3 = x2 + caretSize;
86260			}
86261			if (yAlign === 'top') {
86262				y1 = ptY;
86263				y2 = y1 - caretSize;
86264				y3 = y1;
86265			} else {
86266				y1 = ptY + height;
86267				y2 = y1 + caretSize;
86268				y3 = y1;
86269				// invert drawing order
86270				var tmp = x3;
86271				x3 = x1;
86272				x1 = tmp;
86273			}
86274		}
86275		return {x1: x1, x2: x2, x3: x3, y1: y1, y2: y2, y3: y3};
86276	},
86277
86278	drawTitle: function(pt, vm, ctx, opacity) {
86279		var title = vm.title;
86280
86281		if (title.length) {
86282			ctx.textAlign = vm._titleAlign;
86283			ctx.textBaseline = 'top';
86284
86285			var titleFontSize = vm.titleFontSize;
86286			var titleSpacing = vm.titleSpacing;
86287
86288			ctx.fillStyle = mergeOpacity(vm.titleFontColor, opacity);
86289			ctx.font = helpers.fontString(titleFontSize, vm._titleFontStyle, vm._titleFontFamily);
86290
86291			var i, len;
86292			for (i = 0, len = title.length; i < len; ++i) {
86293				ctx.fillText(title[i], pt.x, pt.y);
86294				pt.y += titleFontSize + titleSpacing; // Line Height and spacing
86295
86296				if (i + 1 === title.length) {
86297					pt.y += vm.titleMarginBottom - titleSpacing; // If Last, add margin, remove spacing
86298				}
86299			}
86300		}
86301	},
86302
86303	drawBody: function(pt, vm, ctx, opacity) {
86304		var bodyFontSize = vm.bodyFontSize;
86305		var bodySpacing = vm.bodySpacing;
86306		var body = vm.body;
86307
86308		ctx.textAlign = vm._bodyAlign;
86309		ctx.textBaseline = 'top';
86310		ctx.font = helpers.fontString(bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily);
86311
86312		// Before Body
86313		var xLinePadding = 0;
86314		var fillLineOfText = function(line) {
86315			ctx.fillText(line, pt.x + xLinePadding, pt.y);
86316			pt.y += bodyFontSize + bodySpacing;
86317		};
86318
86319		// Before body lines
86320		ctx.fillStyle = mergeOpacity(vm.bodyFontColor, opacity);
86321		helpers.each(vm.beforeBody, fillLineOfText);
86322
86323		var drawColorBoxes = vm.displayColors;
86324		xLinePadding = drawColorBoxes ? (bodyFontSize + 2) : 0;
86325
86326		// Draw body lines now
86327		helpers.each(body, function(bodyItem, i) {
86328			var textColor = mergeOpacity(vm.labelTextColors[i], opacity);
86329			ctx.fillStyle = textColor;
86330			helpers.each(bodyItem.before, fillLineOfText);
86331
86332			helpers.each(bodyItem.lines, function(line) {
86333				// Draw Legend-like boxes if needed
86334				if (drawColorBoxes) {
86335					// Fill a white rect so that colours merge nicely if the opacity is < 1
86336					ctx.fillStyle = mergeOpacity(vm.legendColorBackground, opacity);
vendor: 4,824 bytes, lines 86337-86540
86337					ctx.fillRect(pt.x, pt.y, bodyFontSize, bodyFontSize);
86338
86339					// Border
86340					ctx.lineWidth = 1;
86341					ctx.strokeStyle = mergeOpacity(vm.labelColors[i].borderColor, opacity);
86342					ctx.strokeRect(pt.x, pt.y, bodyFontSize, bodyFontSize);
86343
86344					// Inner square
86345					ctx.fillStyle = mergeOpacity(vm.labelColors[i].backgroundColor, opacity);
86346					ctx.fillRect(pt.x + 1, pt.y + 1, bodyFontSize - 2, bodyFontSize - 2);
86347					ctx.fillStyle = textColor;
86348				}
86349
86350				fillLineOfText(line);
86351			});
86352
86353			helpers.each(bodyItem.after, fillLineOfText);
86354		});
86355
86356		// Reset back to 0 for after body
86357		xLinePadding = 0;
86358
86359		// After body lines
86360		helpers.each(vm.afterBody, fillLineOfText);
86361		pt.y -= bodySpacing; // Remove last body spacing
86362	},
86363
86364	drawFooter: function(pt, vm, ctx, opacity) {
86365		var footer = vm.footer;
86366
86367		if (footer.length) {
86368			pt.y += vm.footerMarginTop;
86369
86370			ctx.textAlign = vm._footerAlign;
86371			ctx.textBaseline = 'top';
86372
86373			ctx.fillStyle = mergeOpacity(vm.footerFontColor, opacity);
86374			ctx.font = helpers.fontString(vm.footerFontSize, vm._footerFontStyle, vm._footerFontFamily);
86375
86376			helpers.each(footer, function(line) {
86377				ctx.fillText(line, pt.x, pt.y);
86378				pt.y += vm.footerFontSize + vm.footerSpacing;
86379			});
86380		}
86381	},
86382
86383	drawBackground: function(pt, vm, ctx, tooltipSize, opacity) {
86384		ctx.fillStyle = mergeOpacity(vm.backgroundColor, opacity);
86385		ctx.strokeStyle = mergeOpacity(vm.borderColor, opacity);
86386		ctx.lineWidth = vm.borderWidth;
86387		var xAlign = vm.xAlign;
86388		var yAlign = vm.yAlign;
86389		var x = pt.x;
86390		var y = pt.y;
86391		var width = tooltipSize.width;
86392		var height = tooltipSize.height;
86393		var radius = vm.cornerRadius;
86394
86395		ctx.beginPath();
86396		ctx.moveTo(x + radius, y);
86397		if (yAlign === 'top') {
86398			this.drawCaret(pt, tooltipSize);
86399		}
86400		ctx.lineTo(x + width - radius, y);
86401		ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
86402		if (yAlign === 'center' && xAlign === 'right') {
86403			this.drawCaret(pt, tooltipSize);
86404		}
86405		ctx.lineTo(x + width, y + height - radius);
86406		ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
86407		if (yAlign === 'bottom') {
86408			this.drawCaret(pt, tooltipSize);
86409		}
86410		ctx.lineTo(x + radius, y + height);
86411		ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
86412		if (yAlign === 'center' && xAlign === 'left') {
86413			this.drawCaret(pt, tooltipSize);
86414		}
86415		ctx.lineTo(x, y + radius);
86416		ctx.quadraticCurveTo(x, y, x + radius, y);
86417		ctx.closePath();
86418
86419		ctx.fill();
86420
86421		if (vm.borderWidth > 0) {
86422			ctx.stroke();
86423		}
86424	},
86425
86426	draw: function() {
86427		var ctx = this._chart.ctx;
86428		var vm = this._view;
86429
86430		if (vm.opacity === 0) {
86431			return;
86432		}
86433
86434		var tooltipSize = {
86435			width: vm.width,
86436			height: vm.height
86437		};
86438		var pt = {
86439			x: vm.x,
86440			y: vm.y
86441		};
86442
86443		// IE11/Edge does not like very small opacities, so snap to 0
86444		var opacity = Math.abs(vm.opacity < 1e-3) ? 0 : vm.opacity;
86445
86446		// Truthy/falsey value for empty tooltip
86447		var hasTooltipContent = vm.title.length || vm.beforeBody.length || vm.body.length || vm.afterBody.length || vm.footer.length;
86448
86449		if (this._options.enabled && hasTooltipContent) {
86450			// Draw Background
86451			this.drawBackground(pt, vm, ctx, tooltipSize, opacity);
86452
86453			// Draw Title, Body, and Footer
86454			pt.x += vm.xPadding;
86455			pt.y += vm.yPadding;
86456
86457			// Titles
86458			this.drawTitle(pt, vm, ctx, opacity);
86459
86460			// Body
86461			this.drawBody(pt, vm, ctx, opacity);
86462
86463			// Footer
86464			this.drawFooter(pt, vm, ctx, opacity);
86465		}
86466	},
86467
86468	/**
86469	 * Handle an event
86470	 * @private
86471	 * @param {IEvent} event - The event to handle
86472	 * @returns {Boolean} true if the tooltip changed
86473	 */
86474	handleEvent: function(e) {
86475		var me = this;
86476		var options = me._options;
86477		var changed = false;
86478
86479		me._lastActive = me._lastActive || [];
86480
86481		// Find Active Elements for tooltips
86482		if (e.type === 'mouseout') {
86483			me._active = [];
86484		} else {
86485			me._active = me._chart.getElementsAtEventForMode(e, options.mode, options);
86486		}
86487
86488		// Remember Last Actives
86489		changed = !helpers.arrayEquals(me._active, me._lastActive);
86490
86491		// Only handle target event on tooltip change
86492		if (changed) {
86493			me._lastActive = me._active;
86494
86495			if (options.enabled || options.custom) {
86496				me._eventPosition = {
86497					x: e.x,
86498					y: e.y
86499				};
86500
86501				me.update(true);
86502				me.pivot();
86503			}
86504		}
86505
86506		return changed;
86507	}
86508});
86509
86510/**
86511 * @namespace Chart.Tooltip.positioners
86512 */
86513exports.positioners = positioners;
86514
86515
86516},{"26":26,"27":27,"46":46}],37:[function(require,module,exports){
86517'use strict';
86518
86519var defaults = require(26);
86520var Element = require(27);
86521var helpers = require(46);
86522
86523defaults._set('global', {
86524	elements: {
86525		arc: {
86526			backgroundColor: defaults.global.defaultColor,
86527			borderColor: '#fff',
86528			borderWidth: 2
86529		}
86530	}
86531});
86532
86533module.exports = Element.extend({
86534	inLabelRange: function(mouseX) {
86535		var vm = this._view;
86536
86537		if (vm) {
86538			return (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hoverRadius, 2));
86539		}
86540		return false;
86541	},
86542
86543	inRange: function(chartX, chartY) {
86544		var vm = this._view;
86545
86546		if (vm) {
86547			var pointRelativePosition = helpers.getAngleFromPoint(vm, {x: chartX, y: chartY});
86548			var	angle = pointRelativePosition.angle;
86549			var distance = pointRelativePosition.distance;
86550
86551			// Sanitise angle range
86552			var startAngle = vm.startAngle;
86553			var endAngle = vm.endAngle;
86554			while (endAngle < startAngle) {
86555				endAngle += 2.0 * Math.PI;
86556			}
86557			while (angle > endAngle) {
86558				angle -= 2.0 * Math.PI;
86559			}
86560			while (angle < startAngle) {
86561				angle += 2.0 * Math.PI;
86562			}
86563
86564			// Check if within the range of the open/close angle
86565			var betweenAngles = (angle >= startAngle && angle <= endAngle);
86566			var withinRadius = (distance >= vm.innerRadius && distance <= vm.outerRadius);
86567
86568			return (betweenAngles && withinRadius);
86569		}
86570		return false;
86571	},
86572
86573	getCenterPoint: function() {
86574		var vm = this._view;
86575		var halfAngle = (vm.startAngle + vm.endAngle) / 2;
86576		var halfRadius = (vm.innerRadius + vm.outerRadius) / 2;
86577		return {
86578			x: vm.x + Math.cos(halfAngle) * halfRadius,
86579			y: vm.y + Math.sin(halfAngle) * halfRadius
86580		};
86581	},
86582
86583	getArea: function() {
86584		var vm = this._view;
86585		return Math.PI * ((vm.endAngle - vm.startAngle) / (2 * Math.PI)) * (Math.pow(vm.outerRadius, 2) - Math.pow(vm.innerRadius, 2));
86586	},
86587
86588	tooltipPosition: function() {
86589		var vm = this._view;
86590		var centreAngle = vm.startAngle + ((vm.endAngle - vm.startAngle) / 2);
86591		var rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius;
86592
86593		return {
86594			x: vm.x + (Math.cos(centreAngle) * rangeFromCentre),
86595			y: vm.y + (Math.sin(centreAngle) * rangeFromCentre)
86596		};
86597	},
86598
86599	draw: function() {
86600		var ctx = this._chart.ctx;
86601		var vm = this._view;
86602		var sA = vm.startAngle;
86603		var eA = vm.endAngle;
86604
86605		ctx.beginPath();
86606
86607		ctx.arc(vm.x, vm.y, vm.outerRadius, sA, eA);
86608		ctx.arc(vm.x, vm.y, vm.innerRadius, eA, sA, true);
86609
86610		ctx.closePath();
86611		ctx.strokeStyle = vm.borderColor;
86612		ctx.lineWidth = vm.borderWidth;
86613
86614		ctx.fillStyle = vm.backgroundColor;
86615
86616		ctx.fill();
86617		ctx.lineJoin = 'bevel';
86618
86619		if (vm.borderWidth) {
86620			ctx.stroke();
86621		}
86622	}
86623});
86624
86625},{"26":26,"27":27,"46":46}],38:[function(require,module,exports){
86626'use strict';
86627
86628var defaults = require(26);
86629var Element = require(27);
86630var helpers = require(46);
86631
86632var globalDefaults = defaults.global;
86633
86634defaults._set('global', {
86635	elements: {
86636		line: {
86637			tension: 0.4,
86638			backgroundColor: globalDefaults.defaultColor,
86639			borderWidth: 3,
86640			borderColor: globalDefaults.defaultColor,
86641			borderCapStyle: 'butt',
86642			borderDash: [],
86643			borderDashOffset: 0.0,
86644			borderJoinStyle: 'miter',
86645			capBezierPoints: true,
86646			fill: true, // do we fill in the area between the line and its base axis
86647		}
86648	}
86649});
86650
86651module.exports = Element.extend({
86652	draw: function() {
86653		var me = this;
86654		var vm = me._view;
86655		var ctx = me._chart.ctx;
86656		var spanGaps = vm.spanGaps;
86657		var points = me._children.slice(); // clone array
86658		var globalOptionLineElements = globalDefaults.elements.line;
86659		var lastDrawnIndex = -1;
86660		var index, current, previous, currentVM;
86661
86662		// If we are looping, adding the first point again
86663		if (me._loop && points.length) {
86664			points.push(points[0]);
86665		}
86666
86667		ctx.save();
86668
86669		// Stroke Line Options
86670		ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle;
86671
86672		// IE 9 and 10 do not support line dash
86673		if (ctx.setLineDash) {
86674			ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash);
86675		}
86676
86677		ctx.lineDashOffset = vm.borderDashOffset || globalOptionLineElements.borderDashOffset;
86678		ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle;
86679		ctx.lineWidth = vm.borderWidth || globalOptionLineElements.borderWidth;
86680		ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor;
86681
86682		// Stroke Line
86683		ctx.beginPath();
86684		lastDrawnIndex = -1;
86685
86686		for (index = 0; index < points.length; ++index) {
86687			current = points[index];
86688			previous = helpers.previousItem(points, index);
86689			currentVM = current._view;
86690
86691			// First point moves to it's starting position no matter what
86692			if (index === 0) {
86693				if (!currentVM.skip) {
86694					ctx.moveTo(currentVM.x, currentVM.y);
86695					lastDrawnIndex = index;
86696				}
86697			} else {
86698				previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex];
86699
86700				if (!currentVM.skip) {
86701					if ((lastDrawnIndex !== (index - 1) && !spanGaps) || lastDrawnIndex === -1) {
86702						// There was a gap and this is the first point after the gap
86703						ctx.moveTo(currentVM.x, currentVM.y);
86704					} else {
86705						// Line to next point
86706						helpers.canvas.lineTo(ctx, previous._view, current._view);
86707					}
86708					lastDrawnIndex = index;
86709				}
86710			}
86711		}
86712
86713		ctx.stroke();
86714		ctx.restore();
86715	}
86716});
86717
86718},{"26":26,"27":27,"46":46}],39:[function(require,module,exports){
86719'use strict';
86720
86721var defaults = require(26);
86722var Element = require(27);
86723var helpers = require(46);
86724
86725var defaultColor = defaults.global.defaultColor;
86726
86727defaults._set('global', {
86728	elements: {
86729		point: {
86730			radius: 3,
86731			pointStyle: 'circle',
86732			backgroundColor: defaultColor,
86733			borderColor: defaultColor,
86734			borderWidth: 1,
86735			// Hover
86736			hitRadius: 1,
86737			hoverRadius: 4,
86738			hoverBorderWidth: 1
86739		}
86740	}
86741});
86742
86743function xRange(mouseX) {
86744	var vm = this._view;
86745	return vm ? (Math.abs(mouseX - vm.x) < vm.radius + vm.hitRadius) : false;
86746}
86747
86748function yRange(mouseY) {
86749	var vm = this._view;
86750	return vm ? (Math.abs(mouseY - vm.y) < vm.radius + vm.hitRadius) : false;
86751}
86752
86753module.exports = Element.extend({
86754	inRange: function(mouseX, mouseY) {
86755		var vm = this._view;
86756		return vm ? ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(vm.hitRadius + vm.radius, 2)) : false;
86757	},
86758
86759	inLabelRange: xRange,
86760	inXRange: xRange,
86761	inYRange: yRange,
86762
86763	getCenterPoint: function() {
86764		var vm = this._view;
86765		return {
86766			x: vm.x,
86767			y: vm.y
86768		};
86769	},
86770
86771	getArea: function() {
86772		return Math.PI * Math.pow(this._view.radius, 2);
86773	},
86774
86775	tooltipPosition: function() {
86776		var vm = this._view;
86777		return {
86778			x: vm.x,
86779			y: vm.y,
86780			padding: vm.radius + vm.borderWidth
86781		};
86782	},
86783
86784	draw: function(chartArea) {
86785		var vm = this._view;
86786		var model = this._model;
86787		var ctx = this._chart.ctx;
86788		var pointStyle = vm.pointStyle;
86789		var rotation = vm.rotation;
86790		var radius = vm.radius;
86791		var x = vm.x;
86792		var y = vm.y;
86793		var errMargin = 1.01; // 1.01 is margin for Accumulated error. (Especially Edge, IE.)
86794
86795		if (vm.skip) {
86796			return;
86797		}
86798
86799		// Clipping for Points.
86800		if (chartArea === undefined || (model.x >= chartArea.left && chartArea.right * errMargin >= model.x && model.y >= chartArea.top && chartArea.bottom * errMargin >= model.y)) {
86801			ctx.strokeStyle = vm.borderColor || defaultColor;
86802			ctx.lineWidth = helpers.valueOrDefault(vm.borderWidth, defaults.global.elements.point.borderWidth);
86803			ctx.fillStyle = vm.backgroundColor || defaultColor;
86804			helpers.canvas.drawPoint(ctx, pointStyle, radius, x, y, rotation);
86805		}
86806	}
86807});
86808
86809},{"26":26,"27":27,"46":46}],40:[function(require,module,exports){
86810'use strict';
86811
86812var defaults = require(26);
86813var Element = require(27);
86814
86815defaults._set('global', {
86816	elements: {
86817		rectangle: {
86818			backgroundColor: defaults.global.defaultColor,
86819			borderColor: defaults.global.defaultColor,
86820			borderSkipped: 'bottom',
86821			borderWidth: 0
86822		}
86823	}
86824});
86825
86826function isVertical(bar) {
86827	return bar._view.width !== undefined;
86828}
86829
86830/**
86831 * Helper function to get the bounds of the bar regardless of the orientation
86832 * @param bar {Chart.Element.Rectangle} the bar
86833 * @return {Bounds} bounds of the bar
86834 * @private
86835 */
86836function getBarBounds(bar) {
86837	var vm = bar._view;
86838	var x1, x2, y1, y2;
86839
86840	if (isVertical(bar)) {
86841		// vertical
86842		var halfWidth = vm.width / 2;
86843		x1 = vm.x - halfWidth;
86844		x2 = vm.x + halfWidth;
86845		y1 = Math.min(vm.y, vm.base);
86846		y2 = Math.max(vm.y, vm.base);
86847	} else {
86848		// horizontal bar
86849		var halfHeight = vm.height / 2;
86850		x1 = Math.min(vm.x, vm.base);
86851		x2 = Math.max(vm.x, vm.base);
86852		y1 = vm.y - halfHeight;
86853		y2 = vm.y + halfHeight;
86854	}
86855
86856	return {
86857		left: x1,
86858		top: y1,
86859		right: x2,
86860		bottom: y2
86861	};
86862}
86863
86864module.exports = Element.extend({
86865	draw: function() {
86866		var ctx = this._chart.ctx;
86867		var vm = this._view;
86868		var left, right, top, bottom, signX, signY, borderSkipped;
86869		var borderWidth = vm.borderWidth;
86870
86871		if (!vm.horizontal) {
86872			// bar
86873			left = vm.x - vm.width / 2;
86874			right = vm.x + vm.width / 2;
86875			top = vm.y;
86876			bottom = vm.base;
86877			signX = 1;
86878			signY = bottom > top ? 1 : -1;
86879			borderSkipped = vm.borderSkipped || 'bottom';
86880		} else {
86881			// horizontal bar
86882			left = vm.base;
86883			right = vm.x;
86884			top = vm.y - vm.height / 2;
86885			bottom = vm.y + vm.height / 2;
86886			signX = right > left ? 1 : -1;
86887			signY = 1;
86888			borderSkipped = vm.borderSkipped || 'left';
86889		}
86890
86891		// Canvas doesn't allow us to stroke inside the width so we can
86892		// adjust the sizes to fit if we're setting a stroke on the line
86893		if (borderWidth) {
86894			// borderWidth shold be less than bar width and bar height.
86895			var barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom));
86896			borderWidth = borderWidth > barSize ? barSize : borderWidth;
86897			var halfStroke = borderWidth / 2;
86898			// Adjust borderWidth when bar top position is near vm.base(zero).
86899			var borderLeft = left + (borderSkipped !== 'left' ? halfStroke * signX : 0);
86900			var borderRight = right + (borderSkipped !== 'right' ? -halfStroke * signX : 0);
86901			var borderTop = top + (borderSkipped !== 'top' ? halfStroke * signY : 0);
86902			var borderBottom = bottom + (borderSkipped !== 'bottom' ? -halfStroke * signY : 0);
86903			// not become a vertical line?
86904			if (borderLeft !== borderRight) {
86905				top = borderTop;
86906				bottom = borderBottom;
86907			}
86908			// not become a horizontal line?
86909			if (borderTop !== borderBottom) {
86910				left = borderLeft;
86911				right = borderRight;
86912			}
86913		}
86914
86915		ctx.beginPath();
86916		ctx.fillStyle = vm.backgroundColor;
86917		ctx.strokeStyle = vm.borderColor;
86918		ctx.lineWidth = borderWidth;
86919
86920		// Corner points, from bottom-left to bottom-right clockwise
86921		// | 1 2 |
86922		// | 0 3 |
86923		var corners = [
86924			[left, bottom],
86925			[left, top],
86926			[right, top],
86927			[right, bottom]
86928		];
86929
86930		// Find first (starting) corner with fallback to 'bottom'
86931		var borders = ['bottom', 'left', 'top', 'right'];
86932		var startCorner = borders.indexOf(borderSkipped, 0);
86933		if (startCorner === -1) {
86934			startCorner = 0;
86935		}
86936
86937		function cornerAt(index) {
86938			return corners[(startCorner + index) % 4];
86939		}
86940
86941		// Draw rectangle from 'startCorner'
86942		var corner = cornerAt(0);
86943		ctx.moveTo(corner[0], corner[1]);
86944
86945		for (var i = 1; i < 4; i++) {
86946			corner = cornerAt(i);
86947			ctx.lineTo(corner[0], corner[1]);
86948		}
86949
86950		ctx.fill();
86951		if (borderWidth) {
86952			ctx.stroke();
86953		}
86954	},
86955
86956	height: function() {
86957		var vm = this._view;
86958		return vm.base - vm.y;
86959	},
86960
86961	inRange: function(mouseX, mouseY) {
86962		var inRange = false;
86963
86964		if (this._view) {
86965			var bounds = getBarBounds(this);
86966			inRange = mouseX >= bounds.left && mouseX <= bounds.right && mouseY >= bounds.top && mouseY <= bounds.bottom;
86967		}
86968
86969		return inRange;
86970	},
86971
86972	inLabelRange: function(mouseX, mouseY) {
86973		var me = this;
86974		if (!me._view) {
86975			return false;
86976		}
86977
86978		var inRange = false;
86979		var bounds = getBarBounds(me);
86980
86981		if (isVertical(me)) {
86982			inRange = mouseX >= bounds.left && mouseX <= bounds.right;
86983		} else {
86984			inRange = mouseY >= bounds.top && mouseY <= bounds.bottom;
86985		}
86986
86987		return inRange;
86988	},
86989
86990	inXRange: function(mouseX) {
86991		var bounds = getBarBounds(this);
86992		return mouseX >= bounds.left && mouseX <= bounds.right;
86993	},
86994
86995	inYRange: function(mouseY) {
86996		var bounds = getBarBounds(this);
86997		return mouseY >= bounds.top && mouseY <= bounds.bottom;
86998	},
86999
87000	getCenterPoint: function() {
87001		var vm = this._view;
87002		var x, y;
87003		if (isVertical(this)) {
87004			x = vm.x;
87005			y = (vm.y + vm.base) / 2;
87006		} else {
87007			x = (vm.x + vm.base) / 2;
87008			y = vm.y;
87009		}
87010
87011		return {x: x, y: y};
87012	},
87013
87014	getArea: function() {
87015		var vm = this._view;
87016		return vm.width * Math.abs(vm.y - vm.base);
87017	},
87018
87019	tooltipPosition: function() {
87020		var vm = this._view;
87021		return {
87022			x: vm.x,
87023			y: vm.y
87024		};
87025	}
87026});
87027
87028},{"26":26,"27":27}],41:[function(require,module,exports){
87029'use strict';
87030
87031module.exports = {};
87032module.exports.Arc = require(37);
87033module.exports.Line = require(38);
87034module.exports.Point = require(39);
87035module.exports.Rectangle = require(40);
87036
87037},{"37":37,"38":38,"39":39,"40":40}],42:[function(require,module,exports){
87038'use strict';
87039
87040var helpers = require(43);
87041
87042/**
87043 * @namespace Chart.helpers.canvas
87044 */
87045var exports = module.exports = {
87046	/**
87047	 * Clears the entire canvas associated to the given `chart`.
87048	 * @param {Chart} chart - The chart for which to clear the canvas.
87049	 */
87050	clear: function(chart) {
87051		chart.ctx.clearRect(0, 0, chart.width, chart.height);
87052	},
87053
87054	/**
87055	 * Creates a "path" for a rectangle with rounded corners at position (x, y) with a
87056	 * given size (width, height) and the same `radius` for all corners.
87057	 * @param {CanvasRenderingContext2D} ctx - The canvas 2D Context.
87058	 * @param {Number} x - The x axis of the coordinate for the rectangle starting point.
87059	 * @param {Number} y - The y axis of the coordinate for the rectangle starting point.
87060	 * @param {Number} width - The rectangle's width.
87061	 * @param {Number} height - The rectangle's height.
87062	 * @param {Number} radius - The rounded amount (in pixels) for the four corners.
87063	 * @todo handle `radius` as top-left, top-right, bottom-right, bottom-left array/object?
87064	 */
87065	roundedRect: function(ctx, x, y, width, height, radius) {
87066		if (radius) {
87067			// NOTE(SB) `epsilon` helps to prevent minor artifacts appearing
87068			// on Chrome when `r` is exactly half the height or the width.
87069			var epsilon = 0.0000001;
87070			var r = Math.min(radius, (height / 2) - epsilon, (width / 2) - epsilon);
87071
87072			ctx.moveTo(x + r, y);
87073			ctx.lineTo(x + width - r, y);
87074			ctx.arcTo(x + width, y, x + width, y + r, r);
87075			ctx.lineTo(x + width, y + height - r);
87076			ctx.arcTo(x + width, y + height, x + width - r, y + height, r);
87077			ctx.lineTo(x + r, y + height);
87078			ctx.arcTo(x, y + height, x, y + height - r, r);
87079			ctx.lineTo(x, y + r);
87080			ctx.arcTo(x, y, x + r, y, r);
87081			ctx.closePath();
87082			ctx.moveTo(x, y);
87083		} else {
87084			ctx.rect(x, y, width, height);
87085		}
87086	},
87087
87088	drawPoint: function(ctx, style, radius, x, y, rotation) {
87089		var type, edgeLength, xOffset, yOffset, height, size;
87090		rotation = rotation || 0;
87091
87092		if (style && typeof style === 'object') {
87093			type = style.toString();
87094			if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') {
87095				ctx.drawImage(style, x - style.width / 2, y - style.height / 2, style.width, style.height);
87096				return;
87097			}
87098		}
87099
87100		if (isNaN(radius) || radius <= 0) {
87101			return;
87102		}
87103
87104		ctx.save();
87105		ctx.translate(x, y);
87106		ctx.rotate(rotation * Math.PI / 180);
87107		ctx.beginPath();
87108
87109		switch (style) {
87110		// Default includes circle
87111		default:
87112			ctx.arc(0, 0, radius, 0, Math.PI * 2);
87113			ctx.closePath();
87114			break;
87115		case 'triangle':
87116			edgeLength = 3 * radius / Math.sqrt(3);
87117			height = edgeLength * Math.sqrt(3) / 2;
87118			ctx.moveTo(-edgeLength / 2, height / 3);
87119			ctx.lineTo(edgeLength / 2, height / 3);
87120			ctx.lineTo(0, -2 * height / 3);
87121			ctx.closePath();
87122			break;
87123		case 'rect':
87124			size = 1 / Math.SQRT2 * radius;
87125			ctx.rect(-size, -size, 2 * size, 2 * size);
87126			break;
87127		case 'rectRounded':
87128			var offset = radius / Math.SQRT2;
87129			var leftX = -offset;
87130			var topY = -offset;
87131			var sideSize = Math.SQRT2 * radius;
87132
87133			// NOTE(SB) the rounded rect implementation changed to use `arcTo`
87134			// instead of `quadraticCurveTo` since it generates better results
87135			// when rect is almost a circle. 0.425 (instead of 0.5) produces
87136			// results visually closer to the previous impl.
87137			this.roundedRect(ctx, leftX, topY, sideSize, sideSize, radius * 0.425);
87138			break;
87139		case 'rectRot':
87140			size = 1 / Math.SQRT2 * radius;
87141			ctx.moveTo(-size, 0);
87142			ctx.lineTo(0, size);
87143			ctx.lineTo(size, 0);
87144			ctx.lineTo(0, -size);
87145			ctx.closePath();
87146			break;
87147		case 'cross':
87148			ctx.moveTo(0, radius);
87149			ctx.lineTo(0, -radius);
87150			ctx.moveTo(-radius, 0);
87151			ctx.lineTo(radius, 0);
87152			break;
87153		case 'crossRot':
87154			xOffset = Math.cos(Math.PI / 4) * radius;
87155			yOffset = Math.sin(Math.PI / 4) * radius;
87156			ctx.moveTo(-xOffset, -yOffset);
87157			ctx.lineTo(xOffset, yOffset);
87158			ctx.moveTo(-xOffset, yOffset);
87159			ctx.lineTo(xOffset, -yOffset);
87160			break;
87161		case 'star':
87162			ctx.moveTo(0, radius);
87163			ctx.lineTo(0, -radius);
87164			ctx.moveTo(-radius, 0);
87165			ctx.lineTo(radius, 0);
87166			xOffset = Math.cos(Math.PI / 4) * radius;
87167			yOffset = Math.sin(Math.PI / 4) * radius;
87168			ctx.moveTo(-xOffset, -yOffset);
87169			ctx.lineTo(xOffset, yOffset);
87170			ctx.moveTo(-xOffset, yOffset);
87171			ctx.lineTo(xOffset, -yOffset);
87172			break;
87173		case 'line':
87174			ctx.moveTo(-radius, 0);
87175			ctx.lineTo(radius, 0);
87176			break;
87177		case 'dash':
87178			ctx.moveTo(0, 0);
87179			ctx.lineTo(radius, 0);
87180			break;
87181		}
87182
87183		ctx.fill();
87184		ctx.stroke();
87185		ctx.restore();
87186	},
87187
87188	clipArea: function(ctx, area) {
87189		ctx.save();
87190		ctx.beginPath();
87191		ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top);
87192		ctx.clip();
87193	},
87194
87195	unclipArea: function(ctx) {
87196		ctx.restore();
87197	},
87198
87199	lineTo: function(ctx, previous, target, flip) {
87200		if (target.steppedLine) {
87201			if ((target.steppedLine === 'after' && !flip) || (target.steppedLine !== 'after' && flip)) {
87202				ctx.lineTo(previous.x, target.y);
87203			} else {
87204				ctx.lineTo(target.x, previous.y);
87205			}
87206			ctx.lineTo(target.x, target.y);
87207			return;
87208		}
87209
87210		if (!target.tension) {
87211			ctx.lineTo(target.x, target.y);
87212			return;
87213		}
87214
87215		ctx.bezierCurveTo(
87216			flip ? previous.controlPointPreviousX : previous.controlPointNextX,
87217			flip ? previous.controlPointPreviousY : previous.controlPointNextY,
87218			flip ? target.controlPointNextX : target.controlPointPreviousX,
87219			flip ? target.controlPointNextY : target.controlPointPreviousY,
87220			target.x,
87221			target.y);
87222	}
87223};
87224
87225// DEPRECATIONS
87226
87227/**
87228 * Provided for backward compatibility, use Chart.helpers.canvas.clear instead.
87229 * @namespace Chart.helpers.clear
87230 * @deprecated since version 2.7.0
87231 * @todo remove at version 3
87232 * @private
87233 */
87234helpers.clear = exports.clear;
87235
87236/**
87237 * Provided for backward compatibility, use Chart.helpers.canvas.roundedRect instead.
87238 * @namespace Chart.helpers.drawRoundedRectangle
87239 * @deprecated since version 2.7.0
87240 * @todo remove at version 3
87241 * @private
87242 */
87243helpers.drawRoundedRectangle = function(ctx) {
87244	ctx.beginPath();
87245	exports.roundedRect.apply(exports, arguments);
87246};
87247
87248},{"43":43}],43:[function(require,module,exports){
87249'use strict';
87250
87251/**
87252 * @namespace Chart.helpers
87253 */
87254var helpers = {
87255	/**
87256	 * An empty function that can be used, for example, for optional callback.
87257	 */
87258	noop: function() {},
87259
87260	/**
87261	 * Returns a unique id, sequentially generated from a global variable.
87262	 * @returns {Number}
87263	 * @function
87264	 */
87265	uid: (function() {
87266		var id = 0;
87267		return function() {
87268			return id++;
87269		};
87270	}()),
87271
87272	/**
87273	 * Returns true if `value` is neither null nor undefined, else returns false.
87274	 * @param {*} value - The value to test.
87275	 * @returns {Boolean}
87276	 * @since 2.7.0
87277	 */
87278	isNullOrUndef: function(value) {
87279		return value === null || typeof value === 'undefined';
87280	},
87281
87282	/**
87283	 * Returns true if `value` is an array, else returns false.
87284	 * @param {*} value - The value to test.
87285	 * @returns {Boolean}
87286	 * @function
87287	 */
87288	isArray: Array.isArray ? Array.isArray : function(value) {
87289		return Object.prototype.toString.call(value) === '[object Array]';
87290	},
87291
87292	/**
87293	 * Returns true if `value` is an object (excluding null), else returns false.
87294	 * @param {*} value - The value to test.
87295	 * @returns {Boolean}
87296	 * @since 2.7.0
87297	 */
87298	isObject: function(value) {
87299		return value !== null && Object.prototype.toString.call(value) === '[object Object]';
87300	},
87301
87302	/**
87303	 * Returns `value` if defined, else returns `defaultValue`.
87304	 * @param {*} value - The value to return if defined.
87305	 * @param {*} defaultValue - The value to return if `value` is undefined.
87306	 * @returns {*}
87307	 */
87308	valueOrDefault: function(value, defaultValue) {
87309		return typeof value === 'undefined' ? defaultValue : value;
87310	},
87311
87312	/**
87313	 * Returns value at the given `index` in array if defined, else returns `defaultValue`.
87314	 * @param {Array} value - The array to lookup for value at `index`.
87315	 * @param {Number} index - The index in `value` to lookup for value.
87316	 * @param {*} defaultValue - The value to return if `value[index]` is undefined.
87317	 * @returns {*}
87318	 */
87319	valueAtIndexOrDefault: function(value, index, defaultValue) {
87320		return helpers.valueOrDefault(helpers.isArray(value) ? value[index] : value, defaultValue);
87321	},
87322
87323	/**
87324	 * Calls `fn` with the given `args` in the scope defined by `thisArg` and returns the
87325	 * value returned by `fn`. If `fn` is not a function, this method returns undefined.
87326	 * @param {Function} fn - The function to call.
87327	 * @param {Array|undefined|null} args - The arguments with which `fn` should be called.
87328	 * @param {Object} [thisArg] - The value of `this` provided for the call to `fn`.
87329	 * @returns {*}
87330	 */
87331	callback: function(fn, args, thisArg) {
87332		if (fn && typeof fn.call === 'function') {
87333			return fn.apply(thisArg, args);
87334		}
87335	},
87336
87337	/**
87338	 * Note(SB) for performance sake, this method should only be used when loopable type
87339	 * is unknown or in none intensive code (not called often and small loopable). Else
87340	 * it's preferable to use a regular for() loop and save extra function calls.
87341	 * @param {Object|Array} loopable - The object or array to be iterated.
87342	 * @param {Function} fn - The function to call for each item.
87343	 * @param {Object} [thisArg] - The value of `this` provided for the call to `fn`.
87344	 * @param {Boolean} [reverse] - If true, iterates backward on the loopable.
87345	 */
87346	each: function(loopable, fn, thisArg, reverse) {
87347		var i, len, keys;
87348		if (helpers.isArray(loopable)) {
87349			len = loopable.length;
87350			if (reverse) {
87351				for (i = len - 1; i >= 0; i--) {
87352					fn.call(thisArg, loopable[i], i);
87353				}
87354			} else {
87355				for (i = 0; i < len; i++) {
87356					fn.call(thisArg, loopable[i], i);
87357				}
87358			}
87359		} else if (helpers.isObject(loopable)) {
87360			keys = Object.keys(loopable);
87361			len = keys.length;
87362			for (i = 0; i < len; i++) {
87363				fn.call(thisArg, loopable[keys[i]], keys[i]);
87364			}
87365		}
87366	},
87367
87368	/**
87369	 * Returns true if the `a0` and `a1` arrays have the same content, else returns false.
87370	 * @see http://stackoverflow.com/a/14853974
87371	 * @param {Array} a0 - The array to compare
87372	 * @param {Array} a1 - The array to compare
87373	 * @returns {Boolean}
87374	 */
87375	arrayEquals: function(a0, a1) {
87376		var i, ilen, v0, v1;
87377
87378		if (!a0 || !a1 || a0.length !== a1.length) {
87379			return false;
vendor: 10,367 bytes, lines 87380-87833
87380		}
87381
87382		for (i = 0, ilen = a0.length; i < ilen; ++i) {
87383			v0 = a0[i];
87384			v1 = a1[i];
87385
87386			if (v0 instanceof Array && v1 instanceof Array) {
87387				if (!helpers.arrayEquals(v0, v1)) {
87388					return false;
87389				}
87390			} else if (v0 !== v1) {
87391				// NOTE: two different object instances will never be equal: {x:20} != {x:20}
87392				return false;
87393			}
87394		}
87395
87396		return true;
87397	},
87398
87399	/**
87400	 * Returns a deep copy of `source` without keeping references on objects and arrays.
87401	 * @param {*} source - The value to clone.
87402	 * @returns {*}
87403	 */
87404	clone: function(source) {
87405		if (helpers.isArray(source)) {
87406			return source.map(helpers.clone);
87407		}
87408
87409		if (helpers.isObject(source)) {
87410			var target = {};
87411			var keys = Object.keys(source);
87412			var klen = keys.length;
87413			var k = 0;
87414
87415			for (; k < klen; ++k) {
87416				target[keys[k]] = helpers.clone(source[keys[k]]);
87417			}
87418
87419			return target;
87420		}
87421
87422		return source;
87423	},
87424
87425	/**
87426	 * The default merger when Chart.helpers.merge is called without merger option.
87427	 * Note(SB): this method is also used by configMerge and scaleMerge as fallback.
87428	 * @private
87429	 */
87430	_merger: function(key, target, source, options) {
87431		var tval = target[key];
87432		var sval = source[key];
87433
87434		if (helpers.isObject(tval) && helpers.isObject(sval)) {
87435			helpers.merge(tval, sval, options);
87436		} else {
87437			target[key] = helpers.clone(sval);
87438		}
87439	},
87440
87441	/**
87442	 * Merges source[key] in target[key] only if target[key] is undefined.
87443	 * @private
87444	 */
87445	_mergerIf: function(key, target, source) {
87446		var tval = target[key];
87447		var sval = source[key];
87448
87449		if (helpers.isObject(tval) && helpers.isObject(sval)) {
87450			helpers.mergeIf(tval, sval);
87451		} else if (!target.hasOwnProperty(key)) {
87452			target[key] = helpers.clone(sval);
87453		}
87454	},
87455
87456	/**
87457	 * Recursively deep copies `source` properties into `target` with the given `options`.
87458	 * IMPORTANT: `target` is not cloned and will be updated with `source` properties.
87459	 * @param {Object} target - The target object in which all sources are merged into.
87460	 * @param {Object|Array(Object)} source - Object(s) to merge into `target`.
87461	 * @param {Object} [options] - Merging options:
87462	 * @param {Function} [options.merger] - The merge method (key, target, source, options)
87463	 * @returns {Object} The `target` object.
87464	 */
87465	merge: function(target, source, options) {
87466		var sources = helpers.isArray(source) ? source : [source];
87467		var ilen = sources.length;
87468		var merge, i, keys, klen, k;
87469
87470		if (!helpers.isObject(target)) {
87471			return target;
87472		}
87473
87474		options = options || {};
87475		merge = options.merger || helpers._merger;
87476
87477		for (i = 0; i < ilen; ++i) {
87478			source = sources[i];
87479			if (!helpers.isObject(source)) {
87480				continue;
87481			}
87482
87483			keys = Object.keys(source);
87484			for (k = 0, klen = keys.length; k < klen; ++k) {
87485				merge(keys[k], target, source, options);
87486			}
87487		}
87488
87489		return target;
87490	},
87491
87492	/**
87493	 * Recursively deep copies `source` properties into `target` *only* if not defined in target.
87494	 * IMPORTANT: `target` is not cloned and will be updated with `source` properties.
87495	 * @param {Object} target - The target object in which all sources are merged into.
87496	 * @param {Object|Array(Object)} source - Object(s) to merge into `target`.
87497	 * @returns {Object} The `target` object.
87498	 */
87499	mergeIf: function(target, source) {
87500		return helpers.merge(target, source, {merger: helpers._mergerIf});
87501	},
87502
87503	/**
87504	 * Applies the contents of two or more objects together into the first object.
87505	 * @param {Object} target - The target object in which all objects are merged into.
87506	 * @param {Object} arg1 - Object containing additional properties to merge in target.
87507	 * @param {Object} argN - Additional objects containing properties to merge in target.
87508	 * @returns {Object} The `target` object.
87509	 */
87510	extend: function(target) {
87511		var setFn = function(value, key) {
87512			target[key] = value;
87513		};
87514		for (var i = 1, ilen = arguments.length; i < ilen; ++i) {
87515			helpers.each(arguments[i], setFn);
87516		}
87517		return target;
87518	},
87519
87520	/**
87521	 * Basic javascript inheritance based on the model created in Backbone.js
87522	 */
87523	inherits: function(extensions) {
87524		var me = this;
87525		var ChartElement = (extensions && extensions.hasOwnProperty('constructor')) ? extensions.constructor : function() {
87526			return me.apply(this, arguments);
87527		};
87528
87529		var Surrogate = function() {
87530			this.constructor = ChartElement;
87531		};
87532
87533		Surrogate.prototype = me.prototype;
87534		ChartElement.prototype = new Surrogate();
87535		ChartElement.extend = helpers.inherits;
87536
87537		if (extensions) {
87538			helpers.extend(ChartElement.prototype, extensions);
87539		}
87540
87541		ChartElement.__super__ = me.prototype;
87542		return ChartElement;
87543	}
87544};
87545
87546module.exports = helpers;
87547
87548// DEPRECATIONS
87549
87550/**
87551 * Provided for backward compatibility, use Chart.helpers.callback instead.
87552 * @function Chart.helpers.callCallback
87553 * @deprecated since version 2.6.0
87554 * @todo remove at version 3
87555 * @private
87556 */
87557helpers.callCallback = helpers.callback;
87558
87559/**
87560 * Provided for backward compatibility, use Array.prototype.indexOf instead.
87561 * Array.prototype.indexOf compatibility: Chrome, Opera, Safari, FF1.5+, IE9+
87562 * @function Chart.helpers.indexOf
87563 * @deprecated since version 2.7.0
87564 * @todo remove at version 3
87565 * @private
87566 */
87567helpers.indexOf = function(array, item, fromIndex) {
87568	return Array.prototype.indexOf.call(array, item, fromIndex);
87569};
87570
87571/**
87572 * Provided for backward compatibility, use Chart.helpers.valueOrDefault instead.
87573 * @function Chart.helpers.getValueOrDefault
87574 * @deprecated since version 2.7.0
87575 * @todo remove at version 3
87576 * @private
87577 */
87578helpers.getValueOrDefault = helpers.valueOrDefault;
87579
87580/**
87581 * Provided for backward compatibility, use Chart.helpers.valueAtIndexOrDefault instead.
87582 * @function Chart.helpers.getValueAtIndexOrDefault
87583 * @deprecated since version 2.7.0
87584 * @todo remove at version 3
87585 * @private
87586 */
87587helpers.getValueAtIndexOrDefault = helpers.valueAtIndexOrDefault;
87588
87589},{}],44:[function(require,module,exports){
87590'use strict';
87591
87592var helpers = require(43);
87593
87594/**
87595 * Easing functions adapted from Robert Penner's easing equations.
87596 * @namespace Chart.helpers.easingEffects
87597 * @see http://www.robertpenner.com/easing/
87598 */
87599var effects = {
87600	linear: function(t) {
87601		return t;
87602	},
87603
87604	easeInQuad: function(t) {
87605		return t * t;
87606	},
87607
87608	easeOutQuad: function(t) {
87609		return -t * (t - 2);
87610	},
87611
87612	easeInOutQuad: function(t) {
87613		if ((t /= 0.5) < 1) {
87614			return 0.5 * t * t;
87615		}
87616		return -0.5 * ((--t) * (t - 2) - 1);
87617	},
87618
87619	easeInCubic: function(t) {
87620		return t * t * t;
87621	},
87622
87623	easeOutCubic: function(t) {
87624		return (t = t - 1) * t * t + 1;
87625	},
87626
87627	easeInOutCubic: function(t) {
87628		if ((t /= 0.5) < 1) {
87629			return 0.5 * t * t * t;
87630		}
87631		return 0.5 * ((t -= 2) * t * t + 2);
87632	},
87633
87634	easeInQuart: function(t) {
87635		return t * t * t * t;
87636	},
87637
87638	easeOutQuart: function(t) {
87639		return -((t = t - 1) * t * t * t - 1);
87640	},
87641
87642	easeInOutQuart: function(t) {
87643		if ((t /= 0.5) < 1) {
87644			return 0.5 * t * t * t * t;
87645		}
87646		return -0.5 * ((t -= 2) * t * t * t - 2);
87647	},
87648
87649	easeInQuint: function(t) {
87650		return t * t * t * t * t;
87651	},
87652
87653	easeOutQuint: function(t) {
87654		return (t = t - 1) * t * t * t * t + 1;
87655	},
87656
87657	easeInOutQuint: function(t) {
87658		if ((t /= 0.5) < 1) {
87659			return 0.5 * t * t * t * t * t;
87660		}
87661		return 0.5 * ((t -= 2) * t * t * t * t + 2);
87662	},
87663
87664	easeInSine: function(t) {
87665		return -Math.cos(t * (Math.PI / 2)) + 1;
87666	},
87667
87668	easeOutSine: function(t) {
87669		return Math.sin(t * (Math.PI / 2));
87670	},
87671
87672	easeInOutSine: function(t) {
87673		return -0.5 * (Math.cos(Math.PI * t) - 1);
87674	},
87675
87676	easeInExpo: function(t) {
87677		return (t === 0) ? 0 : Math.pow(2, 10 * (t - 1));
87678	},
87679
87680	easeOutExpo: function(t) {
87681		return (t === 1) ? 1 : -Math.pow(2, -10 * t) + 1;
87682	},
87683
87684	easeInOutExpo: function(t) {
87685		if (t === 0) {
87686			return 0;
87687		}
87688		if (t === 1) {
87689			return 1;
87690		}
87691		if ((t /= 0.5) < 1) {
87692			return 0.5 * Math.pow(2, 10 * (t - 1));
87693		}
87694		return 0.5 * (-Math.pow(2, -10 * --t) + 2);
87695	},
87696
87697	easeInCirc: function(t) {
87698		if (t >= 1) {
87699			return t;
87700		}
87701		return -(Math.sqrt(1 - t * t) - 1);
87702	},
87703
87704	easeOutCirc: function(t) {
87705		return Math.sqrt(1 - (t = t - 1) * t);
87706	},
87707
87708	easeInOutCirc: function(t) {
87709		if ((t /= 0.5) < 1) {
87710			return -0.5 * (Math.sqrt(1 - t * t) - 1);
87711		}
87712		return 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1);
87713	},
87714
87715	easeInElastic: function(t) {
87716		var s = 1.70158;
87717		var p = 0;
87718		var a = 1;
87719		if (t === 0) {
87720			return 0;
87721		}
87722		if (t === 1) {
87723			return 1;
87724		}
87725		if (!p) {
87726			p = 0.3;
87727		}
87728		if (a < 1) {
87729			a = 1;
87730			s = p / 4;
87731		} else {
87732			s = p / (2 * Math.PI) * Math.asin(1 / a);
87733		}
87734		return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p));
87735	},
87736
87737	easeOutElastic: function(t) {
87738		var s = 1.70158;
87739		var p = 0;
87740		var a = 1;
87741		if (t === 0) {
87742			return 0;
87743		}
87744		if (t === 1) {
87745			return 1;
87746		}
87747		if (!p) {
87748			p = 0.3;
87749		}
87750		if (a < 1) {
87751			a = 1;
87752			s = p / 4;
87753		} else {
87754			s = p / (2 * Math.PI) * Math.asin(1 / a);
87755		}
87756		return a * Math.pow(2, -10 * t) * Math.sin((t - s) * (2 * Math.PI) / p) + 1;
87757	},
87758
87759	easeInOutElastic: function(t) {
87760		var s = 1.70158;
87761		var p = 0;
87762		var a = 1;
87763		if (t === 0) {
87764			return 0;
87765		}
87766		if ((t /= 0.5) === 2) {
87767			return 1;
87768		}
87769		if (!p) {
87770			p = 0.45;
87771		}
87772		if (a < 1) {
87773			a = 1;
87774			s = p / 4;
87775		} else {
87776			s = p / (2 * Math.PI) * Math.asin(1 / a);
87777		}
87778		if (t < 1) {
87779			return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p));
87780		}
87781		return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p) * 0.5 + 1;
87782	},
87783	easeInBack: function(t) {
87784		var s = 1.70158;
87785		return t * t * ((s + 1) * t - s);
87786	},
87787
87788	easeOutBack: function(t) {
87789		var s = 1.70158;
87790		return (t = t - 1) * t * ((s + 1) * t + s) + 1;
87791	},
87792
87793	easeInOutBack: function(t) {
87794		var s = 1.70158;
87795		if ((t /= 0.5) < 1) {
87796			return 0.5 * (t * t * (((s *= (1.525)) + 1) * t - s));
87797		}
87798		return 0.5 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);
87799	},
87800
87801	easeInBounce: function(t) {
87802		return 1 - effects.easeOutBounce(1 - t);
87803	},
87804
87805	easeOutBounce: function(t) {
87806		if (t < (1 / 2.75)) {
87807			return 7.5625 * t * t;
87808		}
87809		if (t < (2 / 2.75)) {
87810			return 7.5625 * (t -= (1.5 / 2.75)) * t + 0.75;
87811		}
87812		if (t < (2.5 / 2.75)) {
87813			return 7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375;
87814		}
87815		return 7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375;
87816	},
87817
87818	easeInOutBounce: function(t) {
87819		if (t < 0.5) {
87820			return effects.easeInBounce(t * 2) * 0.5;
87821		}
87822		return effects.easeOutBounce(t * 2 - 1) * 0.5 + 0.5;
87823	}
87824};
87825
87826module.exports = {
87827	effects: effects
87828};
87829
87830// DEPRECATIONS
87831
87832/**
87833 * Provided for backward compatibility, use Chart.helpers.easing.effects instead.
87834 * @function Chart.helpers.easingEffects
87835 * @deprecated since version 2.7.0
87836 * @todo remove at version 3
87837 * @private
87838 */
87839helpers.easingEffects = effects;
87840
87841},{"43":43}],45:[function(require,module,exports){
87842'use strict';
87843
87844var helpers = require(43);
87845
87846/**
87847 * @alias Chart.helpers.options
87848 * @namespace
87849 */
87850module.exports = {
87851	/**
87852	 * Converts the given line height `value` in pixels for a specific font `size`.
87853	 * @param {Number|String} value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em').
87854	 * @param {Number} size - The font size (in pixels) used to resolve relative `value`.
87855	 * @returns {Number} The effective line height in pixels (size * 1.2 if value is invalid).
87856	 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
87857	 * @since 2.7.0
87858	 */
87859	toLineHeight: function(value, size) {
87860		var matches = ('' + value).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);
87861		if (!matches || matches[1] === 'normal') {
87862			return size * 1.2;
87863		}
87864
87865		value = +matches[2];
87866
87867		switch (matches[3]) {
87868		case 'px':
87869			return value;
87870		case '%':
87871			value /= 100;
87872			break;
87873		default:
87874			break;
87875		}
87876
87877		return size * value;
87878	},
87879
87880	/**
87881	 * Converts the given value into a padding object with pre-computed width/height.
87882	 * @param {Number|Object} value - If a number, set the value to all TRBL component,
87883	 *  else, if and object, use defined properties and sets undefined ones to 0.
87884	 * @returns {Object} The padding values (top, right, bottom, left, width, height)
87885	 * @since 2.7.0
87886	 */
87887	toPadding: function(value) {
87888		var t, r, b, l;
87889
87890		if (helpers.isObject(value)) {
87891			t = +value.top || 0;
87892			r = +value.right || 0;
87893			b = +value.bottom || 0;
87894			l = +value.left || 0;
87895		} else {
87896			t = r = b = l = +value || 0;
87897		}
87898
87899		return {
87900			top: t,
87901			right: r,
87902			bottom: b,
87903			left: l,
87904			height: t + b,
87905			width: l + r
87906		};
87907	},
87908
87909	/**
87910	 * Evaluates the given `inputs` sequentially and returns the first defined value.
87911	 * @param {Array[]} inputs - An array of values, falling back to the last value.
87912	 * @param {Object} [context] - If defined and the current value is a function, the value
87913	 * is called with `context` as first argument and the result becomes the new input.
87914	 * @param {Number} [index] - If defined and the current value is an array, the value
87915	 * at `index` become the new input.
87916	 * @since 2.7.0
87917	 */
87918	resolve: function(inputs, context, index) {
87919		var i, ilen, value;
87920
87921		for (i = 0, ilen = inputs.length; i < ilen; ++i) {
87922			value = inputs[i];
87923			if (value === undefined) {
87924				continue;
87925			}
87926			if (context !== undefined && typeof value === 'function') {
87927				value = value(context);
87928			}
87929			if (index !== undefined && helpers.isArray(value)) {
87930				value = value[index];
87931			}
87932			if (value !== undefined) {
87933				return value;
87934			}
87935		}
87936	}
87937};
87938
87939},{"43":43}],46:[function(require,module,exports){
87940'use strict';
87941
87942module.exports = require(43);
87943module.exports.easing = require(44);
87944module.exports.canvas = require(42);
87945module.exports.options = require(45);
87946
87947},{"42":42,"43":43,"44":44,"45":45}],47:[function(require,module,exports){
87948/**
87949 * Platform fallback implementation (minimal).
87950 * @see https://github.com/chartjs/Chart.js/pull/4591#issuecomment-319575939
87951 */
87952
87953module.exports = {
87954	acquireContext: function(item) {
87955		if (item && item.canvas) {
87956			// Support for any object associated to a canvas (including a context2d)
87957			item = item.canvas;
87958		}
87959
87960		return item && item.getContext('2d') || null;
87961	}
87962};
87963
87964},{}],48:[function(require,module,exports){
87965/**
87966 * Chart.Platform implementation for targeting a web browser
87967 */
87968
87969'use strict';
87970
87971var helpers = require(46);
87972
87973var EXPANDO_KEY = '$chartjs';
87974var CSS_PREFIX = 'chartjs-';
87975var CSS_RENDER_MONITOR = CSS_PREFIX + 'render-monitor';
87976var CSS_RENDER_ANIMATION = CSS_PREFIX + 'render-animation';
87977var ANIMATION_START_EVENTS = ['animationstart', 'webkitAnimationStart'];
87978
87979/**
87980 * DOM event types -> Chart.js event types.
87981 * Note: only events with different types are mapped.
87982 * @see https://developer.mozilla.org/en-US/docs/Web/Events
87983 */
87984var EVENT_TYPES = {
87985	touchstart: 'mousedown',
87986	touchmove: 'mousemove',
87987	touchend: 'mouseup',
87988	pointerenter: 'mouseenter',
87989	pointerdown: 'mousedown',
87990	pointermove: 'mousemove',
87991	pointerup: 'mouseup',
87992	pointerleave: 'mouseout',
87993	pointerout: 'mouseout'
87994};
87995
87996/**
87997 * The "used" size is the final value of a dimension property after all calculations have
87998 * been performed. This method uses the computed style of `element` but returns undefined
87999 * if the computed style is not expressed in pixels. That can happen in some cases where
88000 * `element` has a size relative to its parent and this last one is not yet displayed,
88001 * for example because of `display: none` on a parent node.
88002 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value
88003 * @returns {Number} Size in pixels or undefined if unknown.
88004 */
88005function readUsedSize(element, property) {
88006	var value = helpers.getStyle(element, property);
88007	var matches = value && value.match(/^(\d+)(\.\d+)?px$/);
88008	return matches ? Number(matches[1]) : undefined;
88009}
88010
88011/**
88012 * Initializes the canvas style and render size without modifying the canvas display size,
88013 * since responsiveness is handled by the controller.resize() method. The config is used
88014 * to determine the aspect ratio to apply in case no explicit height has been specified.
88015 */
88016function initCanvas(canvas, config) {
88017	var style = canvas.style;
88018
88019	// NOTE(SB) canvas.getAttribute('width') !== canvas.width: in the first case it
88020	// returns null or '' if no explicit value has been set to the canvas attribute.
88021	var renderHeight = canvas.getAttribute('height');
88022	var renderWidth = canvas.getAttribute('width');
88023
88024	// Chart.js modifies some canvas values that we want to restore on de
vendor: 4,559 bytes, lines 88024-88198
88024stroy
88025	canvas[EXPANDO_KEY] = {
88026		initial: {
88027			height: renderHeight,
88028			width: renderWidth,
88029			style: {
88030				display: style.display,
88031				height: style.height,
88032				width: style.width
88033			}
88034		}
88035	};
88036
88037	// Force canvas to display as block to avoid extra space caused by inline
88038	// elements, which would interfere with the responsive resize process.
88039	// https://github.com/chartjs/Chart.js/issues/2538
88040	style.display = style.display || 'block';
88041
88042	if (renderWidth === null || renderWidth === '') {
88043		var displayWidth = readUsedSize(canvas, 'width');
88044		if (displayWidth !== undefined) {
88045			canvas.width = displayWidth;
88046		}
88047	}
88048
88049	if (renderHeight === null || renderHeight === '') {
88050		if (canvas.style.height === '') {
88051			// If no explicit render height and style height, let's apply the aspect ratio,
88052			// which one can be specified by the user but also by charts as default option
88053			// (i.e. options.aspectRatio). If not specified, use canvas aspect ratio of 2.
88054			canvas.height = canvas.width / (config.options.aspectRatio || 2);
88055		} else {
88056			var displayHeight = readUsedSize(canvas, 'height');
88057			if (displayWidth !== undefined) {
88058				canvas.height = displayHeight;
88059			}
88060		}
88061	}
88062
88063	return canvas;
88064}
88065
88066/**
88067 * Detects support for options object argument in addEventListener.
88068 * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support
88069 * @private
88070 */
88071var supportsEventListenerOptions = (function() {
88072	var supports = false;
88073	try {
88074		var options = Object.defineProperty({}, 'passive', {
88075			get: function() {
88076				supports = true;
88077			}
88078		});
88079		window.addEventListener('e', null, options);
88080	} catch (e) {
88081		// continue regardless of error
88082	}
88083	return supports;
88084}());
88085
88086// Default passive to true as expected by Chrome for 'touchstart' and 'touchend' events.
88087// https://github.com/chartjs/Chart.js/issues/4287
88088var eventListenerOptions = supportsEventListenerOptions ? {passive: true} : false;
88089
88090function addEventListener(node, type, listener) {
88091	node.addEventListener(type, listener, eventListenerOptions);
88092}
88093
88094function removeEventListener(node, type, listener) {
88095	node.removeEventListener(type, listener, eventListenerOptions);
88096}
88097
88098function createEvent(type, chart, x, y, nativeEvent) {
88099	return {
88100		type: type,
88101		chart: chart,
88102		native: nativeEvent || null,
88103		x: x !== undefined ? x : null,
88104		y: y !== undefined ? y : null,
88105	};
88106}
88107
88108function fromNativeEvent(event, chart) {
88109	var type = EVENT_TYPES[event.type] || event.type;
88110	var pos = helpers.getRelativePosition(event, chart);
88111	return createEvent(type, chart, pos.x, pos.y, event);
88112}
88113
88114function throttled(fn, thisArg) {
88115	var ticking = false;
88116	var args = [];
88117
88118	return function() {
88119		args = Array.prototype.slice.call(arguments);
88120		thisArg = thisArg || this;
88121
88122		if (!ticking) {
88123			ticking = true;
88124			helpers.requestAnimFrame.call(window, function() {
88125				ticking = false;
88126				fn.apply(thisArg, args);
88127			});
88128		}
88129	};
88130}
88131
88132// Implementation based on https://github.com/marcj/css-element-queries
88133function createResizer(handler) {
88134	var resizer = document.createElement('div');
88135	var cls = CSS_PREFIX + 'size-monitor';
88136	var maxSize = 1000000;
88137	var style =
88138		'position:absolute;' +
88139		'left:0;' +
88140		'top:0;' +
88141		'right:0;' +
88142		'bottom:0;' +
88143		'overflow:hidden;' +
88144		'pointer-events:none;' +
88145		'visibility:hidden;' +
88146		'z-index:-1;';
88147
88148	resizer.style.cssText = style;
88149	resizer.className = cls;
88150	resizer.innerHTML =
88151		'<div class="' + cls + '-expand" style="' + style + '">' +
88152			'<div style="' +
88153				'position:absolute;' +
88154				'width:' + maxSize + 'px;' +
88155				'height:' + maxSize + 'px;' +
88156				'left:0;' +
88157				'top:0">' +
88158			'</div>' +
88159		'</div>' +
88160		'<div class="' + cls + '-shrink" style="' + style + '">' +
88161			'<div style="' +
88162				'position:absolute;' +
88163				'width:200%;' +
88164				'height:200%;' +
88165				'left:0; ' +
88166				'top:0">' +
88167			'</div>' +
88168		'</div>';
88169
88170	var expand = resizer.childNodes[0];
88171	var shrink = resizer.childNodes[1];
88172
88173	resizer._reset = function() {
88174		expand.scrollLeft = maxSize;
88175		expand.scrollTop = maxSize;
88176		shrink.scrollLeft = maxSize;
88177		shrink.scrollTop = maxSize;
88178	};
88179	var onScroll = function() {
88180		resizer._reset();
88181		handler();
88182	};
88183
88184	addEventListener(expand, 'scroll', onScroll.bind(expand, 'expand'));
88185	addEventListener(shrink, 'scroll', onScroll.bind(shrink, 'shrink'));
88186
88187	return resizer;
88188}
88189
88190// https://davidwalsh.name/detect-node-insertion
88191function watchForRender(node, handler) {
88192	var expando = node[EXPANDO_KEY] || (node[EXPANDO_KEY] = {});
88193	var proxy = expando.renderProxy = function(e) {
88194		if (e.animationName === CSS_RENDER_ANIMATION) {
88195			handler();
88196		}
88197	};
88198
88199	helpers.each(ANIMATION_START_EVENTS, function(type) {
88200		addEventListener(node, type, proxy);
88201	});
88202
88203	// #4737: Chrome might skip the CSS animation when the CSS_RENDER_MONITOR class
88204	// is removed then added back immediately (same animation frame?). Accessing the
88205	// `offsetParent` property will force a reflow and re-evaluate the CSS animation.
88206	// https://gist.github.com/paulirish/5d52fb081b3570c81e3a#box-metrics
88207	// https://github.com/chartjs/Chart.js/issues/4737
88208	expando.reflow = !!node.offsetParent;
88209
88210	node.classList.add(CSS_RENDER_MONITOR);
88211}
88212
88213function unwatchForRender(node) {
88214	var expando = node[EXPANDO_KEY] || {};
88215	var proxy = expando.renderProxy;
88216
88217	if (proxy) {
88218		helpers.each(ANIMATION_START_EVENTS, function(type) {
88219			removeEventListener(node, type, proxy);
88220		});
88221
88222		delete expando.renderProxy;
88223	}
88224
88225	node.classList.remove(CSS_RENDER_MONITOR);
88226}
88227
88228function addResizeListener(node, listener, chart) {
88229	var expando = node[EXPANDO_KEY] || (node[EXPANDO_KEY] = {});
88230
88231	// Let's keep track of this added resizer and thus avoid DOM query when removing it.
88232	var resizer = expando.resizer = createResizer(throttled(function() {
88233		if (expando.resizer) {
88234			return listener(createEvent('resize', chart));
88235		}
88236	}));
88237
88238	// The resizer needs to be attached to the node parent, so we first need to be
88239	// sure that `node` is attached to the DOM before injecting the resizer element.
88240	watchForRender(node, function() {
88241		if (expando.resizer) {
88242			var container = node.parentNode;
88243			if (container && container !== resizer.parentNode) {
88244				container.insertBefore(resizer, container.firstChild);
88245			}
88246
88247			// The container size might have changed, let's reset the resizer state.
88248			resizer._reset();
88249		}
88250	});
88251}
88252
88253function removeResizeListener(node) {
88254	var expando = node[EXPANDO_KEY] || {};
88255	var resizer = expando.resizer;
88256
88257	delete expando.resizer;
88258	unwatchForRender(node);
88259
88260	if (resizer && resizer.parentNode) {
88261		resizer.parentNode.removeChild(resizer);
88262	}
88263}
88264
88265function injectCSS(platform, css) {
88266	// http://stackoverflow.com/q/3922139
88267	var style = platform._style || document.createElement('style');
88268	if (!platform._style) {
88269		platform._style = style;
88270		css = '/* Chart.js */\n' + css;
88271		style.setAttribute('type', 'text/css');
88272		document.getElementsByTagName('head')[0].appendChild(style);
88273	}
88274
88275	style.appendChild(document.createTextNode(css));
88276}
88277
88278module.exports = {
88279	/**
88280	 * This property holds whether this platform is enabled for the current environment.
88281	 * Currently used by platform.js to select the proper implementation.
88282	 * @private
88283	 */
88284	_enabled: typeof window !== 'undefined' && typeof document !== 'undefined',
88285
88286	initialize: function() {
88287		var keyframes = 'from{opacity:0.99}to{opacity:1}';
88288
88289		injectCSS(this,
88290			// DOM rendering detection
88291			// https://davidwalsh.name/detect-node-insertion
88292			'@-webkit-keyframes ' + CSS_RENDER_ANIMATION + '{' + keyframes + '}' +
88293			'@keyframes ' + CSS_RENDER_ANIMATION + '{' + keyframes + '}' +
88294			'.' + CSS_RENDER_MONITOR + '{' +
88295				'-webkit-animation:' + CSS_RENDER_ANIMATION + ' 0.001s;' +
88296				'animation:' + CSS_RENDER_ANIMATION + ' 0.001s;' +
88297			'}'
88298		);
88299	},
88300
88301	acquireContext: function(item, config) {
88302		if (typeof item === 'string') {
88303			item = document.getElementById(item);
88304		} else if (item.length) {
88305			// Support for array based queries (such as jQuery)
88306			item = item[0];
88307		}
88308
88309		if (item && item.canvas) {
88310			// Support for any object associated to a canvas (including a context2d)
88311			item = item.canvas;
88312		}
88313
88314		// To prevent canvas fingerprinting, some add-ons undefine the getContext
88315		// method, for example: https://github.com/kkapsner/CanvasBlocker
88316		// https://github.com/chartjs/Chart.js/issues/2807
88317		var context = item && item.getContext && item.getContext('2d');
88318
88319		// `instanceof HTMLCanvasElement/CanvasRenderingContext2D` fails when the item is
88320		// inside an iframe or when running in a protected environment. We could guess the
88321		// types from their toString() value but let's keep things flexible and assume it's
88322		// a sufficient condition if the item has a context2D which has item as `canvas`.
88323		// https://github.com/chartjs/Chart.js/issues/3887
88324		// https://github.com/chartjs/Chart.js/issues/4102
88325		// https://github.com/chartjs/Chart.js/issues/4152
88326		if (context && context.canvas === item) {
88327			initCanvas(item, config);
88328			return context;
88329		}
88330
88331		return null;
88332	},
88333
88334	releaseContext: function(context) {
88335		var canvas = context.canvas;
88336		if (!canvas[EXPANDO_KEY]) {
88337			return;
88338		}
88339
88340		var initial = canvas[EXPANDO_KEY].initial;
88341		['height', 'width'].forEach(function(prop) {
88342			var value = initial[prop];
88343			if (helpers.isNullOrUndef(value)) {
88344				canvas.removeAttribute(prop);
88345			} else {
88346				canvas.setAttribute(prop, value);
88347			}
88348		});
88349
88350		helpers.each(initial.style || {}, function(value, key) {
88351			canvas.style[key] = value;
88352		});
88353
88354		// The canvas render size might have been changed (and thus the state stack discarded),
88355		// we can't use save() and restore() to restore the initial state. So make sure that at
88356		// least the canvas context is reset to the default state by setting the canvas width.
88357		// https://www.w3.org/TR/2011/WD-html5-20110525/the-canvas-element.html
88358		canvas.width = canvas.width;
88359
88360		delete canvas[EXPANDO_KEY];
88361	},
88362
88363	addEventListener: function(chart, type, listener) {
88364		var canvas = chart.canvas;
88365		if (type === 'resize') {
88366			// Note: the resize event is not supported on all browsers.
88367			addResizeListener(canvas, listener, chart);
88368			return;
88369		}
88370
88371		var expando = listener[EXPANDO_KEY] || (listener[EXPANDO_KEY] = {});
88372		var proxies = expando.proxies || (expando.proxies = {});
88373		var proxy = proxies[chart.id + '_' + type] = function(event) {
88374			listener(fromNativeEvent(event, chart));
88375		};
88376
88377		addEventListener(canvas, type, proxy);
88378	},
88379
88380	removeEventListener: function(chart, type, listener) {
88381		var canvas = chart.canvas;
88382		if (type === 'resize') {
88383			// Note: the resize event is not supported on all browsers.
88384			removeResizeListener(canvas, listener);
88385			return;
88386		}
88387
88388		var expando = listener[EXPANDO_KEY] || {};
88389		var proxies = expando.proxies || {};
88390		var proxy = proxies[chart.id + '_' + type];
88391		if (!proxy) {
88392			return;
88393		}
88394
88395		removeEventListener(canvas, type, proxy);
88396	}
88397};
88398
88399// DEPRECATIONS
88400
88401/**
88402 * Provided for backward compatibility, use EventTarget.addEventListener instead.
88403 * EventTarget.addEventListener compatibility: Chrome, Opera 7, Safari, FF1.5+, IE9+
88404 * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
88405 * @function Chart.helpers.addEvent
88406 * @deprecated since version 2.7.0
88407 * @todo remove at version 3
88408 * @private
88409 */
88410helpers.addEvent = addEventListener;
88411
88412/**
88413 * Provided for backward compatibility, use EventTarget.removeEventListener instead.
88414 * EventTarget.removeEventListener compatibility: Chrome, Opera 7, Safari, FF1.5+, IE9+
88415 * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
88416 * @function Chart.helpers.removeEvent
88417 * @deprecated since version 2.7.0
88418 * @todo remove at version 3
88419 * @private
88420 */
88421helpers.removeEvent = removeEventListener;
88422
88423},{"46":46}],49:[function(require,module,exports){
88424'use strict';
88425
88426var helpers = require(46);
88427var basic = require(47);
88428var dom = require(48);
88429
88430// @TODO Make possible to select another platform at build time.
88431var implementation = dom._enabled ? dom : basic;
88432
88433/**
88434 * @namespace Chart.platform
88435 * @see https://chartjs.gitbooks.io/proposals/content/Platform.html
88436 * @since 2.4.0
88437 */
88438module.exports = helpers.extend({
88439	/**
88440	 * @since 2.7.0
88441	 */
88442	initialize: function() {},
88443
88444	/**
88445	 * Called at chart construction time, returns a context2d instance implementing
88446	 * the [W3C Canvas 2D Context API standard]{@link https://www.w3.org/TR/2dcontext/}.
88447	 * @param {*} item - The native item from which to acquire context (platform specific)
88448	 * @param {Object} options - The chart options
88449	 * @returns {CanvasRenderingContext2D} context2d instance
88450	 */
88451	acquireContext: function() {},
88452
88453	/**
88454	 * Called at chart destruction time, releases any resources associated to the context
88455	 * previously returned by the acquireContext() method.
88456	 * @param {CanvasRenderingContext2D} context - The context2d instance
88457	 * @returns {Boolean} true if the method succeeded, else false
88458	 */
88459	releaseContext: function() {},
88460
88461	/**
88462	 * Registers the specified listener on the given chart.
88463	 * @param {Chart} chart - Chart from which to listen for event
88464	 * @param {String} type - The ({@link IEvent}) type to listen for
88465	 * @param {Function} listener - Receives a notification (an object that implements
88466	 * the {@link IEvent} interface) when an event of the specified type occurs.
88467	 */
88468	addEventListener: function() {},
88469
88470	/**
88471	 * Removes the specified listener previously registered with addEventListener.
88472	 * @param {Chart} chart -Chart from which to remove the listener
88473	 * @param {String} type - The ({@link IEvent}) type to remove
88474	 * @param {Function} listener - The listener function to remove from the event target.
88475	 */
88476	removeEventListener: function() {}
88477
88478}, implementation);
88479
88480/**
88481 * @interface IPlatform
88482 * Allows abstracting platform dependencies away from the chart
88483 * @borrows Chart.platform.acquireContext as acquireContext
88484 * @borrows Chart.platform.releaseContext as releaseContext
88485 * @borrows Chart.platform.addEventListener as addEventListener
88486 * @borrows Chart.platform.removeEventListener as removeEventListener
88487 */
88488
88489/**
88490 * @interface IEvent
88491 * @prop {String} type - The event type name, possible values are:
88492 * 'contextmenu', 'mouseenter', 'mousedown', 'mousemove', 'mouseup', 'mouseout',
88493 * 'click', 'dblclick', 'keydown', 'keypress', 'keyup' and 'resize'
88494 * @prop {*} native - The original native event (null for emulated events, e.g. 'resize')
88495 * @prop {Number} x - The mouse x position, relative to the canvas (null for incompatible events)
88496 * @prop {Number} y - The mouse y position, relative to the canvas (null for incompatible events)
88497 */
88498
88499},{"46":46,"47":47,"48":48}],50:[function(require,module,exports){
88500'use strict';
88501
88502module.exports = {};
88503module.exports.filler = require(51);
88504module.exports.legend = require(52);
88505module.exports.title = require(53);
88506
88507},{"51":51,"52":52,"53":53}],51:[function(require,module,exports){
88508/**
88509 * Plugin based on discussion from the following Chart.js issues:
88510 * @see https://github.com/chartjs/Chart.js/issues/2380#issuecomment-279961569
88511 * @see https://github.com/chartjs/Chart.js/issues/2440#issuecomment-256461897
88512 */
88513
88514'use strict';
88515
88516var defaults = require(26);
88517var elements = require(41);
88518var helpers = require(46);
88519
88520defaults._set('global', {
88521	plugins: {
88522		filler: {
88523			propagate: true
88524		}
88525	}
88526});
88527
88528var mappers = {
88529	dataset: function(source) {
88530		var index = source.fill;
88531		var chart = source.chart;
88532		var meta = chart.getDatasetMeta(index);
88533		var visible = meta && chart.isDatasetVisible(index);
88534		var points = (visible && meta.dataset._children) || [];
88535		var length = points.length || 0;
88536
88537		return !length ? null : function(point, i) {
88538			return (i < length && points[i]._view) || null;
88539		};
88540	},
88541
88542	boundary: function(source) {
88543		var boundary = source.boundary;
88544		var x = boundary ? boundary.x : null;
88545		var y = boundary ? boundary.y : null;
88546
88547		return function(point) {
88548			return {
88549				x: x === null ? point.x : x,
88550				y: y === null ? point.y : y,
88551			};
88552		};
88553	}
88554};
88555
88556// @todo if (fill[0] === '#')
88557function decodeFill(el, index, count) {
88558	var model = el._model || {};
88559	var fill = model.fill;
88560	var target;
88561
88562	if (fill === undefined) {
88563		fill = !!model.backgroundColor;
88564	}
88565
88566	if (fill === false || fill === null) {
88567		return false;
88568	}
88569
88570	if (fill === true) {
88571		return 'origin';
88572	}
88573
88574	target = parseFloat(fill, 10);
88575	if (isFinite(target) && Math.floor(target) === target) {
88576		if (fill[0] === '-' || fill[0] === '+') {
88577			target = index + target;
88578		}
88579
88580		if (target === index || target < 0 || target >= count) {
88581			return false;
88582		}
88583
88584		return target;
88585	}
88586
88587	switch (fill) {
88588	// compatibility
88589	case 'bottom':
88590		return 'start';
88591	case 'top':
88592		return 'end';
88593	case 'zero':
88594		return 'origin';
88595	// supported boundaries
88596	case 'origin':
88597	case 'start':
88598	case 'end':
88599		return fill;
88600	// invalid fill values
88601	default:
88602		return false;
88603	}
88604}
88605
88606function computeBoundary(source) {
88607	var model = source.el._model || {};
88608	var scale = source.el._scale || {};
88609	var fill = source.fill;
88610	var target = null;
88611	var horizontal;
88612
88613	if (isFinite(fill)) {
88614		return null;
88615	}
88616
88617	// Backward compatibility: until v3, we still need to support boundary values set on
88618	// the model (scaleTop, scaleBottom and scaleZero) because some external plugins and
88619	// controllers might still use it (e.g. the Smith chart).
88620
88621	if (fill === 'start') {
88622		target = model.scaleBottom === undefined ? scale.bottom : model.scaleBottom;
88623	} else if (fill === 'end') {
88624		target = model.scaleTop === undefined ? scale.top : model.scaleTop;
88625	} else if (model.scaleZero !== undefined) {
88626		target = model.scaleZero;
88627	} else if (scale.getBasePosition) {
88628		target = scale.getBasePosition();
88629	} else if (scale.getBasePixel) {
88630		target = scale.getBasePixel();
88631	}
88632
88633	if (target !== undefined && target !== null) {
88634		if (target.x !== undefined && target.y !== undefined) {
88635			return target;
88636		}
88637
88638		if (typeof target === 'number' && isFinite(target)) {
88639			horizontal = scale.isHorizontal();
88640			return {
88641				x: horizontal ? target : null,
88642				y: horizontal ? null : target
88643			};
88644		}
88645	}
88646
88647	return null;
88648}
88649
88650function resolveTarget(sources, index, propagate) {
88651	var source = sources[index];
88652	var fill = source.fill;
88653	var visited = [index];
88654	var target;
88655
88656	if (!propagate) {
88657		return fill;
88658	}
88659
88660	while (fill !== false && visited.indexOf(fill) === -1) {
88661		if (!isFinite(fill)) {
88662			return fill;
88663		}
88664
88665		target = sources[fill];
88666		if (!target) {
88667			return false;
vendor: 4,184 bytes, lines 88668-88873
88668		}
88669
88670		if (target.visible) {
88671			return fill;
88672		}
88673
88674		visited.push(fill);
88675		fill = target.fill;
88676	}
88677
88678	return false;
88679}
88680
88681function createMapper(source) {
88682	var fill = source.fill;
88683	var type = 'dataset';
88684
88685	if (fill === false) {
88686		return null;
88687	}
88688
88689	if (!isFinite(fill)) {
88690		type = 'boundary';
88691	}
88692
88693	return mappers[type](source);
88694}
88695
88696function isDrawable(point) {
88697	return point && !point.skip;
88698}
88699
88700function drawArea(ctx, curve0, curve1, len0, len1) {
88701	var i;
88702
88703	if (!len0 || !len1) {
88704		return;
88705	}
88706
88707	// building first area curve (normal)
88708	ctx.moveTo(curve0[0].x, curve0[0].y);
88709	for (i = 1; i < len0; ++i) {
88710		helpers.canvas.lineTo(ctx, curve0[i - 1], curve0[i]);
88711	}
88712
88713	// joining the two area curves
88714	ctx.lineTo(curve1[len1 - 1].x, curve1[len1 - 1].y);
88715
88716	// building opposite area curve (reverse)
88717	for (i = len1 - 1; i > 0; --i) {
88718		helpers.canvas.lineTo(ctx, curve1[i], curve1[i - 1], true);
88719	}
88720}
88721
88722function doFill(ctx, points, mapper, view, color, loop) {
88723	var count = points.length;
88724	var span = view.spanGaps;
88725	var curve0 = [];
88726	var curve1 = [];
88727	var len0 = 0;
88728	var len1 = 0;
88729	var i, ilen, index, p0, p1, d0, d1;
88730
88731	ctx.beginPath();
88732
88733	for (i = 0, ilen = (count + !!loop); i < ilen; ++i) {
88734		index = i % count;
88735		p0 = points[index]._view;
88736		p1 = mapper(p0, index, view);
88737		d0 = isDrawable(p0);
88738		d1 = isDrawable(p1);
88739
88740		if (d0 && d1) {
88741			len0 = curve0.push(p0);
88742			len1 = curve1.push(p1);
88743		} else if (len0 && len1) {
88744			if (!span) {
88745				drawArea(ctx, curve0, curve1, len0, len1);
88746				len0 = len1 = 0;
88747				curve0 = [];
88748				curve1 = [];
88749			} else {
88750				if (d0) {
88751					curve0.push(p0);
88752				}
88753				if (d1) {
88754					curve1.push(p1);
88755				}
88756			}
88757		}
88758	}
88759
88760	drawArea(ctx, curve0, curve1, len0, len1);
88761
88762	ctx.closePath();
88763	ctx.fillStyle = color;
88764	ctx.fill();
88765}
88766
88767module.exports = {
88768	id: 'filler',
88769
88770	afterDatasetsUpdate: function(chart, options) {
88771		var count = (chart.data.datasets || []).length;
88772		var propagate = options.propagate;
88773		var sources = [];
88774		var meta, i, el, source;
88775
88776		for (i = 0; i < count; ++i) {
88777			meta = chart.getDatasetMeta(i);
88778			el = meta.dataset;
88779			source = null;
88780
88781			if (el && el._model && el instanceof elements.Line) {
88782				source = {
88783					visible: chart.isDatasetVisible(i),
88784					fill: decodeFill(el, i, count),
88785					chart: chart,
88786					el: el
88787				};
88788			}
88789
88790			meta.$filler = source;
88791			sources.push(source);
88792		}
88793
88794		for (i = 0; i < count; ++i) {
88795			source = sources[i];
88796			if (!source) {
88797				continue;
88798			}
88799
88800			source.fill = resolveTarget(sources, i, propagate);
88801			source.boundary = computeBoundary(source);
88802			source.mapper = createMapper(source);
88803		}
88804	},
88805
88806	beforeDatasetDraw: function(chart, args) {
88807		var meta = args.meta.$filler;
88808		if (!meta) {
88809			return;
88810		}
88811
88812		var ctx = chart.ctx;
88813		var el = meta.el;
88814		var view = el._view;
88815		var points = el._children || [];
88816		var mapper = meta.mapper;
88817		var color = view.backgroundColor || defaults.global.defaultColor;
88818
88819		if (mapper && color && points.length) {
88820			helpers.canvas.clipArea(ctx, chart.chartArea);
88821			doFill(ctx, points, mapper, view, color, el._loop);
88822			helpers.canvas.unclipArea(ctx);
88823		}
88824	}
88825};
88826
88827},{"26":26,"41":41,"46":46}],52:[function(require,module,exports){
88828'use strict';
88829
88830var defaults = require(26);
88831var Element = require(27);
88832var helpers = require(46);
88833var layouts = require(31);
88834
88835var noop = helpers.noop;
88836
88837defaults._set('global', {
88838	legend: {
88839		display: true,
88840		position: 'top',
88841		fullWidth: true,
88842		reverse: false,
88843		weight: 1000,
88844
88845		// a callback that will handle
88846		onClick: function(e, legendItem) {
88847			var index = legendItem.datasetIndex;
88848			var ci = this.chart;
88849			var meta = ci.getDatasetMeta(index);
88850
88851			// See controller.isDatasetVisible comment
88852			meta.hidden = meta.hidden === null ? !ci.data.datasets[index].hidden : null;
88853
88854			// We hid a dataset ... rerender the chart
88855			ci.update();
88856		},
88857
88858		onHover: null,
88859
88860		labels: {
88861			boxWidth: 40,
88862			padding: 10,
88863			// Generates labels shown in the legend
88864			// Valid properties to return:
88865			// text : text to display
88866			// fillStyle : fill of coloured box
88867			// strokeStyle: stroke of coloured box
88868			// hidden : if this legend item refers to a hidden item
88869			// lineCap : cap style for line
88870			// lineDash
88871			// lineDashOffset :
88872			// lineJoin :
88873			// lineWidth :
88874			generateLabels: function(chart) {
88875				var data = chart.data;
88876				return helpers.isArray(data.datasets) ? data.datasets.map(function(dataset, i) {
88877					return {
88878						text: dataset.label,
88879						fillStyle: (!helpers.isArray(dataset.backgroundColor) ? dataset.backgroundColor : dataset.backgroundColor[0]),
88880						hidden: !chart.isDatasetVisible(i),
88881						lineCap: dataset.borderCapStyle,
88882						lineDash: dataset.borderDash,
88883						lineDashOffset: dataset.borderDashOffset,
88884						lineJoin: dataset.borderJoinStyle,
88885						lineWidth: dataset.borderWidth,
88886						strokeStyle: dataset.borderColor,
88887						pointStyle: dataset.pointStyle,
88888
88889						// Below is extra data used for toggling the datasets
88890						datasetIndex: i
88891					};
88892				}, this) : [];
88893			}
88894		}
88895	},
88896
88897	legendCallback: function(chart) {
88898		var text = [];
88899		text.push('<ul class="' + chart.id + '-legend">');
88900		for (var i = 0; i < chart.data.datasets.length; i++) {
88901			text.push('<li><span style="background-color:' + chart.data.datasets[i].backgroundColor + '"></span>');
88902			if (chart.data.datasets[i].label) {
88903				text.push(chart.data.datasets[i].label);
88904			}
88905			text.push('</li>');
88906		}
88907		text.push('</ul>');
88908		return text.join('');
88909	}
88910});
88911
88912/**
88913 * Helper function to get the box width based on the usePointStyle option
88914 * @param labelopts {Object} the label options on the legend
88915 * @param fontSize {Number} the label font size
88916 * @return {Number} width of the color box area
88917 */
88918function getBoxWidth(labelOpts, fontSize) {
88919	return labelOpts.usePointStyle ?
88920		fontSize * Math.SQRT2 :
88921		labelOpts.boxWidth;
88922}
88923
88924/**
88925 * IMPORTANT: this class is exposed publicly as Chart.Legend, backward compatibility required!
88926 */
88927var Legend = Element.extend({
88928
88929	initialize: function(config) {
88930		helpers.extend(this, config);
88931
88932		// Contains hit boxes for each dataset (in dataset order)
88933		this.legendHitBoxes = [];
88934
88935		// Are we in doughnut mode which has a different data type
88936		this.doughnutMode = false;
88937	},
88938
88939	// These methods are ordered by lifecycle. Utilities then follow.
88940	// Any function defined here is inherited by all legend types.
88941	// Any function can be extended by the legend type
88942
88943	beforeUpdate: noop,
88944	update: function(maxWidth, maxHeight, margins) {
88945		var me = this;
88946
88947		// Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
88948		me.beforeUpdate();
88949
88950		// Absorb the master measurements
88951		me.maxWidth = maxWidth;
88952		me.maxHeight = maxHeight;
88953		me.margins = margins;
88954
88955		// Dimensions
88956		me.beforeSetDimensions();
88957		me.setDimensions();
88958		me.afterSetDimensions();
88959		// Labels
88960		me.beforeBuildLabels();
88961		me.buildLabels();
88962		me.afterBuildLabels();
88963
88964		// Fit
88965		me.beforeFit();
88966		me.fit();
88967		me.afterFit();
88968		//
88969		me.afterUpdate();
88970
88971		return me.minSize;
88972	},
88973	afterUpdate: noop,
88974
88975	//
88976
88977	beforeSetDimensions: noop,
88978	setDimensions: function() {
88979		var me = this;
88980		// Set the unconstrained dimension before label rotation
88981		if (me.isHorizontal()) {
88982			// Reset position before calculating rotation
88983			me.width = me.maxWidth;
88984			me.left = 0;
88985			me.right = me.width;
88986		} else {
88987			me.height = me.maxHeight;
88988
88989			// Reset position before calculating rotation
88990			me.top = 0;
88991			me.bottom = me.height;
88992		}
88993
88994		// Reset padding
88995		me.paddingLeft = 0;
88996		me.paddingTop = 0;
88997		me.paddingRight = 0;
88998		me.paddingBottom = 0;
88999
89000		// Reset minSize
89001		me.minSize = {
89002			width: 0,
89003			height: 0
89004		};
89005	},
89006	afterSetDimensions: noop,
89007
89008	//
89009
89010	beforeBuildLabels: noop,
89011	buildLabels: function() {
89012		var me = this;
89013		var labelOpts = me.options.labels || {};
89014		var legendItems = helpers.callback(labelOpts.generateLabels, [me.chart], me) || [];
89015
89016		if (labelOpts.filter) {
89017			legendItems = legendItems.filter(function(item) {
89018				return labelOpts.filter(item, me.chart.data);
89019			});
89020		}
89021
89022		if (me.options.reverse) {
89023			legendItems.reverse();
89024		}
89025
89026		me.legendItems = legendItems;
89027	},
89028	afterBuildLabels: noop,
89029
89030	//
89031
89032	beforeFit: noop,
89033	fit: function() {
89034		var me = this;
89035		var opts = me.options;
89036		var labelOpts = opts.labels;
89037		var display = opts.display;
89038
89039		var ctx = me.ctx;
89040
89041		var globalDefault = defaults.global;
89042		var valueOrDefault = helpers.valueOrDefault;
89043		var fontSize = valueOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize);
89044		var fontStyle = valueOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle);
89045		var fontFamily = valueOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily);
89046		var labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
89047
89048		// Reset hit boxes
89049		var hitboxes = me.legendHitBoxes = [];
89050
89051		var minSize = me.minSize;
89052		var isHorizontal = me.isHorizontal();
89053
89054		if (isHorizontal) {
89055			minSize.width = me.maxWidth; // fill all the width
89056			minSize.height = display ? 10 : 0;
89057		} else {
89058			minSize.width = display ? 10 : 0;
89059			minSize.height = me.maxHeight; // fill all the height
89060		}
89061
89062		// Increase sizes here
89063		if (display) {
89064			ctx.font = labelFont;
89065
89066			if (isHorizontal) {
89067				// Labels
89068
89069				// Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one
89070				var lineWidths = me.lineWidths = [0];
89071				var totalHeight = me.legendItems.length ? fontSize + (labelOpts.padding) : 0;
89072
89073				ctx.textAlign = 'left';
89074				ctx.textBaseline = 'top';
89075
89076				helpers.each(me.legendItems, function(legendItem, i) {
89077					var boxWidth = getBoxWidth(labelOpts, fontSize);
89078					var width = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
89079
89080					if (lineWidths[lineWidths.length - 1] + width + labelOpts.padding >= me.width) {
89081						totalHeight += fontSize + (labelOpts.padding);
89082						lineWidths[lineWidths.length] = me.left;
89083					}
89084
89085					// Store the hitbox width and height here. Final position will be updated in `draw`
89086					hitboxes[i] = {
89087						left: 0,
89088						top: 0,
89089						width: width,
89090						height: fontSize
89091					};
89092
89093					lineWidths[lineWidths.length - 1] += width + labelOpts.padding;
89094				});
89095
89096				minSize.height += totalHeight;
89097
89098			} else {
89099				var vPadding = labelOpts.padding;
89100				var columnWidths = me.columnWidths = [];
89101				var totalWidth = labelOpts.padding;
89102				var currentColWidth = 0;
89103				var currentColHeight = 0;
89104				var itemHeight = fontSize + vPadding;
89105
89106				helpers.each(me.legendItems, function(legendItem, i) {
89107					var boxWidth = getBoxWidth(labelOpts, fontSize);
89108					var itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
89109
89110					// If too tall, go to new column
89111					if (currentColHeight + itemHeight > minSize.height) {
89112						totalWidth += currentColWidth + labelOpts.padding;
89113						columnWidths.push(currentColWidth); // previous column width
89114
89115						currentColWidth = 0;
89116						currentColHeight = 0;
89117					}
89118
89119					// Get max width
89120					currentColWidth = Math.max(currentColWidth, itemWidth);
89121					currentColHeight += itemHeight;
89122
89123					// Store the hitbox width and height here. Final position will be updated in `draw`
89124					hitboxes[i] = {
89125						left: 0,
89126						top: 0,
89127						width: itemWidth,
89128						height: fontSize
89129					};
89130				});
89131
89132				totalWidth += currentColWidth;
89133				columnWidths.push(currentColWidth);
89134				minSize.width += totalWidth;
89135			}
89136		}
89137
89138		me.width = minSize.width;
89139		me.height = minSize.height;
89140	},
89141	afterFit: noop,
89142
89143	// Shared Methods
89144	isHorizontal: function() {
89145		return this.options.position === 'top' || this.options.position === 'bottom';
89146	},
89147
89148	// Actually draw the legend on the canvas
89149	draw: function() {
89150		var me = this;
89151		var opts = me.options;
89152		var labelOpts = opts.labels;
89153		var globalDefault = defaults.global;
89154		var lineDefault = globalDefault.elements.line;
89155		var legendWidth = me.width;
89156		var lineWidths = me.lineWidths;
89157
89158		if (opts.display) {
89159			var ctx = me.ctx;
89160			var valueOrDefault = helpers.valueOrDefault;
89161			var fontColor = valueOrDefault(labelOpts.fontColor, globalDefault.defaultFontColor);
89162			var fontSize = valueOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize);
89163			var fontStyle = valueOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle);
89164			var fontFamily = valueOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily);
89165			var labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
89166			var cursor;
89167
89168			// Canvas setup
89169			ctx.textAlign = 'left';
89170			ctx.textBaseline = 'middle';
89171			ctx.lineWidth = 0.5;
89172			ctx.strokeStyle = fontColor; // for strikethrough effect
89173			ctx.fillStyle = fontColor; // render in correct colour
89174			ctx.font = labelFont;
89175
89176			var boxWidth = getBoxWidth(labelOpts, fontSize);
89177			var hitboxes = me.legendHitBoxes;
89178
89179			// current position
89180			var drawLegendBox = function(x, y, legendItem) {
89181				if (isNaN(boxWidth) || boxWidth <= 0) {
89182					return;
89183				}
89184
89185				// Set the ctx for the box
89186				ctx.save();
89187
89188				ctx.fillStyle = valueOrDefault(legendItem.fillStyle, globalDefault.defaultColor);
89189				ctx.lineCap = valueOrDefault(legendItem.lineCap, lineDefault.borderCapStyle);
89190				ctx.lineDashOffset = valueOrDefault(legendItem.lineDashOffset, lineDefault.borderDashOffset);
89191				ctx.lineJoin = valueOrDefault(legendItem.lineJoin, lineDefault.borderJoinStyle);
89192				ctx.lineWidth = valueOrDefault(legendItem.lineWidth, lineDefault.borderWidth);
89193				ctx.strokeStyle = valueOrDefault(legendItem.strokeStyle, globalDefault.defaultColor);
89194				var isLineWidthZero = (valueOrDefault(legendItem.lineWidth, lineDefault.borderWidth) === 0);
89195
89196				if (ctx.setLineDash) {
89197					// IE 9 and 10 do not support line dash
89198					ctx.setLineDash(valueOrDefault(legendItem.lineDash, lineDefault.borderDash));
89199				}
89200
89201				if (opts.labels && opts.labels.usePointStyle) {
89202					// Recalculate x and y for drawPoint() because its expecting
89203					// x and y to be center of figure (instead of top left)
89204					var radius = fontSize * Math.SQRT2 / 2;
89205					var offSet = radius / Math.SQRT2;
89206					var centerX = x + offSet;
89207					var centerY = y + offSet;
89208
89209					// Draw pointStyle as legend symbol
89210					helpers.canvas.drawPoint(ctx, legendItem.pointStyle, radius, centerX, centerY);
89211				} else {
89212					// Draw box as legend symbol
89213					if (!isLineWidthZero) {
89214						ctx.strokeRect(x, y, boxWidth, fontSize);
89215					}
89216					ctx.fillRect(x, y, boxWidth, fontSize);
89217				}
89218
89219				ctx.restore();
89220			};
89221			var fillText = function(x, y, legendItem, textWidth) {
89222				var halfFontSize = fontSize / 2;
89223				var xLeft = boxWidth + halfFontSize + x;
89224				var yMiddle = y + halfFontSize;
89225
89226				ctx.fillText(legendItem.text, xLeft, yMiddle);
89227
89228				if (legendItem.hidden) {
89229					// Strikethrough the text if hidden
89230					ctx.beginPath();
89231					ctx.lineWidth = 2;
89232					ctx.moveTo(xLeft, yMiddle);
89233					ctx.lineTo(xLeft + textWidth, yMiddle);
89234					ctx.stroke();
89235				}
89236			};
89237
89238			// Horizontal
89239			var isHorizontal = me.isHorizontal();
89240			if (isHorizontal) {
89241				cursor = {
89242					x: me.left + ((legendWidth - lineWidths[0]) / 2),
89243					y: me.top + labelOpts.padding,
89244					line: 0
89245				};
89246			} else {
89247				cursor = {
89248					x: me.left + labelOpts.padding,
89249					y: me.top + labelOpts.padding,
89250					line: 0
89251				};
89252			}
89253
89254			var itemHeight = fontSize + labelOpts.padding;
89255			helpers.each(me.legendItems, function(legendItem, i) {
89256				var textWidth = ctx.measureText(legendItem.text).width;
89257				var width = boxWidth + (fontSize / 2) + textWidth;
89258				var x = cursor.x;
89259				var y = cursor.y;
89260
89261				if (isHorizontal) {
89262					if (x + width >= legendWidth) {
89263						y = cursor.y += itemHeight;
89264						cursor.line++;
89265						x = cursor.x = me.left + ((legendWidth - lineWidths[cursor.line]) / 2);
89266					}
89267				} else if (y + itemHeight > me.bottom) {
89268					x = cursor.x = x + me.columnWidths[cursor.line] + labelOpts.padding;
89269					y = cursor.y = me.top + labelOpts.padding;
89270					cursor.line++;
89271				}
89272
89273				drawLegendBox(x, y, legendItem);
89274
89275				hitboxes[i].left = x;
89276				hitboxes[i].top = y;
89277
89278				// Fill the actual label
89279				fillText(x, y, legendItem, textWidth);
89280
89281				if (isHorizontal) {
89282					cursor.x += width + (labelOpts.padding);
89283				} else {
89284					cursor.y += itemHeight;
89285				}
89286
89287			});
89288		}
89289	},
89290
89291	/**
89292	 * Handle an event
89293	 * @private
89294	 * @param {IEvent} event - The event to handle
89295	 * @return {Boolean} true if a change occured
89296	 */
89297	handleEvent: function(e) {
89298		var me = this;
89299		var opts = me.options;
89300		var type = e.type === 'mouseup' ? 'click' : e.type;
89301		var changed = false;
89302
89303		if (type === 'mousemove') {
89304			if (!opts.onHover) {
89305				return;
89306			}
89307		} else if (type === 'click') {
89308			if (!opts.onClick) {
89309				return;
89310			}
89311		} else {
89312			return;
89313		}
89314
89315		// Chart event already has relative position in it
89316		var x = e.x;
89317		var y = e.y;
89318
89319		if (x >= me.left && x <= me.right && y >= me.top && y <= me.bottom) {
89320			// See if we are touching one of the dataset boxes
89321			var lh = me.legendHitBoxes;
89322			for (var i = 0; i < lh.length; ++i) {
89323				var hitBox = lh[i];
89324
89325				if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) {
89326					// Touching an element
89327					if (type === 'click') {
89328						// use e.native for backwards compatibility
89329						opts.onClick.call(me, e.native, me.legendItems[i]);
89330						changed = true;
89331						break;
89332					} else if (type === 'mousemove') {
89333						// use e.native for backwards compatibility
89334						opts.onHover.call(me, e.native, me.legendItems[i]);
89335						changed = true;
89336						break;
89337					}
89338				}
89339			}
89340		}
89341
89342		return changed;
89343	}
89344});
89345
89346function createNewLegendAndAttach(chart, legendOpts) {
89347	var legend = new Legend({
89348		ctx: chart.ctx,
89349		options: legendOpts,
89350		chart: chart
89351	});
89352
89353	layouts.configure(chart, legend, legendOpts);
89354	layouts.addBox(chart, legend);
89355	chart.legend = legend;
89356}
89357
89358module.exports = {
89359	id: 'legend',
89360
89361	/**
89362	 * Backward compatibility: since 2.1.5, the legend is registered as a plugin, making
89363	 * Chart.Legend obsolete. To avoid a breaking change, we export the Legend as part of
89364	 * the plugin, which one will be re-exposed in the chart.js file.
89365	 * https://github.com/chartjs/Chart.js/pull/2640
89366	 * @private
89367	 */
89368	_element: Legend,
89369
89370	beforeInit: function(chart) {
89371		var legendOpts = chart.options.legend;
89372
89373		if (legendOpts) {
89374			createNewLegendAndAttach(chart, legendOpts);
89375		}
89376	},
89377
89378	beforeUpdate: function(chart) {
89379		var legendOpts = chart.options.legend;
89380		var legend = chart.legend;
89381
89382		if (legendOpts) {
89383			helpers.mergeIf(legendOpts, defaults.global.legend);
89384
89385			if (legend) {
89386				layouts.configure(chart, legend, legendOpts);
89387				legend.options = legendOpts;
89388			} else {
89389				createNewLegendAndAttach(chart, legendOpts);
89390			}
89391		} else if (legend) {
89392			layouts.removeBox(chart, legend);
89393			delete chart.legend;
89394		}
89395	},
89396
vendor: 4,952 bytes, lines 89397-89601
89397	afterEvent: function(chart, e) {
89398		var legend = chart.legend;
89399		if (legend) {
89400			legend.handleEvent(e);
89401		}
89402	}
89403};
89404
89405},{"26":26,"27":27,"31":31,"46":46}],53:[function(require,module,exports){
89406'use strict';
89407
89408var defaults = require(26);
89409var Element = require(27);
89410var helpers = require(46);
89411var layouts = require(31);
89412
89413var noop = helpers.noop;
89414
89415defaults._set('global', {
89416	title: {
89417		display: false,
89418		fontStyle: 'bold',
89419		fullWidth: true,
89420		lineHeight: 1.2,
89421		padding: 10,
89422		position: 'top',
89423		text: '',
89424		weight: 2000         // by default greater than legend (1000) to be above
89425	}
89426});
89427
89428/**
89429 * IMPORTANT: this class is exposed publicly as Chart.Legend, backward compatibility required!
89430 */
89431var Title = Element.extend({
89432	initialize: function(config) {
89433		var me = this;
89434		helpers.extend(me, config);
89435
89436		// Contains hit boxes for each dataset (in dataset order)
89437		me.legendHitBoxes = [];
89438	},
89439
89440	// These methods are ordered by lifecycle. Utilities then follow.
89441
89442	beforeUpdate: noop,
89443	update: function(maxWidth, maxHeight, margins) {
89444		var me = this;
89445
89446		// Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
89447		me.beforeUpdate();
89448
89449		// Absorb the master measurements
89450		me.maxWidth = maxWidth;
89451		me.maxHeight = maxHeight;
89452		me.margins = margins;
89453
89454		// Dimensions
89455		me.beforeSetDimensions();
89456		me.setDimensions();
89457		me.afterSetDimensions();
89458		// Labels
89459		me.beforeBuildLabels();
89460		me.buildLabels();
89461		me.afterBuildLabels();
89462
89463		// Fit
89464		me.beforeFit();
89465		me.fit();
89466		me.afterFit();
89467		//
89468		me.afterUpdate();
89469
89470		return me.minSize;
89471
89472	},
89473	afterUpdate: noop,
89474
89475	//
89476
89477	beforeSetDimensions: noop,
89478	setDimensions: function() {
89479		var me = this;
89480		// Set the unconstrained dimension before label rotation
89481		if (me.isHorizontal()) {
89482			// Reset position before calculating rotation
89483			me.width = me.maxWidth;
89484			me.left = 0;
89485			me.right = me.width;
89486		} else {
89487			me.height = me.maxHeight;
89488
89489			// Reset position before calculating rotation
89490			me.top = 0;
89491			me.bottom = me.height;
89492		}
89493
89494		// Reset padding
89495		me.paddingLeft = 0;
89496		me.paddingTop = 0;
89497		me.paddingRight = 0;
89498		me.paddingBottom = 0;
89499
89500		// Reset minSize
89501		me.minSize = {
89502			width: 0,
89503			height: 0
89504		};
89505	},
89506	afterSetDimensions: noop,
89507
89508	//
89509
89510	beforeBuildLabels: noop,
89511	buildLabels: noop,
89512	afterBuildLabels: noop,
89513
89514	//
89515
89516	beforeFit: noop,
89517	fit: function() {
89518		var me = this;
89519		var valueOrDefault = helpers.valueOrDefault;
89520		var opts = me.options;
89521		var display = opts.display;
89522		var fontSize = valueOrDefault(opts.fontSize, defaults.global.defaultFontSize);
89523		var minSize = me.minSize;
89524		var lineCount = helpers.isArray(opts.text) ? opts.text.length : 1;
89525		var lineHeight = helpers.options.toLineHeight(opts.lineHeight, fontSize);
89526		var textSize = display ? (lineCount * lineHeight) + (opts.padding * 2) : 0;
89527
89528		if (me.isHorizontal()) {
89529			minSize.width = me.maxWidth; // fill all the width
89530			minSize.height = textSize;
89531		} else {
89532			minSize.width = textSize;
89533			minSize.height = me.maxHeight; // fill all the height
89534		}
89535
89536		me.width = minSize.width;
89537		me.height = minSize.height;
89538
89539	},
89540	afterFit: noop,
89541
89542	// Shared Methods
89543	isHorizontal: function() {
89544		var pos = this.options.position;
89545		return pos === 'top' || pos === 'bottom';
89546	},
89547
89548	// Actually draw the title block on the canvas
89549	draw: function() {
89550		var me = this;
89551		var ctx = me.ctx;
89552		var valueOrDefault = helpers.valueOrDefault;
89553		var opts = me.options;
89554		var globalDefaults = defaults.global;
89555
89556		if (opts.display) {
89557			var fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize);
89558			var fontStyle = valueOrDefault(opts.fontStyle, globalDefaults.defaultFontStyle);
89559			var fontFamily = valueOrDefault(opts.fontFamily, globalDefaults.defaultFontFamily);
89560			var titleFont = helpers.fontString(fontSize, fontStyle, fontFamily);
89561			var lineHeight = helpers.options.toLineHeight(opts.lineHeight, fontSize);
89562			var offset = lineHeight / 2 + opts.padding;
89563			var rotation = 0;
89564			var top = me.top;
89565			var left = me.left;
89566			var bottom = me.bottom;
89567			var right = me.right;
89568			var maxWidth, titleX, titleY;
89569
89570			ctx.fillStyle = valueOrDefault(opts.fontColor, globalDefaults.defaultFontColor); // render in correct colour
89571			ctx.font = titleFont;
89572
89573			// Horizontal
89574			if (me.isHorizontal()) {
89575				titleX = left + ((right - left) / 2); // midpoint of the width
89576				titleY = top + offset;
89577				maxWidth = right - left;
89578			} else {
89579				titleX = opts.position === 'left' ? left + offset : right - offset;
89580				titleY = top + ((bottom - top) / 2);
89581				maxWidth = bottom - top;
89582				rotation = Math.PI * (opts.position === 'left' ? -0.5 : 0.5);
89583			}
89584
89585			ctx.save();
89586			ctx.translate(titleX, titleY);
89587			ctx.rotate(rotation);
89588			ctx.textAlign = 'center';
89589			ctx.textBaseline = 'middle';
89590
89591			var text = opts.text;
89592			if (helpers.isArray(text)) {
89593				var y = 0;
89594				for (var i = 0; i < text.length; ++i) {
89595					ctx.fillText(text[i], 0, y, maxWidth);
89596					y += lineHeight;
89597				}
89598			} else {
89599				ctx.fillText(text, 0, 0, maxWidth);
89600			}
89601
89602			ctx.restore();
89603		}
89604	}
89605});
89606
89607function createNewTitleBlockAndAttach(chart, titleOpts) {
89608	var title = new Title({
89609		ctx: chart.ctx,
89610		options: titleOpts,
89611		chart: chart
89612	});
89613
89614	layouts.configure(chart, title, titleOpts);
89615	layouts.addBox(chart, title);
89616	chart.titleBlock = title;
89617}
89618
89619module.exports = {
89620	id: 'title',
89621
89622	/**
89623	 * Backward compatibility: since 2.1.5, the title is registered as a plugin, making
89624	 * Chart.Title obsolete. To avoid a breaking change, we export the Title as part of
89625	 * the plugin, which one will be re-exposed in the chart.js file.
89626	 * https://github.com/chartjs/Chart.js/pull/2640
89627	 * @private
89628	 */
89629	_element: Title,
89630
89631	beforeInit: function(chart) {
89632		var titleOpts = chart.options.title;
89633
89634		if (titleOpts) {
89635			createNewTitleBlockAndAttach(chart, titleOpts);
89636		}
89637	},
89638
89639	beforeUpdate: function(chart) {
89640		var titleOpts = chart.options.title;
89641		var titleBlock = chart.titleBlock;
89642
89643		if (titleOpts) {
89644			helpers.mergeIf(titleOpts, defaults.global.title);
89645
89646			if (titleBlock) {
89647				layouts.configure(chart, titleBlock, titleOpts);
89648				titleBlock.options = titleOpts;
89649			} else {
89650				createNewTitleBlockAndAttach(chart, titleOpts);
89651			}
89652		} else if (titleBlock) {
89653			layouts.removeBox(chart, titleBlock);
89654			delete chart.titleBlock;
89655		}
89656	}
89657};
89658
89659},{"26":26,"27":27,"31":31,"46":46}],54:[function(require,module,exports){
89660'use strict';
89661
89662var Scale = require(33);
89663var scaleService = require(34);
89664
89665module.exports = function() {
89666
89667	// Default config for a category scale
89668	var defaultConfig = {
89669		position: 'bottom'
89670	};
89671
89672	var DatasetScale = Scale.extend({
89673		/**
89674		* Internal function to get the correct labels. If data.xLabels or data.yLabels are defined, use those
89675		* else fall back to data.labels
89676		* @private
89677		*/
89678		getLabels: function() {
89679			var data = this.chart.data;
89680			return this.options.labels || (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels;
89681		},
89682
89683		determineDataLimits: function() {
89684			var me = this;
89685			var labels = me.getLabels();
89686			me.minIndex = 0;
89687			me.maxIndex = labels.length - 1;
89688			var findIndex;
89689
89690			if (me.options.ticks.min !== undefined) {
89691				// user specified min value
89692				findIndex = labels.indexOf(me.options.ticks.min);
89693				me.minIndex = findIndex !== -1 ? findIndex : me.minIndex;
89694			}
89695
89696			if (me.options.ticks.max !== undefined) {
89697				// user specified max value
89698				findIndex = labels.indexOf(me.options.ticks.max);
89699				me.maxIndex = findIndex !== -1 ? findIndex : me.maxIndex;
89700			}
89701
89702			me.min = labels[me.minIndex];
89703			me.max = labels[me.maxIndex];
89704		},
89705
89706		buildTicks: function() {
89707			var me = this;
89708			var labels = me.getLabels();
89709			// If we are viewing some subset of labels, slice the original array
89710			me.ticks = (me.minIndex === 0 && me.maxIndex === labels.length - 1) ? labels : labels.slice(me.minIndex, me.maxIndex + 1);
89711		},
89712
89713		getLabelForIndex: function(index, datasetIndex) {
89714			var me = this;
89715			var data = me.chart.data;
89716			var isHorizontal = me.isHorizontal();
89717
89718			if (data.yLabels && !isHorizontal) {
89719				return me.getRightValue(data.datasets[datasetIndex].data[index]);
89720			}
89721			return me.ticks[index - me.minIndex];
89722		},
89723
89724		// Used to get data value locations.  Value can either be an index or a numerical value
89725		getPixelForValue: function(value, index) {
89726			var me = this;
89727			var offset = me.options.offset;
89728			// 1 is added because we need the length but we have the indexes
89729			var offsetAmt = Math.max((me.maxIndex + 1 - me.minIndex - (offset ? 0 : 1)), 1);
89730
89731			// If value is a data object, then index is the index in the data array,
89732			// not the index of the scale. We need to change that.
89733			var valueCategory;
89734			if (value !== undefined && value !== null) {
89735				valueCategory = me.isHorizontal() ? value.x : value.y;
89736			}
89737			if (valueCategory !== undefined || (value !== undefined && isNaN(index))) {
89738				var labels = me.getLabels();
89739				value = valueCategory || value;
89740				var idx = labels.indexOf(value);
89741				index = idx !== -1 ? idx : index;
89742			}
89743
89744			if (me.isHorizontal()) {
89745				var valueWidth = me.width / offsetAmt;
89746				var widthOffset = (valueWidth * (index - me.minIndex));
89747
89748				if (offset) {
89749					widthOffset += (valueWidth / 2);
89750				}
89751
89752				return me.left + Math.round(widthOffset);
89753			}
89754			var valueHeight = me.height / offsetAmt;
89755			var heightOffset = (valueHeight * (index - me.minIndex));
89756
89757			if (offset) {
89758				heightOffset += (valueHeight / 2);
89759			}
89760
89761			return me.top + Math.round(heightOffset);
89762		},
89763		getPixelForTick: function(index) {
89764			return this.getPixelForValue(this.ticks[index], index + this.minIndex, null);
89765		},
89766		getValueForPixel: function(pixel) {
89767			var me = this;
89768			var offset = me.options.offset;
89769			var value;
89770			var offsetAmt = Math.max((me._ticks.length - (offset ? 0 : 1)), 1);
89771			var horz = me.isHorizontal();
89772			var valueDimension = (horz ? me.width : me.height) / offsetAmt;
89773
89774			pixel -= horz ? me.left : me.top;
89775
89776			if (offset) {
89777				pixel -= (valueDimension / 2);
89778			}
89779
89780			if (pixel <= 0) {
89781				value = 0;
89782			} else {
89783				value = Math.round(pixel / valueDimension);
89784			}
89785
89786			return value + me.minIndex;
89787		},
89788		getBasePixel: function() {
89789			return this.bottom;
89790		}
89791	});
89792
89793	scaleService.registerScaleType('category', DatasetScale, defaultConfig);
89794};
89795
89796},{"33":33,"34":34}],55:[function(require,module,exports){
89797'use strict';
89798
89799var defaults = require(26);
89800var helpers = require(46);
89801var scaleService = require(34);
89802var Ticks = require(35);
89803
89804module.exports = function(Chart) {
89805
89806	var defaultConfig = {
89807		position: 'left',
89808		ticks: {
89809			callback: Ticks.formatters.linear
89810		}
89811	};
89812
89813	var LinearScale = Chart.LinearScaleBase.extend({
89814
89815		determineDataLimits: function() {
89816			var me = this;
89817			var opts = me.options;
89818			var chart = me.chart;
89819			var data = chart.data;
89820			var datasets = data.datasets;
89821			var isHorizontal = me.isHorizontal();
89822			var DEFAULT_MIN = 0;
89823			var DEFAULT_MAX = 1;
89824
89825			function IDMatches(meta) {
89826				return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id;
89827			}
89828
89829			// First Calculate the range
89830			me.min = null;
89831			me.max = null;
89832
89833			var hasStacks = opts.stacked;
89834			if (hasStacks === undefined) {
89835				helpers.each(datasets, function(dataset, datasetIndex) {
89836					if (hasStacks) {
89837						return;
89838					}
89839
89840					var meta = chart.getDatasetMeta(datasetIndex);
89841					if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) &&
89842						meta.stack !== undefined) {
89843						hasStacks = true;
89844					}
89845				});
89846			}
89847
89848			if (opts.stacked || hasStacks) {
89849				var valuesPerStack = {};
89850
89851				helpers.each(datasets, function(dataset, datasetIndex) {
89852					var meta = chart.getDatasetMeta(datasetIndex);
89853					var key = [
89854						meta.type,
89855						// we have a separate stack for stack=undefined datasets when the opts.stacked is undefined
89856						((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''),
89857						meta.stack
89858					].join('.');
89859
89860					if (valuesPerStack[key] === undefined) {
89861						valuesPerStack[key] = {
89862							positiveValues: [],
89863							negativeValues: []
89864						};
89865					}
89866
89867					// Store these per type
89868					var positiveValues = valuesPerStack[key].positiveValues;
89869					var negativeValues = valuesPerStack[key].negativeValues;
89870
89871					if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
89872						helpers.each(dataset.data, function(rawValue, index) {
89873							var value = +me.getRightValue(rawValue);
89874							if (isNaN(value) || meta.data[index].hidden) {
89875								return;
89876							}
89877
89878							positiveValues[index] = positiveValues[index] || 0;
89879							negativeValues[index] = negativeValues[index] || 0;
89880
89881							if (opts.relativePoints) {
89882								positiveValues[index] = 100;
89883							} else if (value < 0) {
89884								negativeValues[index] += value;
89885							} else {
89886								positiveValues[index] += value;
89887							}
89888						});
89889					}
89890				});
89891
89892				helpers.each(valuesPerStack, function(valuesForType) {
89893					var values = valuesForType.positiveValues.concat(valuesForType.negativeValues);
89894					var minVal = helpers.min(values);
89895					var maxVal = helpers.max(values);
89896					me.min = me.min === null ? minVal : Math.min(me.min, minVal);
89897					me.max = me.max === null ? maxVal : Math.max(me.max, maxVal);
89898				});
89899
89900			} else {
89901				helpers.each(datasets, function(dataset, datasetIndex) {
89902					var meta = chart.getDatasetMeta(datasetIndex);
89903					if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
89904						helpers.each(dataset.data, function(rawValue, index) {
89905							var value = +me.getRightValue(rawValue);
89906							if (isNaN(value) || meta.data[index].hidden) {
89907								return;
89908							}
89909
89910							if (me.min === null) {
89911								me.min = value;
89912							} else if (value < me.min) {
89913								me.min = value;
89914							}
89915
89916							if (me.max === null) {
89917								me.max = value;
89918							} else if (value > me.max) {
89919								me.max = value;
89920							}
89921						});
89922					}
89923				});
89924			}
89925
89926			me.min = isFinite(me.min) && !isNaN(me.min) ? me.min : DEFAULT_MIN;
89927			me.max = isFinite(me.max) && !isNaN(me.max) ? me.max : DEFAULT_MAX;
89928
89929			// Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero
89930			this.handleTickRangeOptions();
89931		},
89932		getTickLimit: function() {
89933			var maxTicks;
89934			var me = this;
89935			var tickOpts = me.options.ticks;
89936
89937			if (me.isHorizontal()) {
89938				maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.width / 50));
89939			} else {
89940				// The factor of 2 used to scale the font size has been experimentally determined.
89941				var tickFontSize = helpers.valueOrDefault(tickOpts.fontSize, defaults.global.defaultFontSize);
89942				maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.height / (2 * tickFontSize)));
89943			}
89944
89945			return maxTicks;
89946		},
89947		// Called after the ticks are built. We need
89948		handleDirectionalChanges: function() {
89949			if (!this.isHorizontal()) {
89950				// We are in a vertical orientation. The top value is the highest. So reverse the array
89951				this.ticks.reverse();
89952			}
89953		},
89954		getLabelForIndex: function(index, datasetIndex) {
89955			return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
89956		},
89957		// Utils
89958		getPixelForValue: function(value) {
89959			// This must be called after fit has been run so that
89960			// this.left, this.top, this.right, and this.bottom have been defined
89961			var me = this;
89962			var start = me.start;
89963
89964			var rightValue = +me.getRightValue(value);
89965			var pixel;
89966			var range = me.end - start;
89967
89968			if (me.isHorizontal()) {
89969				pixel = me.left + (me.width / range * (rightValue - start));
89970			} else {
89971				pixel = me.bottom - (me.height / range * (rightValue - start));
89972			}
89973			return pixel;
89974		},
89975		getValueForPixel: function(pixel) {
89976			var me = this;
89977			var isHorizontal = me.isHorizontal();
89978			var innerDimension = isHorizontal ? me.width : me.height;
89979			var offset = (isHorizontal ? pixel - me.left : me.bottom - pixel) / innerDimension;
89980			return me.start + ((me.end - me.start) * offset);
89981		},
89982		getPixelForTick: function(index) {
89983			return this.getPixelForValue(this.ticksAsNumbers[index]);
89984		}
89985	});
89986
89987	scaleService.registerScaleType('linear', LinearScale, defaultConfig);
89988};
89989
89990},{"26":26,"34":34,"35":35,"46":46}],56:[function(require,module,exports){
89991'use strict';
89992
89993var helpers = require(46);
89994var Scale = require(33);
89995
89996/**
89997 * Generate a set of linear ticks
89998 * @param generationOptions the options used to generate the ticks
89999 * @param dataRange the range of the data
90000 * @returns {Array<Number>} array of tick values
90001 */
90002function generateTicks(generationOptions, dataRange) {
90003	var ticks = [];
90004	// To get a "nice" value for the tick spacing, we will use the appropriately named
90005	// "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks
90006	// for details.
90007
90008	var factor;
90009	var precision;
90010	var spacing;
90011
90012	if (generationOptions.stepSize && generationOptions.stepSize > 0) {
90013		spacing = generationOptions.stepSize;
90014	} else {
90015		var niceRange = helpers.niceNum(dataRange.max - dataRange.min, false);
90016		spacing = helpers.niceNum(niceRange / (generationOptions.maxTicks - 1), true);
90017
90018		precision = generationOptions.precision;
90019		if (precision !== undefined) {
90020			// If the user specified a precision, round to that number of decimal places
90021			factor = Math.pow(10, precision);
90022			spacing = Math.ceil(spacing * factor) / factor;
90023		}
90024	}
90025	var niceMin = Math.floor(dataRange.min / spacing) * spacing;
90026	var niceMax = Math.ceil(dataRange.max / spacing) * spacing;
90027
90028	// If min, max and stepSize is set and they make an evenly spaced scale use it.
90029	if (!helpers.isNullOrUndef(generationOptions.min) && !helpers.isNullOrUndef(generationOptions.max) && generationOptions.stepSize) {
90030		// If very close to our whole number, use it.
90031		if (helpers.almostWhole((generationOptions.max - generationOptions.min) / generationOptions.stepSize, spacing / 1000)) {
90032			niceMin = generationOptions.min;
90033			niceMax = generationOptions.max;
90034		}
90035	}
90036
90037	var numSpaces = (niceMax - niceMin) / spacing;
90038	// If very close to our rounded value, use it.
90039	if (helpers.almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) {
90040		numSpaces = Math.round(numSpaces);
90041	} else {
90042		numSpaces = Math.ceil(numSpaces);
90043	}
90044
90045	precision = 1;
90046	if (spacing < 1) {
90047		precision = Math.pow(10, 1 - Math.floor(helpers.log10(spacing)));
90048		niceMin = Math.round(niceMin * precision) / precision;
90049		niceMax = Math.round(niceMax * precision) / precision;
90050	}
90051	ticks.push(generationOptions.min !== undefined ? generationOptions.min : niceMin);
90052	for (var j = 1; j < numSpaces; ++j) {
90053		ticks.push(Math.round((niceMin + j * spacing) * precision) / precision);
90054	}
90055	ticks.push(generationOptions.max !== undefined ? generationOptions.max : niceMax);
90056
90057	return ticks;
90058}
90059
90060module.exports = function(Chart) {
90061
90062	var noop = helpers.noop;
90063
90064	Chart.LinearScaleBase = Scale.extend({
90065		getRightValue: function(value) {
90066			if (typeof value === 'string') {
90067				return +value;
90068			}
90069			return Scale.prototype.getRightValue.call(this, value);
90070		},
90071
90072		handleTickRangeOptions: function() {
90073			var me = this;
90074			var opts = me.options;
90075			var tickOpts = opts.ticks;
90076
90077			// If we are forcing it to begin at 0, but 0 will already be rendered on the chart,
90078			// do nothing since that would make the chart weird. If the user really wants a weird chart
90079			// axis, they can manually override it
90080			if (tickOpts.beginAtZero) {
90081				var minSign = helpers.sign(me.min);
90082				var maxSign = helpers.sign(me.max);
90083
90084				if (minSign < 0 && maxSign < 0) {
90085					// move the top up to 0
90086					me.max = 0;
90087				} else if (minSign > 0 && maxSign > 0) {
90088					// move the bottom down to 0
90089					me.min = 0;
90090				}
90091			}
90092
90093			var setMin = tickOpts.min !== undefined || tickOpts.suggestedMin !== undefined;
90094			var setMax = tickOpts.max !== undefined || tickOpts.suggestedMax !== undefined;
90095
90096			if (tickOpts.min !== undefined) {
90097				me.min = tickOpts.min;
90098			} else if (tickOpts.suggestedMin !== undefined) {
90099				if (me.min === null) {
90100					me.min = tickOpts.suggestedMin;
90101				} else {
90102					me.min = Math.min(me.min, tickOpts.suggestedMin);
90103				}
90104			}
90105
90106			if (tickOpts.max !== undefined) {
90107				me.max = tickOpts.max;
90108			} else if (tickOpts.suggestedMax !== undefined) {
90109				if (me.max === null) {
90110					me.max = tickOpts.suggestedMax;
90111				} else {
90112					me.max = Math.max(me.max, tickOpts.suggestedMax);
90113				}
90114			}
90115
90116			if (setMin !== setMax) {
90117				// We set the min or the max but not both.
90118				// So ensure that our range is good
90119				// Inverted or 0 length range can happen when
90120				// ticks.min is set, and no datasets are visible
90121				if (me.min >= me.max) {
90122					if (setMin) {
90123						me.max = me.min + 1;
90124					} else {
90125						me.min = me.max - 1;
90126					}
90127				}
90128			}
90129
90130			if (me.min === me.max) {
90131				me.max++;
90132
90133				if (!tickOpts.beginAtZero) {
90134					me.min--;
90135				}
90136			}
90137		},
90138		getTickLimit: noop,
90139		handleDirectionalChanges: noop,
90140
90141		buildTicks: function() {
90142			var me = this;
90143			var opts = me.options;
90144			var tickOpts = opts.ticks;
90145
90146			// Figure out what the max number of ticks we can support it is based on the size of
90147			// the axis area. For now, we say that the minimum tick spacing in pixels must be 50
90148			// We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
90149			// the graph. Make sure we always have at least 2 ticks
90150			var maxTicks = me.getTickLimit();
90151			maxTicks = Math.max(2, maxTicks);
90152
90153			var numericGeneratorOptions = {
90154				maxTicks: maxTicks,
90155				min: tickOpts.min,
90156				max: tickOpts.max,
90157				precision: tickOpts.precision,
90158				stepSize: helpers.valueOrDefault(tickOpts.fixedStepSize, tickOpts.stepSize)
90159			};
90160			var ticks = me.ticks = generateTicks(numericGeneratorOptions, me);
90161
90162			me.handleDirectionalChanges();
90163
90164			// At this point, we need to update our max and min given the tick values since we have expanded the
90165			// range of the scale
90166			me.max = helpers.max(ticks);
90167			me.min = helpers.min(ticks);
90168
90169			if (tickOpts.reverse) {
90170				ticks.reverse();
90171
90172				me.start = me.max;
90173				me.end = me.min;
90174			} else {
90175				me.start = me.min;
90176				me.end = me.max;
90177			}
90178		},
90179		convertTicksToLabels: function() {
90180			var me = this;
90181			me.ticksAsNumbers = me.ticks.slice();
90182			me.zeroLineIndex = me.ticks.indexOf(0);
90183
90184			Scale.prototype.convertTicksToLabels.call(me);
90185		}
90186	});
90187};
90188
90189},{"33":33,"46":46}],57:[function(require,module,exports){
90190'use strict';
90191
90192var helpers = require(46);
90193var Scale = require(33);
90194var scaleService = require(34);
90195var Ticks = require(35);
90196
90197/**
90198 * Generate a set of logarithmic ticks
90199 * @param generationOptions the options used to generate the ticks
90200 * @param dataRange the range of the data
90201 * @returns {Array<Number>} array of tick values
90202 */
90203function generateTicks(generationOptions, dataRange) {
90204	var ticks = [];
90205	var valueOrDefault = helpers.valueOrDefault;
90206
90207	// Figure out what the max number of ticks we can support it is based on the size of
90208	// the axis area. For now, we say that the minimum tick spacing in pixels must be 50
90209	// We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
90210	// the graph
90211	var tickVal = valueOrDefault(generationOptions.min, Math.pow(10, Math.floor(helpers.log10(dataRange.min))));
90212
90213	var endExp = Math.floor(helpers.log10(dataRange.max));
90214	var endSignificand = Math.ceil(dataRange.max / Math.pow(10, endExp));
90215	var exp, significand;
90216
90217	if (tickVal === 0) {
90218		exp = Math.floor(helpers.log10(dataRange.minNotZero));
90219		significand = Math.floor(dataRange.minNotZero / Math.pow(10, exp));
90220
90221		ticks.push(tickVal);
90222		tickVal = significand * Math.pow(10, exp);
90223	} else {
90224		exp = Math.floor(helpers.log10(tickVal));
90225		significand = Math.floor(tickVal / Math.pow(10, exp));
90226	}
90227	var precision = exp < 0 ? Math.pow(10, Math.abs(exp)) : 1;
90228
90229	do {
90230		ticks.push(tickVal);
90231
90232		++significand;
90233		if (significand === 10) {
90234			significand = 1;
90235			++exp;
90236			precision = exp >= 0 ? 1 : precision;
90237		}
90238
90239		tickVal = Math.round(significand * Math.pow(10, exp) * precision) / precision;
90240	} while (exp < endExp || (exp === endExp && significand < endSignificand));
90241
90242	var lastTick = valueOrDefault(generationOptions.max, tickVal);
90243	ticks.push(lastTick);
90244
90245	return ticks;
90246}
90247
90248
90249module.exports = function(Chart) {
90250
90251	var defaultConfig = {
90252		position: 'left',
90253
90254		// label settings
90255		ticks: {
90256			callback: Ticks.formatters.logarithmic
90257		}
90258	};
90259
90260	var LogarithmicScale = Scale.extend({
90261		determineDataLimits: function() {
90262			var me = this;
90263			var opts = me.options;
90264			var chart = me.chart;
90265			var data = chart.data;
90266			var datasets = data.datasets;
90267			var isHorizontal = me.isHorizontal();
90268			function IDMatches(meta) {
90269				return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id;
90270			}
90271
90272			// Calculate Range
90273			me.min = null;
90274			me.max = null;
90275			me.minNotZero = null;
90276
90277			var hasStacks = opts.stacked;
90278			if (hasStacks === undefined) {
90279				helpers.each(datasets, function(dataset, datasetIndex) {
90280					if (hasStacks) {
90281						return;
90282					}
90283
90284					var meta = chart.getDatasetMeta(datasetIndex);
90285					if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) &&
90286						meta.stack !== undefined) {
90287						hasStacks = true;
90288					}
90289				});
90290			}
90291
90292			if (opts.stacked || hasStacks) {
90293				var valuesPerStack = {};
90294
90295				helpers.each(datasets, function(dataset, datasetIndex) {
90296					var meta = chart.getDatasetMeta(datasetIndex);
90297					var key = [
90298						meta.type,
90299						// we have a separate stack for stack=undefined datasets when the opts.stacked is undefined
90300						((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''),
90301						meta.stack
90302					].join('.');
90303
90304					if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
90305						if (valuesPerStack[key] === undefined) {
90306							valuesPerStack[key] = [];
90307						}
90308
90309						helpers.each(dataset.data, function(rawValue, index) {
90310							var values = valuesPerStack[key];
90311							var value = +me.getRightValue(rawValue);
90312							// invalid, hidden and negative values are ignored
90313							if (isNaN(value) || meta.data[index].hidden || value < 0) {
90314								return;
90315							}
90316							values[index] = values[index] || 0;
90317							values[index] += value;
90318						});
90319					}
90320				});
90321
90322				helpers.each(valuesPerStack, function(valuesForType) {
90323					if (valuesForType.length > 0) {
90324						var minVal = helpers.min(valuesForType);
90325						var maxVal = helpers.max(valuesForType);
90326						me.min = me.min === null ? minVal : Math.min(me.min, minVal);
90327						me.max = me.max === null ? maxVal : Math.max(me.max, maxVal);
90328					}
90329				});
90330
90331			} else {
90332				helpers.each(datasets, function(dataset, datasetIndex) {
90333					var meta = chart.getDatasetMeta(datasetIndex);
90334					if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
90335						helpers.each(dataset.data, function(rawValue, index) {
90336							var value = +me.getRightValue(rawValue);
90337							// invalid, hidden and negative values are ignored
90338							if (isNaN(value) || meta.data[index].hidden || value < 0) {
90339								return;
90340							}
90341
90342							if (me.min === null) {
90343								me.min = value;
90344							} else if (value < me.min) {
90345								me.min = value;
90346							}
90347
90348							if (me.max === null) {
90349								me.max = value;
90350							} else if (value > me.max) {
90351								me.max = value;
90352							}
90353
90354							if (value !== 0 && (me.minNotZero === null || value < me.minNotZero)) {
90355								me.minNotZero = value;
90356							}
90357						});
90358					}
90359				});
90360			}
90361
90362			// Common base implementation to handle ticks.min, ticks.max
90363			this.handleTickRangeOptions();
90364		},
90365		handleTickRangeOptions: function() {
90366			var me = this;
90367			var opts = me.options;
90368			var tickOpts = opts.ticks;
90369			var valueOrDefault = helpers.valueOrDefault;
90370			var DEFAULT_MIN = 1;
90371			var DEFAULT_MAX = 10;
90372
90373			me.min = valueOrDefault(tickOpts.min, me.min);
90374			me.max = valueOrDefault(tickOpts.max, me.max);
90375
90376			if (me.min === me.max) {
90377				if (me.min !== 0 && me.min !== null) {
90378					me.min = Math.pow(10, Math.floor(helpers.log10(me.min)) - 1);
90379					me.max = Math.pow(10, Math.floor(helpers.log10(me.max)) + 1);
90380				} else {
90381					me.min = DEFAULT_MIN;
90382					me.max = DEFAULT_MAX;
90383				}
90384			}
90385			if (me.min === null) {
90386				me.min = Math.pow(10, Math.floor(helpers.log10(me.max)) - 1);
90387			}
90388			if (me.max === null) {
90389				me.max = me.min !== 0
90390					? Math.pow(10, Math.floor(helpers.log10(me.min)) + 1)
90391					: DEFAULT_MAX;
90392			}
90393			if (me.minNotZero === null) {
90394				if (me.min > 0) {
90395					me.minNotZero = me.min;
90396				} else if (me.max < 1) {
90397					me.minNotZero = Math.pow(10, Math.floor(helpers.log10(me.max)));
90398				} else {
90399					me.minNotZero = DEFAULT_MIN;
90400				}
90401			}
90402		},
90403		buildTicks: function() {
90404			var me = this;
90405			var opts = me.options;
90406			var tickOpts = opts.ticks;
90407			var reverse = !me.isHorizontal();
90408
90409			var generationOptions = {
90410				min: tickOpts.min,
90411				max: tickOpts.max
90412			};
90413			var ticks = me.ticks = generateTicks(generationOptions, me);
90414
90415			// At this point, we need to update our max and min given the tick values since we have expanded the
90416			// range of the scale
90417			me.max = helpers.max(ticks);
90418			me.min = helpers.min(ticks);
90419
90420			if (tickOpts.reverse) {
90421				reverse = !reverse;
90422				me.start = me.max;
90423				me.end = me.min;
90424			} else {
90425				me.start = me.min;
90426				me.end = me.max;
90427			}
90428			if (reverse) {
90429				ticks.reverse();
90430			}
90431		},
90432		convertTicksToLabels: function() {
90433			this.tickValues = this.ticks.slice();
90434
90435			Scale.prototype.convertTicksToLabels.call(this);
90436		},
90437		// Get the correct tooltip label
90438		getLabelForIndex: function(index, datasetIndex) {
90439			return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
90440		},
90441		getPixelForTick: function(index) {
90442			return this.getPixelForValue(this.tickValues[index]);
90443		},
90444		/**
90445		 * Returns the value of the first tick.
90446		 * @param {Number} value - The minimum not zero value.
90447		 * @return {Number} The first tick value.
90448		 * @private
90449		 */
90450		_getFirstTickValue: function(value) {
90451			var exp = Math.floor(helpers.log10(value));
90452			var significand = Math.floor(value / Math.pow(10, exp));
90453
90454			return significand * Math.pow(10, exp);
90455		},
90456		getPixelForValue: function(value) {
90457			var me = this;
90458			var reverse = me.options.ticks.reverse;
90459			var log10 = helpers.log10;
90460			var firstTickValue = me._getFirstTickValue(me.minNotZero);
90461			var offset = 0;
90462			var innerDimension, pixel, start, end, sign;
90463
90464			value = +me.getRightValue(value);
90465			if (reverse) {
90466				start = me.end;
90467				end = me.start;
90468				sign = -1;
90469			} else {
90470				start = me.start;
90471				end = me.end;
90472				sign = 1;
90473			}
90474			if (me.isHorizontal()) {
90475				innerDimension = me.width;
90476				pixel = reverse ? me.right : me.left;
90477			} else {
90478				innerDimension = me.height;
90479				sign *= -1; // invert, since the upper-left corner of the canvas is at pixel (0, 0)
90480				pixel = reverse ? me.top : me.bottom;
90481			}
90482			if (value !== start) {
90483				if (start === 0) { // include zero tick
90484					offset = helpers.getValueOrDefault(
90485						me.options.ticks.fontSize,
90486						Chart.defaults.global.defaultFontSize
90487					);
90488					innerDimension -= offset;
90489					start = firstTickValue;
90490				}
90491				if (value !== 0) {
90492					offset += innerDimension / (log10(end) - log10(start)) * (log10(value) - log10(start));
90493				}
90494				pixel += sign * offset;
90495			}
90496			return pixel;
90497		},
90498		getValueForPixel: function(pixel) {
90499			var me = this;
90500			var reverse = me.options.ticks.reverse;
90501			var log10 = helpers.log10;
90502			var firstTickValue = me._getFirstTickValue(me.minNotZero);
90503			var innerDimension, start, end, value;
90504
90505			if (reverse) {
90506				start = me.end;
90507				end = me.start;
90508			} else {
90509				start = me.start;
90510				end = me.end;
90511			}
90512			if (me.isHorizontal()) {
90513				innerDimension = me.width;
90514				value = reverse ? me.right - pixel : pixel - me.left;
90515			} else {
90516				innerDimension = me.height;
90517				value = reverse ? pixel - me.top : me.bottom - pixel;
90518			}
90519			if (value !== start) {
90520				if (start === 0) { // include zero tick
90521					var offset = helpers.getValueOrDefault(
90522						me.options.ticks.fontSize,
90523						Chart.defaults.global.defaultFontSize
90524					);
90525					value -= offset;
90526					innerDimension -= offset;
90527					start = firstTickValue;
90528				}
90529				value *= log10(end) - log10(start);
90530				value /= innerDimension;
90531				value = Math.pow(10, log10(start) + value);
90532			}
90533			return value;
90534		}
90535	});
90536
90537	scaleService.registerScaleType('logarithmic', LogarithmicScale, defaultConfig);
90538};
90539
90540},{"33":33,"34":34,"35":35,"46":46}],58:[function(require,module,exports){
90541'use strict';
90542
90543var defaults = require(26);
90544var helpers = require(46);
90545var scaleService = require(34);
90546var Ticks = require(35);
90547
90548module.exports = function(Chart) {
90549
90550	var globalDefaults = defaults.global;
90551
90552	var defaultConfig = {
90553		display: true,
90554
90555		// Boolean - Whether to animate scaling the chart from the centre
90556		animate: true,
90557		position: 'chartArea',
90558
90559		angleLines: {
90560			display: true,
90561			color: 'rgba(0, 0, 0, 0.1)',
90562			lineWidth: 1
90563		},
90564
90565		gridLines: {
90566			circular: false
90567		},
90568
90569		// label settings
90570		ticks: {
90571			// Boolean - Show a backdrop to the scale label
90572			showLabelBackdrop: true,
90573
90574			// String - The colour of the label backdrop
90575			backdropColor: 'rgba(255,255,255,0.75)',
90576
90577			// Number - The backdrop padding above & below the label in pixels
90578			backdropPaddingY: 2,
90579
90580			// Number - The backdrop padding to the side of the label in pixels
90581			backdropPaddingX: 2,
90582
90583			callback: Ticks.formatters.linear
90584		},
90585
90586		pointLabels: {
90587			// Boolean - if true, show point labels
90588			display: true,
90589
90590			// Number - Point label font size in pixels
90591			fontSize: 10,
90592
90593			// Function - Used to convert point labels
90594			callback: function(label) {
90595				return label;
90596			}
90597		}
90598	};
90599
90600	function getValueCount(scale) {
90601		var opts = scale.options;
90602		return opts.angleLines.display || opts.pointLabels.display ? scale.chart.data.labels.length : 0;
90603	}
90604
90605	function getPointLabelFontOptions(scale) {
90606		var pointLabelOptions = scale.options.pointLabels;
90607		var fontSize = helpers.valueOrDefault(pointLabelOptions.fontSize, globalDefaults.defaultFontSize);
90608		var fontStyle = helpers.valueOrDefault(pointLabelOptions.fontStyle, globalDefaults.defaultFontStyle);
90609		var fontFamily = helpers.valueOrDefault(pointLabelOptions.fontFamily, globalDefaults.defaultFontFamily);
90610		var font = helpers.fontString(fontSize, fontStyle, fontFamily);
90611
90612		return {
90613			size: fontSize,
90614			style: fontStyle,
90615			family: fontFamily,
90616			font: font
90617		};
90618	}
90619
90620	function measureLabelSize(ctx, fontSize, label) {
90621		if (helpers.isArray(label)) {
90622			return {
90623				w: helpers.longestText(ctx, ctx.font, label),
90624				h: (label.length * fontSize) + ((label.length - 1) * 1.5 * fontSize)
90625			};
90626		}
90627
90628		return {
90629			w: ctx.measureText(label).width,
90630			h: fontSize
90631		};
90632	}
90633
90634	function determineLimits(angle, pos, size, min, max) {
90635		if (angle === min || angle === max) {
90636			return {
90637				start: pos - (size / 2),
90638				end: pos + (size / 2)
90639			};
90640		} else if (angle < min || angle > max) {
90641			return {
90642				start: pos - size - 5,
90643				end: pos
90644			};
90645		}
90646
90647		return {
90648			start: pos,
90649			end: pos + size + 5
90650		};
90651	}
90652
90653	/**
90654	 * Helper function to fit a radial linear scale with point labels
90655	 */
90656	function fitWithPointLabels(scale) {
90657		/*
90658		 * Right, this is really confusing and there is a lot of maths going on here
90659		 * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9
90660		 *
90661		 * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif
90662		 *
90663		 * Solution:
90664		 *
90665		 * We assume the radius of the polygon is half the size of the canvas at first
90666		 * at each index we check if the text overlaps.
90667		 *
90668		 * Where it does, we store that angle and that index.
90669		 *
90670		 * After finding the largest index and angle we calculate how much we need to remove
90671		 * from the shape radius to move the point inwards by that x.
90672		 *
90673		 * We average the left and right distances to get the maximum shape radius that can fit in the box
90674		 * along with labels.
90675		 *
90676		 * Once we have that, we can find the centre point for the chart, by taking the x text protrusion
90677		 * on each side, removing that from the size, halving it and adding the left x protrusion width.
90678		 *
90679		 * This will mean we have a shape fitted to the canvas, as large as it can be with the labels
90680		 * and position it in the most space efficient manner
90681		 *
90682		 * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif
90683		 */
90684
90685		var plFont = getPointLabelFontOptions(scale);
90686
90687		// Get maximum radius of the polygon. Either half the height (minus the text width) or half the width.
90688		// Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points
90689		var largestPossibleRadius = Math.min(scale.height / 2, scale.width / 2);
90690		var furthestLimits = {
90691			r: scale.width,
90692			l: 0,
90693			t: scale.height,
90694			b: 0
90695		};
90696		var furthestAngles = {};
90697		var i, textSize, pointPosition;
90698
90699		scale.ctx.font = plFont.font;
90700		scale._pointLabelSizes = [];
90701
90702		var valueCount = getValueCount(scale);
90703		for (i = 0; i < valueCount; i++) {
90704			pointPosition = scale.getPointPosition(i, largestPossibleRadius);
90705			textSize = measureLabelSize(scale.ctx, plFont.size, scale.pointLabels[i] || '');
90706			scale._pointLabelSizes[i] = textSize;
90707
90708			// Add quarter circle to make degree 0 mean top of circle
90709			var angleRadians = scale.getIndexAngle(i);
90710			var angle = helpers.toDegrees(angleRadians) % 360;
90711			var hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180);
90712			var vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270);
90713
90714			if (hLimits.start < furthestLimits.l) {
90715				furthestLimits.l = hLimits.start;
90716				furthestAngles.l = angleRadians;
90717			}
90718
90719			if (hLimits.end > furthestLimits.r) {
90720				furthestLimits.r = hLimits.end;
90721				furthestAngles.r = angleRadians;
90722			}
90723
90724			if (vLimits.start < furthestLimits.t) {
90725				furthestLimits.t = vLimits.start;
90726				furthestAngles.t = angleRadians;
90727			}
90728
90729			if (vLimits.end > furthestLimits.b) {
90730				furthestLimits.b = vLimits.end;
90731				furthestAngles.b = angleRadians;
90732			}
90733		}
90734
90735		scale.setReductions(largestPossibleRadius, furthestLimits, furthestAngles);
90736	}
90737
90738	/**
90739	 * Helper function to fit a radial linear scale with no point labels
90740	 */
90741	function fit(scale) {
90742		var largestPossibleRadius = Math.min(scale.height / 2, scale.width / 2);
90743		scale.drawingArea = Math.round(largestPossibleRadius);
90744		scale.setCenterPoint(0, 0, 0, 0);
90745	}
90746
90747	function getTextAlignForAngle(angle) {
90748		if (angle === 0 || angle === 180) {
90749			return 'center';
90750		} else if (angle < 180) {
90751			return 'left';
90752		}
90753
90754		return 'right';
90755	}
90756
90757	function fillText(ctx, text, position, fontSize) {
90758		if (helpers.isArray(text)) {
90759			var y = position.y;
90760			var spacing = 1.5 * fontSize;
90761
90762			for (var i = 0; i < text.length; ++i) {
90763				ctx.fillText(text[i], position.x, y);
90764				y += spacing;
90765			}
90766		} else {
90767			ctx.fillText(text, position.x, position.y);
90768		}
90769	}
90770
90771	function adjustPointPositionForLabelHeight(angle, textSize, position) {
90772		if (angle === 90 || angle === 270) {
90773			position.y -= (textSize.h / 2);
90774		} else if (angle > 270 || angle < 90) {
90775			position.y -= textSize.h;
90776		}
90777	}
90778
90779	function drawPointLabels(scale) {
90780		var ctx = scale.ctx;
90781		var opts = scale.options;
90782		var angleLineOpts = opts.angleLines;
90783		var pointLabelOpts = opts.pointLabels;
90784
90785		ctx.lineWidth = angleLineOpts.lineWidth;
90786		ctx.strokeStyle = angleLineOpts.color;
90787
90788		var outerDistance = scale.getDistanceFromCenterForValue(opts.ticks.reverse ? scale.min : scale.max);
90789
90790		// Point Label Font
90791		var plFont = getPointLabelFontOptions(scale);
90792
90793		ctx.textBaseline = 'top';
90794
90795		for (var i = getValueCount(scale) - 1; i >= 0; i--) {
90796			if (angleLineOpts.display) {
90797				var outerPosition = scale.getPointPosition(i, outerDistance);
90798				ctx.beginPath();
90799				ctx.moveTo(scale.xCenter, scale.yCenter);
90800				ctx.lineTo(outerPosition.x, outerPosition.y);
90801				ctx.stroke();
90802				ctx.closePath();
90803			}
90804
90805			if (pointLabelOpts.display) {
90806				// Extra 3px out for some label spacing
90807				var pointLabelPosition = scale.getPointPosition(i, outerDistance + 5);
90808
90809				// Keep this in loop since we may support array properties here
90810				var pointLabelFontColor = helpers.valueAtIndexOrDefault(pointLabelOpts.fontColor, i, globalDefaults.defaultFontColor);
90811				ctx.font = plFont.font;
90812				ctx.fillStyle = pointLabelFontColor;
90813
90814				var angleRadians = scale.getIndexAngle(i);
90815				var angle = helpers.toDegrees(angleRadians);
90816				ctx.textAlign = getTextAlignForAngle(angle);
90817				adjustPointPositionForLabelHeight(angle, scale._pointLabelSizes[i], pointLabelPosition);
90818				fillText(ctx, scale.pointLabels[i] || '', pointLabelPosition, plFont.size);
90819			}
90820		}
90821	}
90822
90823	function drawRadiusLine(scale, gridLineOpts, radius, index) {
90824		var ctx = scale.ctx;
90825		ctx.strokeStyle = helpers.valueAtIndexOrDefault(gridLineOpts.color, index - 1);
90826		ctx.lineWidth = helpers.valueAtIndexOrDefault(gridLineOpts.lineWidth, index - 1);
90827
90828		if (scale.options.gridLines.circular) {
90829			// Draw circular arcs between the points
90830			ctx.beginPath();
90831			ctx.arc(scale.xCenter, scale.yCenter, radius, 0, Math.PI * 2);
90832			ctx.closePath();
90833			ctx.stroke();
90834		} else {
90835			// Draw straight lines connecting each index
90836			var valueCount = getValueCount(scale);
90837
90838			if (valueCount === 0) {
90839				return;
90840			}
90841
90842			ctx.beginPath();
90843			var pointPosition = scale.getPointPosition(0, radius);
90844			ctx.moveTo(pointPosition.x, pointPosition.y);
90845
90846			for (var i = 1; i < valueCount; i++) {
90847				pointPosition = scale.getPointPosition(i, radius);
90848				ctx.lineTo(pointPosition.x, pointPosition.y);
90849			}
90850
90851			ctx.closePath();
90852			ctx.stroke();
90853		}
90854	}
90855
90856	function numberOrZero(param) {
90857		return helpers.isNumber(param) ? param : 0;
90858	}
90859
90860	var LinearRadialScale = Chart.LinearScaleBase.extend({
90861		setDimensions: function() {
90862			var me = this;
90863			var opts = me.options;
90864			var tickOpts = opts.ticks;
90865			// Set the unconstrained dimension before label rotation
90866			me.width = me.maxWidth;
90867			me.height = me.maxHeight;
90868			me.xCenter = Math.round(me.width / 2);
90869			me.yCenter = Math.round(me.height / 2);
90870
90871			var minSize = helpers.min([me.height, me.width]);
90872			var tickFontSize = helpers.valueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);
90873			me.drawingArea = opts.display ? (minSize / 2) - (tickFontSize / 2 + tickOpts.backdropPaddingY) : (minSize / 2);
90874		},
90875		determineDataLimits: function() {
90876			var me = this;
90877			var chart = me.chart;
90878			var min = Number.POSITIVE_INFINITY;
90879			var max = Number.NEGATIVE_INFINITY;
90880
90881			helpers.each(chart.data.datasets, function(dataset, datasetIndex) {
90882				if (chart.isDatasetVisible(datasetIndex)) {
90883					var meta = chart.getDatasetMeta(datasetIndex);
90884
90885					helpers.each(dataset.data, function(rawValue, index) {
90886						var value = +me.getRightValue(rawValue);
90887						if (isNaN(value) || meta.data[index].hidden) {
90888							return;
90889						}
90890
90891						min = Math.min(value, min);
90892						max = Math.max(value, max);
90893					});
90894				}
90895			});
90896
90897			me.min = (min === Number.POSITIVE_INFINITY ? 0 : min);
90898			me.max = (max === Number.NEGATIVE_INFINITY ? 0 : max);
90899
90900			// Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero
90901			me.handleTickRangeOptions();
90902		},
90903		getTickLimit: function() {
90904			var tickOpts = this.options.ticks;
90905			var tickFontSize = helpers.valueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);
90906			return Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(this.drawingArea / (1.5 * tickFontSize)));
90907		},
90908		convertTicksToLabels: function() {
90909			var me = this;
90910
90911			Chart.LinearScaleBase.prototype.convertTicksToLabels.call(me);
90912
90913			// Point labels
90914			me.pointLabels = me.chart.data.labels.map(me.options.pointLabels.callback, me);
90915		},
90916		getLabelForIndex: function(index, datasetIndex) {
90917			return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
90918		},
90919		fit: function() {
90920			if (this.options.pointLabels.display) {
90921				fitWithPointLabels(this);
90922			} else {
90923				fit(this);
90924			}
90925		},
90926		/**
90927		 * Set radius reductions and determine new radius and center point
90928		 * @private
90929		 */
90930		setReductions: function(largestPossibleRadius, furthestLimits, furthestAngles) {
90931			var me = this;
90932			var radiusReductionLeft = furthestLimits.l / Math.sin(furthestAngles.l);
90933			var radiusReductionRight = Math.max(furthestLimits.r - me.width, 0) / Math.sin(furthestAngles.r);
90934			var radiusReductionTop = -furthestLimits.t / Math.cos(furthestAngles.t);
90935			var radiusReductionBottom = -Math.max(furthestLimits.b - me.height, 0) / Math.cos(furthestAngles.b);
90936
90937			radiusReductionLeft = numberOrZero(radiusReductionLeft);
90938			radiusReductionRight = numberOrZero(radiusReductionRight);
90939			radiusReductionTop = numberOrZero(radiusReductionTop);
90940			radiusReductionBottom = numberOrZero(radiusReductionBottom);
90941
90942			me.drawingArea = Math.min(
90943				Math.round(largestPossibleRadius - (radiusReductionLeft + radiusReductionRight) / 2),
90944				Math.round(largestPossibleRadius - (radiusReductionTop + radiusReductionBottom) / 2));
90945			me.setCenterPoint(radiusReductionLeft, radiusReductionRight, radiusReductionTop, radiusReductionBottom);
90946		},
90947		setCenterPoint: function(leftMovement, rightMovement, topMovement, bottomMovement) {
90948			var me = this;
90949			var maxRight = me.width - rightMovement - me.drawingArea;
90950			var maxLeft = leftMovement + me.drawingArea;
90951			var maxTop = topMovement + me.drawingArea;
90952			var maxBottom = me.height - bottomMovement - me.drawingArea;
90953
90954			me.xCenter = Math.round(((maxLeft + maxRight) / 2) + me.left);
90955			me.yCenter = Math.round(((maxTop + maxBottom) / 2) + me.top);
90956		},
90957
90958		getIndexAngle: function(index) {
90959			var angleMultiplier = (Math.PI * 2) / getValueCount(this);
90960			var startAngle = this.chart.options && this.chart.options.startAngle ?
90961				this.chart.options.startAngle :
90962				0;
90963
90964			var startAngleRadians = startAngle * Math.PI * 2 / 360;
90965
90966			// Start from the top instead of right, so remove a quarter of the circle
90967			return index * angleMultiplier + startAngleRadians;
90968		},
90969		getDistanceFromCenterForValue: function(value) {
90970			var me = this;
90971
90972			if (value === null) {
90973				return 0; // null always in center
90974			}
90975
90976			// Take into account half font size + the yPadding of the top value
90977			var scalingFactor = me.drawingArea / (me.max - me.min);
90978			if (me.options.ticks.reverse) {
90979				return (me.max - value) * scalingFactor;
90980			}
90981			return (value - me.min) * scalingFactor;
90982		},
90983		getPointPosition: function(index, distanceFromCenter) {
90984			var me = this;
90985			var thisAngle = me.getIndexAngle(index) - (Math.PI / 2);
90986			return {
90987				x: Math.round(Math.cos(thisAngle) * distanceFromCenter) + me.xCenter,
90988				y: Math.round(Math.sin(thisAngle) * distanceFromCenter) + me.yCenter
90989			};
90990		},
90991		getPointPositionForValue: function(index, value) {
90992			return this.getPointPosition(index, this.getDistanceFromCenterForValue(value));
90993		},
90994
90995		getBasePosition: function() {
90996			var me = this;
90997			var min = me.min;
90998			var max = me.max;
90999
91000			return me.getPointPositionForValue(0,
91001				me.beginAtZero ? 0 :
91002				min < 0 && max < 0 ? max :
91003				min > 0 && max > 0 ? min :
91004				0);
91005		},
91006
91007		draw: function() {
91008			var me = this;
91009			var opts = me.options;
91010			var gridLineOpts = opts.gridLines;
91011			var tickOpts = opts.ticks;
91012			var valueOrDefault = helpers.valueOrDefault;
91013
91014			if (opts.display) {
91015				var ctx = me.ctx;
91016				var startAngle = this.getIndexAngle(0);
91017
91018				// Tick Font
91019				var tickFontSize = valueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);
91020				var tickFontStyle = valueOrDefault(tickOpts.fontStyle, globalDefaults.defaultFontStyle);
91021				var tickFontFamily = valueOrDefault(tickOpts.fontFamily, globalDefaults.defaultFontFamily);
91022				var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
91023
91024				helpers.each(me.ticks, function(label, index) {
91025					// Don't draw a centre value (if it is minimum)
91026					if (index > 0 || tickOpts.reverse) {
91027						var yCenterOffset = me.getDistanceFromCenterForValue(me.ticksAsNumbers[index]);
91028
91029						// Draw circular lines around the scale
91030						if (gridLineOpts.display && index !== 0) {
91031							drawRadiusLine(me, gridLineOpts, yCenterOffset, index);
91032						}
91033
91034						if (tickOpts.display) {
91035							var tickFontColor = valueOrDefault(tickOpts.fontColor, globalDefaults.defaultFontColor);
91036							ctx.font = tickLabelFont;
91037
91038							ctx.save();
91039							ctx.translate(me.xCenter, me.yCenter);
91040							ctx.rotate(startAngle);
91041
91042							if (tickOpts.showLabelBackdrop) {
91043								var labelWidth = ctx.measureText(label).width;
91044								ctx.fillStyle = tickOpts.backdropColor;
91045								ctx.fillRect(
91046									-labelWidth / 2 - tickOpts.backdropPaddingX,
91047									-yCenterOffset - tickFontSize / 2 - tickOpts.backdropPaddingY,
91048									labelWidth + tickOpts.backdropPaddingX * 2,
91049									tickFontSize + tickOpts.backdropPaddingY * 2
91050								);
91051							}
91052
91053							ctx.textAlign = 'center';
91054							ctx.textBaseline = 'middle';
91055							ctx.fillStyle = tickFontColor;
91056							ctx.fillText(label, 0, -yCenterOffset);
91057							ctx.restore();
91058						}
91059					}
91060				});
91061
91062				if (opts.angleLines.display || opts.pointLabels.display) {
91063					drawPointLabels(me);
91064				}
91065			}
91066		}
91067	});
91068
91069	scaleService.registerScaleType('radialLinear', LinearRadialScale, defaultConfig);
91070};
91071
91072},{"26":26,"34":34,"35":35,"46":46}],59:[function(require,module,exports){
91073/* global window: false */
91074'use strict';
91075
91076var moment = require(6);
91077moment = typeof moment === 'function' ? moment : window.moment;
91078
91079var defaults = require(26);
91080var helpers = require(46);
91081var Scale = require(33);
91082var scaleService = require(34);
91083
91084// Integer constants are from the ES6 spec.
91085var MIN_INTEGER = Number.MIN_SAFE_INTEGER || -9007199254740991;
91086var MAX_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991;
91087
91088var INTERVALS = {
91089	millisecond: {
91090		common: true,
91091		size: 1,
91092		steps: [1, 2, 5, 10, 20, 50, 100, 250, 500]
91093	},
91094	second: {
91095		common: true,
91096		size: 1000,
91097		steps: [1, 2, 5, 10, 15, 30]
91098	},
91099	minute: {
91100		common: true,
91101		size: 60000,
91102		steps: [1, 2, 5, 10, 15, 30]
91103	},
91104	hour: {
91105		common: true,
91106		size: 3600000,
91107		steps: [1, 2, 3, 6, 12]
91108	},
91109	day: {
91110		common: true,
91111		size: 86400000,
91112		steps: [1, 2, 5]
91113	},
91114	week: {
91115		common: false,
91116		size: 604800000,
91117		steps: [1, 2, 3, 4]
91118	},
91119	month: {
91120		common: true,
91121		size: 2.628e9,
91122		steps: [1, 2, 3]
91123	},
91124	quarter: {
91125		common: false,
91126		size: 7.884e9,
91127		steps: [1, 2, 3, 4]
91128	},
91129	year: {
91130		common: true,
91131		size: 3.154e10
91132	}
91133};
91134
91135var UNITS = Object.keys(INTERVALS);
91136
91137function sorter(a, b) {
91138	return a - b;
91139}
91140
91141function arrayUnique(items) {
91142	var hash = {};
91143	var out = [];
91144	var i, ilen, item;
91145
91146	for (i = 0, ilen = items.length; i < ilen; ++i) {
91147		item = items[i];
91148		if (!hash[item]) {
91149			hash[item] = true;
91150			out.push(item);
91151		}
91152	}
91153
91154	return out;
91155}
91156
91157/**
91158 * Returns an array of {time, pos} objects used to interpolate a specific `time` or position
91159 * (`pos`) on the scale, by searching entries before and after the requested value. `pos` is
91160 * a decimal between 0 and 1: 0 being the start of the scale (left or top) and 1 the other
91161 * extremity (left + width or top + height). Note that it would be more optimized to directly
91162 * store pre-computed pixels, but the scale dimensions are not guaranteed at the time we need
91163 * to create the lookup table. The table ALWAYS contains at least two items: min and max.
91164 *
91165 * @param {Number[]} timestamps - timestamps sorted from lowest to highest.
91166 * @param {String} distribution - If 'linear', timestamps will be spread linearly along the min
91167 * and max range, so basically, the table will contains only two items: {min, 0} and {max, 1}.
91168 * If 'series', timestamps will be positioned at the same distance from each other. In this
91169 * case, only timestamps that break the time linearity are registered, meaning that in the
91170 * best case, all timestamps are linear, the table contains only min and max.
91171 */
91172function buildLookupTable(timestamps, min, max, distribution) {
91173	if (distribution === 'linear' || !timestamps.length) {
91174		return [
91175			{time: min, pos: 0},
91176			{time: max, pos: 1}
91177		];
91178	}
91179
91180	var table = [];
91181	var items = [min];
91182	var i, ilen, prev, curr, next;
91183
91184	for (i = 0, ilen = timestamps.length; i < ilen; ++i) {
91185		curr = timestamps[i];
91186		if (curr > min && curr < max) {
91187			items.push(curr);
91188		}
91189	}
91190
91191	items.push(max);
91192
91193	for (i = 0, ilen = items.length; i < ilen; ++i) {
91194		next = items[i + 1];
91195		prev = items[i - 1];
91196		curr = items[i];
91197
91198		// only add points that breaks the scale linearity
91199		if (prev === undefined || next === undefined || Math.round((next + prev) / 2) !== curr) {
91200			table.push({time: curr, pos: i / (ilen - 1)});
91201		}
91202	}
91203
91204	return table;
91205}
91206
91207// @see adapted from http://www.anujgakhar.com/2014/03/01/binary-search-in-javascript/
91208function lookup(table, key, value) {
91209	var lo = 0;
91210	var hi = table.length - 1;
91211	var mid, i0, i1;
91212
91213	while (lo >= 0 && lo <= hi) {
91214		mid = (lo + hi) >> 1;
91215		i0 = table[mid - 1] || null;
91216		i1 = table[mid];
91217
91218		if (!i0) {
91219			// given value is outside table (before first item)
91220			return {lo: null, hi: i1};
91221		} else if (i1[key] < value) {
91222			lo = mid + 1;
91223		} else if (i0[key] > value) {
91224			hi = mid - 1;
91225		} else {
91226			return {lo: i0, hi: i1};
91227		}
91228	}
91229
91230	// given value is outside table (after last item)
91231	return {lo: i1, hi: null};
91232}
91233
91234/**
91235 * Linearly interpolates the given source `value` using the table items `skey` values and
91236 * returns the associated `tkey` value. For example, interpolate(table, 'time', 42, 'pos')
91237 * returns the position for a timestamp equal to 42. If value is out of bounds, values at
91238 * index [0, 1] or [n - 1, n] are used for the interpolation.
91239 */
91240function interpolate(table, skey, sval, tkey) {
91241	var range = lookup(table, skey, sval);
91242
91243	// Note: the lookup table ALWAYS contains at least 2 items (min and max)
91244	var prev = !range.lo ? table[0] : !range.hi ? table[table.length - 2] : range.lo;
91245	var next = !range.lo ? table[1] : !range.hi ? table[table.length - 1] : range.hi;
91246
91247	var span = next[skey] - prev[skey];
91248	var ratio = span ? (sval - prev[skey]) / span : 0;
91249	var offset = (next[tkey] - prev[tkey]) * ratio;
91250
91251	return prev[tkey] + offset;
91252}
91253
91254/**
91255 * Convert the given value to a moment object using the given time options.
91256 * @see http://momentjs.com/docs/#/parsing/
91257 */
91258function momentify(value, options) {
91259	var parser = options.parser;
91260	var format = options.parser || options.format;
91261
91262	if (typeof parser === 'function') {
91263		return parser(value);
91264	}
91265
91266	if (typeof value === 'string' && typeof format === 'string') {
91267		return moment(value, format);
91268	}
91269
91270	if (!(value instanceof moment)) {
91271		value = moment(value);
91272	}
91273
91274	if (value.isValid()) {
91275		return value;
91276	}
91277
91278	// Labels are in an incompatible moment format and no `parser` has been provided.
91279	// The user might still use the deprecated `format` option to convert his inputs.
91280	if (typeof format === 'function') {
91281		return format(value);
91282	}
91283
91284	return value;
91285}
91286
91287function parse(input, scale) {
91288	if (helpers.isNullOrUndef(input)) {
91289		return null;
91290	}
91291
91292	var options = scale.options.time;
91293	var value = momentify(scale.getRightValue(input), options);
91294	if (!value.isValid()) {
91295		return null;
91296	}
91297
91298	if (options.round) {
91299		value.startOf(options.round);
91300	}
91301
91302	return value.valueOf();
91303}
91304
91305/**
91306 * Returns the number of unit to skip to be able to display up to `capacity` number of ticks
91307 * in `unit` for the given `min` / `max` range and respecting the interval steps constraints.
91308 */
91309function determineStepSize(min, max, unit, capacity) {
91310	var range = max - min;
91311	var interval = INTERVALS[unit];
91312	var milliseconds = interval.size;
91313	var steps = interval.steps;
91314	var i, ilen, factor;
91315
91316	if (!steps) {
91317		return Math.ceil(range / (capacity * milliseconds));
91318	}
91319
91320	for (i = 0, ilen = steps.length; i < ilen; ++i) {
91321		factor = steps[i];
91322		if (Math.ceil(range / (milliseconds * factor)) <= capacity) {
91323			break;
91324		}
91325	}
91326
91327	return factor;
91328}
91329
91330/**
91331 * Figures out what unit results in an appropriate number of auto-generated ticks
91332 */
91333function determineUnitForAutoTicks(minUnit, min, max, capacity) {
91334	var ilen = UNITS.length;
91335	var i, interval, factor;
91336
91337	for (i = UNITS.indexOf(minUnit); i < ilen - 1; ++i) {
91338		interval = INTERVALS[UNITS[i]];
91339		factor = interval.steps ? interval.steps[interval.steps.length - 1] : MAX_INTEGER;
91340
91341		if (interval.common && Math.ceil((max - min) / (factor * interval.size)) <= capacity) {
91342			return UNITS[i];
91343		}
91344	}
91345
91346	return UNITS[ilen - 1];
91347}
91348
91349/**
91350 * Figures out what unit to format a set of ticks with
91351 */
91352function determineUnitForFormatting(ticks, minUnit, min, max) {
91353	var duration = moment.duration(moment(max).diff(moment(min)));
91354	var ilen = UNITS.length;
91355	var i, unit;
91356
91357	for (i = ilen - 1; i >= UNITS.indexOf(minUnit); i--) {
91358		unit = UNITS[i];
91359		if (INTERVALS[unit].common && duration.as(unit) >= ticks.length) {
91360			return unit;
91361		}
91362	}
91363
91364	return UNITS[minUnit ? UNITS.indexOf(minUnit) : 0];
91365}
91366
91367function determineMajorUnit(unit) {
91368	for (var i = UNITS.indexOf(unit) + 1, ilen = UNITS.length; i < ilen; ++i) {
91369		if (INTERVALS[UNITS[i]].common) {
91370			return UNITS[i];
91371		}
91372	}
91373}
91374
91375/**
91376 * Generates a maximum of `capacity` timestamps between min and max, rounded to the
91377 * `minor` unit, aligned on the `major` unit and using the given scale time `options`.
91378 * Important: this method can return ticks outside the min and max range, it's the
91379 * responsibility of the calling code to clamp values if needed.
91380 */
91381function generate(min, max, capacity, options) {
91382	var timeOpts = options.time;
91383	var minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min, max, capacity);
91384	var major = determineMajorUnit(minor);
91385	var stepSize = helpers.valueOrDefault(timeOpts.stepSize, timeOpts.unitStepSize);
91386	var weekday = minor === 'week' ? timeOpts.isoWeekday : false;
91387	var majorTicksEnabled = options.ticks.major.enabled;
91388	var interval = INTERVALS[minor];
91389	var first = moment(min);
91390	var last = moment(max);
91391	var ticks = [];
91392	var time;
91393
91394	if (!stepSize) {
91395		stepSize = determineStepSize(min, max, minor, capacity);
91396	}
91397
91398	// For 'week' unit, handle the first day of week option
91399	if (weekday) {
91400		first = first.isoWeekday(weekday);
91401		last = last.isoWeekday(weekday);
91402	}
91403
91404	// Align first/last ticks on unit
91405	first = first.startOf(weekday ? 'day' : minor);
91406	last = last.startOf(weekday ? 'day' : minor);
91407
91408	// Make sure that the last tick include max
91409	if (last < max) {
91410		last.add(1, minor);
91411	}
91412
91413	time = moment(first);
91414
91415	if (majorTicksEnabled && major && !weekday && !timeOpts.round) {
91416		// Align the first tick on the previous `minor` unit aligned on the `major` unit:
91417		// we first aligned time on the previous `major` unit then add the number of full
91418		// stepSize there is between first and the previous major time.
91419		time.startOf(major);
91420		time.add(~~((first - time) / (interval.size * stepSize)) * stepSize, minor);
91421	}
91422
91423	for (; time < last; time.add(stepSize, minor)) {
91424		ticks.push(+time);
91425	}
91426
91427	ticks.push(+time);
91428
91429	return ticks;
91430}
91431
91432/**
91433 * Returns the right and left offsets from edges in the form of {left, right}.
91434 * Offsets are added when the `offset` option is true.
91435 */
91436function computeOffsets(table, ticks, min, max, options) {
91437	var left = 0;
91438	var right = 0;
91439	var upper, lower;
91440
91441	if (options.offset && ticks.length) {
91442		if (!options.time.min) {
91443			upper = ticks.length > 1 ? ticks[1] : max;
91444			lower = ticks[0];
91445			left = (
91446				interpolate(table, 'time', upper, 'pos') -
91447				interpolate(table, 'time', lower, 'pos')
91448			) / 2;
91449		}
91450		if (!options.time.max) {
91451			upper = ticks[ticks.length - 1];
91452			lower = ticks.length > 1 ? ticks[ticks.length - 2] : min;
91453			right = (
91454				interpolate(table, 'time', upper, 'pos') -
91455				interpolate(table, 'time', lower, 'pos')
91456			) / 2;
91457		}
91458	}
91459
91460	return {left: left, right: right};
91461}
91462
91463function ticksFromTimestamps(values, majorUnit) {
91464	var ticks = [];
91465	var i, ilen, value, major;
91466
91467	for (i = 0, ilen = values.length; i < ilen; ++i) {
91468		value = values[i];
91469		major = majorUnit ? value === +moment(value).startOf(majorUnit) : false;
91470
91471		ticks.push({
91472			value: value,
91473			major: major
91474		});
91475	}
91476
91477	return ticks;
91478}
91479
91480function determineLabelFormat(data, timeOpts) {
91481	var i, momentDate, hasTime;
91482	var ilen = data.length;
91483
91484	// find the label with the most parts (milliseconds, minutes, etc.)
91485	// format all labels with the same level of detail as the most specific label
91486	for (i = 0; i < ilen; i++) {
91487		momentDate = momentify(data[i], timeOpts);
91488		if (momentDate.millisecond() !== 0) {
91489			return 'MMM D, YYYY h:mm:ss.SSS a';
91490		}
91491		if (momentDate.second() !== 0 || momentDate.minute() !== 0 || momentDate.hour() !== 0) {
91492			hasTime = true;
91493		}
91494	}
91495	if (hasTime) {
91496		return 'MMM D, YYYY h:mm:ss a';
91497	}
91498	return 'MMM D, YYYY';
91499}
91500
91501module.exports = function() {
91502
91503	var defaultConfig = {
91504		position: 'bottom',
91505
91506		/**
91507		 * Data distribution along the scale:
91508		 * - 'linear': data are spread according to their time (distances can vary),
91509		 * - 'series': data are spread at the same distance from each other.
91510		 * @see https://github.com/chartjs/Chart.js/pull/4507
91511		 * @since 2.7.0
91512		 */
91513		distribution: 'linear',
91514
91515		/**
91516		 * Scale boundary strategy (bypassed by min/max time options)
91517		 * - `data`: make sure data are fully visible, ticks outside are removed
91518		 * - `ticks`: make sure ticks are fully visible, data outside are truncated
91519		 * @see https://github.com/chartjs/Chart.js/pull/4556
91520		 * @since 2.7.0
91521		 */
91522		bounds: 'data',
91523
91524		time: {
91525			parser: false, // false == a pattern string from http://momentjs.com/docs/#/parsing/string-format/ or a custom callback that converts its argument to a moment
91526			format: false, // DEPRECATED false == date objects, moment object, callback or a pattern string from http://momentjs.com/docs/#/parsing/string-format/
91527			unit: false, // false == automatic or override with week, month, year, etc.
91528			round: false, // none, or override with week, month, year, etc.
91529			displayFormat: false, // DEPRECATED
91530			isoWeekday: false, // override week start day - see http://momentjs.com/docs/#/get-set/iso-weekday/
91531			minUnit: 'millisecond',
91532
91533			// defaults to unit's corresponding unitFormat below or override using pattern string from http://momentjs.com/docs/#/displaying/format/
91534			displayFormats: {
91535				millisecond: 'h:mm:ss.SSS a', // 11:20:01.123 AM,
91536				second: 'h:mm:ss a', // 11:20:01 AM
91537				minute: 'h:mm a', // 11:20 AM
91538				hour: 'hA', // 5PM
91539				day: 'MMM D', // Sep 4
91540				week: 'll', // Week 46, or maybe "[W]WW - YYYY" ?
91541				month: 'MMM YYYY', // Sept 2015
91542				quarter: '[Q]Q - YYYY', // Q3
91543				year: 'YYYY' // 2015
91544			},
91545		},
91546		ticks: {
91547			autoSkip: false,
91548
91549			/**
91550			 * Ticks generation input values:
91551			 * - 'auto': generates "optimal" ticks based on scale size and time options.
91552			 * - 'data': generates ticks from data (including labels from data {t|x|y} objects).
91553			 * - 'labels': generates ticks from user given `data.labels` values ONLY.
91554			 * @see https://github.com/chartjs/Chart.js/pull/4507
91555			 * @since 2.7.0
91556			 */
91557			source: 'auto',
91558
91559			major: {
91560				enabled: false
91561			}
91562		}
91563	};
91564
91565	var TimeScale = Scale.extend({
91566		initialize: function() {
91567			if (!moment) {
91568				throw new Error('Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com');
91569			}
91570
91571			this.mergeTicksOptions();
91572
91573			Scale.prototype.initialize.call(this);
91574		},
91575
91576		update: function() {
91577			var me = this;
91578			var options = me.options;
91579
91580			// DEPRECATIONS: output a message only one time per update
91581			if (options.time && options.time.format) {
91582				console.warn('options.time.format is deprecated and replaced by options.time.parser.');
91583			}
91584
91585			return Scale.prototype.update.apply(me, arguments);
91586		},
91587
91588		/**
91589		 * Allows data to be referenced via 't' attribute
91590		 */
91591		getRightValue: function(rawValue) {
91592			if (rawValue && rawValue.t !== undefined) {
91593				rawValue = rawValue.t;
91594			}
91595			return Scale.prototype.getRightValue.call(this, rawValue);
91596		},
91597
91598		determineDataLimits: function() {
91599			var me = this;
91600			var chart = me.chart;
91601			var timeOpts = me.options.time;
91602			var unit = timeOpts.unit || 'day';
91603			var min = MAX_INTEGER;
91604			var max = MIN_INTEGER;
91605			var timestamps = [];
91606			var datasets = [];
91607			var labels = [];
91608			var i, j, ilen, jlen, data, timestamp;
91609
91610			// Convert labels to timestamps
91611			for (i = 0, ilen = chart.data.labels.length; i < ilen; ++i) {
91612				labels.push(parse(chart.data.labels[i], me));
91613			}
91614
91615			// Convert data to timestamps
91616			for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
91617				if (chart.isDatasetVisible(i)) {
91618					data = chart.data.datasets[i].data;
91619
91620					// Let's consider that all data have the same format.
91621					if (helpers.isObject(data[0])) {
91622						datasets[i] = [];
91623
91624						for (j = 0, jlen = data.length; j < jlen; ++j) {
91625							timestamp = parse(data[j], me);
91626							timestamps.push(timestamp);
91627							datasets[i][j] = timestamp;
91628						}
91629					} else {
91630						timestamps.push.apply(timestamps, labels);
91631						datasets[i] = labels.slice(0);
91632					}
91633				} else {
91634					datasets[i] = [];
91635				}
91636			}
91637
91638			if (labels.length) {
91639				// Sort labels **after** data have been converted
91640				labels = arrayUnique(labels).sort(sorter);
91641				min = Math.min(min, labels[0]);
91642				max = Math.max(max, labels[labels.length - 1]);
91643			}
91644
91645			if (timestamps.length) {
91646				timestamps = arrayUnique(timestamps).sort(sorter);
91647				min = Math.min(min, timestamps[0]);
91648				max = Math.max(max, timestamps[timestamps.length - 1]);
91649			}
91650
91651			min = parse(timeOpts.min, me) || min;
91652			max = parse(timeOpts.max, me) || max;
91653
91654			// In case there is no valid min/max, set limits based on unit time option
91655			min = min === MAX_INTEGER ? +moment().startOf(unit) : min;
91656			max = max === MIN_INTEGER ? +moment().endOf(unit) + 1 : max;
91657
91658			// Make sure that max is strictly higher than min (required by the lookup table)
91659			me.min = Math.min(min, max);
91660			me.max = Math.max(min + 1, max);
91661
91662			// PRIVATE
91663			me._horizontal = me.isHorizontal();
91664			me._table = [];
91665			me._timestamps = {
91666				data: timestamps,
91667				datasets: datasets,
91668				labels: labels
91669			};
91670		},
91671
91672		buildTicks: function() {
91673			var me = this;
91674			var min = me.min;
91675			var max = me.max;
91676			var options = me.options;
91677			var timeOpts = options.time;
91678			var timestamps = [];
91679			var ticks = [];
91680			var i, ilen, timestamp;
91681
91682			switch (options.ticks.source) {
91683			case 'data':
91684				timestamps = me._timestamps.data;
91685				break;
91686			case 'labels':
91687				timestamps = me._timestamps.labels;
91688				break;
91689			case 'auto':
91690			default:
91691				timestamps = generate(min, max, me.getLabelCapacity(min), options);
91692			}
91693
91694			if (options.bounds === 'ticks' && timestamps.length) {
91695				min = timestamps[0];
91696				max = timestamps[timestamps.length - 1];
91697			}
91698
91699			// Enforce limits with user min/max options
91700			min = parse(timeOpts.min, me) || min;
91701			max = parse(timeOpts.max, me) || max;
91702
91703			// Remove ticks outside the min/max range
91704			for (i = 0, ilen = timestamps.length; i < ilen; ++i) {
91705				timestamp = timestamps[i];
91706				if (timestamp >= min && timestamp <= max) {
91707					ticks.push(timestamp);
91708				}
91709			}
91710
91711			me.min = min;
91712			me.max = max;
91713
91714			// PRIVATE
91715			me._unit = timeOpts.unit || determineUnitForFormatting(ticks, timeOpts.minUnit, me.min, me.max);
91716			me._majorUnit = determineMajorUnit(me._unit);
91717			me._table = buildLookupTable(me._timestamps.data, min, max, options.distribution);
91718			me._offsets = computeOffsets(me._table, ticks, min, max, options);
91719			me._labelFormat = determineLabelFormat(me._timestamps.data, timeOpts);
91720
91721			return ticksFromTimestamps(ticks, me._majorUnit);
91722		},
91723
91724		getLabelForIndex: function(index, datasetIndex) {
91725			var me = this;
91726			var data = me.chart.data;
91727			var timeOpts = me.options.time;
91728			var label = data.labels && index < data.labels.length ? data.labels[index] : '';
91729			var value = data.datasets[datasetIndex].data[index];
91730
91731			if (helpers.isObject(value)) {
91732				label = me.getRightValue(value);
91733			}
91734			if (timeOpts.tooltipFormat) {
91735				return momentify(label, timeOpts).format(timeOpts.tooltipFormat);
91736			}
91737			if (typeof label === 'string') {
91738				return label;
91739			}
91740
91741			return momentify(label, timeOpts).format(me._labelFormat);
91742		},
91743
91744		/**
91745		 * Function to format an individual tick mark
91746		 * @private
91747		 */
91748		tickFormatFunction: function(tick, index, ticks, formatOverride) {
91749			var me = this;
91750			var options = me.options;
91751			var time = tick.valueOf();
91752			var formats = options.time.displayFormats;
91753			var minorFormat = formats[me._unit];
91754			var majorUnit = me._majorUnit;
91755			var majorFormat = formats[majorUnit];
91756			var majorTime = tick.clone().startOf(majorUnit).valueOf();
91757			var majorTickOpts = options.ticks.major;
91758			var major = majorTickOpts.enabled && majorUnit && majorFormat && time === majorTime;
91759			var label = tick.format(formatOverride ? formatOverride : major ? majorFormat : minorFormat);
91760			var tickOpts = major ? majorTickOpts : options.ticks.minor;
91761			var formatter = helpers.valueOrDefault(tickOpts.callback, tickOpts.userCallback);
91762
91763			return formatter ? formatter(label, index, ticks) : label;
91764		},
91765
91766		convertTicksToLabels: function(ticks) {
91767			var labels = [];
91768			var i, ilen;
91769
91770			for (i = 0, ilen = ticks.length; i < ilen; ++i) {
91771				labels.push(this.tickFormatFunction(moment(ticks[i].value), i, ticks));
91772			}
91773
91774			return labels;
91775		},
91776
91777		/**
91778		 * @private
91779		 */
91780		getPixelForOffset: function(time) {
91781			var me = this;
91782			var size = me._horizontal ? me.width : me.height;
91783			var start = me._horizontal ? me.left : me.top;
91784			var pos = interpolate(me._table, 'time', time, 'pos');
91785
91786			return start + size * (me._offsets.left + pos) / (me._offsets.left + 1 + me._offsets.right);
91787		},
91788
91789		getPixelForValue: function(value, index, datasetIndex) {
91790			var me = this;
91791			var time = null;
91792
91793			if (index !== undefined && datasetIndex !== undefined) {
91794				time = me._timestamps.datasets[datasetIndex][index];
91795			}
91796
91797			if (time === null) {
91798				time = parse(value, me);
91799			}
91800
91801			if (time !== null) {
91802				return me.getPixelForOffset(time);
91803			}
91804		},
91805
91806		getPixelForTick: function(index) {
91807			var ticks = this.getTicks();
91808			return index >= 0 && index < ticks.length ?
91809				this.getPixelForOffset(ticks[index].value) :
91810				null;
91811		},
91812
91813		getValueForPixel: function(pixel) {
91814			var me = this;
91815			var size = me._horizontal ? me.width : me.height;
91816			var start = me._horizontal ? me.left : me.top;
91817			var pos = (size ? (pixel - start) / size : 0) * (me._offsets.left + 1 + me._offsets.left) - me._offsets.right;
91818			var time = interpolate(me._table, 'pos', pos, 'time');
91819
91820			return moment(time);
91821		},
91822
91823		/**
91824		 * Crude approximation of what the label width might be
91825		 * @private
91826		 */
91827		getLabelWidth: function(label) {
91828			var me = this;
91829			var ticksOpts = me.options.ticks;
91830			var tickLabelWidth = me.ctx.measureText(label).width;
91831			var angle = helpers.toRadians(ticksOpts.maxRotation);
91832			var cosRotation = Math.cos(angle);
91833			var sinRotation = Math.sin(angle);
91834			var tickFontSize = helpers.valueOrDefault(ticksOpts.fontSize, defaults.global.defaultFontSize);
91835
91836			return (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation);
91837		},
91838
91839		/**
91840		 * @private
91841		 */
91842		getLabelCapacity: function(exampleTime) {
91843			var me = this;
91844
91845			var formatOverride = me.options.time.displayFormats.millisecond;	// Pick the longest format for guestimation
91846
91847			var exampleLabel = me.tickFormatFunction(moment(exampleTime), 0, [], formatOverride);
91848			var tickLabelWidth = me.getLabelWidth(exampleLabel);
91849			var innerWidth = me.isHorizontal() ? me.width : me.height;
91850
91851			var capacity = Math.floor(innerWidth / tickLabelWidth);
91852			return capacity > 0 ? capacity : 1;
91853		}
91854	});
91855
91856	scaleService.registerScaleType('time', TimeScale, defaultConfig);
91857};
91858
91859},{"26":26,"33":33,"34":34,"46":46,"6":6}]},{},[7])(7)
91860});
91861
91862Chart.elements.Rectangle.prototype.draw = function() {    
91863    var ctx = this._chart.ctx;
91864    var vm = this._view;
91865    var left, right, top, bottom, signX, signY, borderSkipped, radius;
91866    var borderWidth = vm.borderWidth;
91867
91868    // Set Radius Here
91869    // If radius is large enough to cause drawing errors a max radius is imposed
91870    var cornerRadius = this._chart.options.barRadius ? this._chart.options.barRadius : 0;
91871
91872    if (!vm.horizontal) {
91873        // bar
91874        left = vm.x - vm.width / 2;
91875        right = vm.x + vm.width / 2;
91876
91877        if (vm.y > 2 * cornerRadius) {
91878        	top = vm.y - cornerRadius;        
91879        } else {
91880        	top = vm.y;        
91881        }
91882
91883        bottom = vm.base;
91884        signX = 1;
91885        signY = bottom > top? 1: -1;
91886        borderSkipped = vm.borderSkipped || 'bottom';
91887        //console.log(vm.base + '-' + vm.y);
91888    } else {
91889        // horizontal bar
91890        left = vm.base;
91891        right = vm.x;
91892        top = vm.y - vm.height / 2;
91893        bottom = vm.y + vm.height / 2;
91894        signX = right > left? 1: -1;
91895        signY = 1;
91896        borderSkipped = vm.borderSkipped || 'left';
91897    }
91898
91899    // Canvas doesn't allow us to stroke inside the width so we can
91900    // adjust the sizes to fit if we're setting a stroke on the line
91901    if (borderWidth) {
91902        // borderWidth shold be less than bar width and bar height.
91903        var barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom));
91904        borderWidth = borderWidth > barSize? barSize: borderWidth;
91905        var halfStroke = borderWidth / 2;
91906        // Adjust borderWidth when bar top position is near vm.base(zero).
91907        var borderLeft = left + (borderSkipped !== 'left'? halfStroke * signX: 0);
91908        var borderRight = right + (borderSkipped !== 'right'? -halfStroke * signX: 0);
91909        var borderTop = top + (borderSkipped !== 'top'? halfStroke * signY: 0);
91910        var borderBottom = bottom + (borderSkipped !== 'bottom'? -halfStroke * signY: 0);
91911        // not become a vertical line?
91912        if (borderLeft !== borderRight) {
91913            top = borderTop;
91914            bottom = borderBottom;
91915        }
91916        // not become a horizontal line?
91917        if (borderTop !== borderBottom) {
91918            left = borderLeft;
91919            right = borderRight;
91920        }
91921    }
91922
91923    ctx.beginPath();
91924    ctx.fillStyle = vm.backgroundColor;
91925    ctx.strokeStyle = vm.borderColor;
91926    ctx.lineWidth = borderWidth;
91927
91928    // Corner points, from bottom-left to bottom-right clockwise
91929    // | 1 2 |
91930    // | 0 3 |
91931    var corners = [
91932        [left, bottom],
91933        [left, top],
91934        [right, top],
91935        [right, bottom]
91936    ];
91937
91938    // Find first (starting) corner with fallback to 'bottom'
91939    var borders = ['bottom', 'left', 'top', 'right'];
91940    var startCorner = borders.indexOf(borderSkipped, 0);
91941    if (startCorner === -1) {
91942        startCorner = 0;
91943    }
91944
91945    function cornerAt(index) {
91946        return corners[(startCorner + index) % 4];
91947    }
91948
91949    // Draw rectangle from 'startCorner'
91950    var corner = cornerAt(0);
91951    ctx.moveTo(corner[0], corner[1]);
91952
91953    for (var i = 1; i < 4; i++) {
91954        corner = cornerAt(i);
91955        nextCornerId = i+1;
91956        if(nextCornerId == 4){
91957            nextCornerId = 0
91958        }
91959
91960        nextCorner = cornerAt(nextCornerId);
91961
91962        width = corners[2][0] - corners[1][0];
91963        height = corners[0][1] - corners[1][1];
91964        x = corners[1][0];
91965        y = corners[1][1];
91966        
91967        var radius = cornerRadius;
91968        
91969        // Fix radius being too large
91970        if(radius > height/2){
91971            radius = height/2;
91972        }if(radius > width/2){
91973            radius = width/2;
91974        }
91975
91976        ctx.moveTo(x + radius, y);
91977        ctx.lineTo(x + width - radius, y);
91978        ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
91979        ctx.lineTo(x + width, y + height - radius);
91980        ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
91981        ctx.lineTo(x + radius, y + height);
91982        ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
91983        ctx.lineTo(x, y + radius);
91984        ctx.quadraticCurveTo(x, y, x + radius, y);
91985    }
91986
91987    ctx.fill();
91988    if (borderWidth) {
91989        ctx.stroke();
91990    }
91991}; 
91992!function(a){"use strict";a.sessionTimeout=function(b){function c(){n||(a.ajax({type:i.ajaxType,url:i.keepAliveUrl,data:i.ajaxData}),n=!0,setTimeout(function(){n=!1},i.keepAliveInterval))}function d(){clearTimeout(g),(i.countdownMessage||i.countdownBar)&&f("session",!0),"function"==typeof i.onStart&&i.onStart(i),i.keepAlive&&c(),g=setTimeout(function(){"function"!=typeof i.onWarn?a("#session-timeout-dialog").modal("show"):i.onWarn(i),e()},i.warnAfter)}function e(){clearTimeout(g),a("#session-timeout-dialog").hasClass("in")||!i.countdownMessage&&!i.countdownBar||f("dialog",!0),g=setTimeout(function(){"function"!=typeof i.onRedir?window.location=i.redirUrl:i.onRedir(i)},i.redirAfter-i.warnAfter)}function f(b,c){clearTimeout(j.timer),"dialog"===b&&c?j.timeLeft=Math.floor((i.redirAfter-i.warnAfter)/1e3):"session"===b&&c&&(j.timeLeft=Math.floor(i.redirAfter/1e3)),i.countdownBar&&"dialog"===b?j.percentLeft=Math.floor(j.timeLeft/((i.redirAfter-i.warnAfter)/1e3)*100):i.countdownBar&&"session"===b&&(j.percentLeft=Math.floor(j.timeLeft/(i.redirAfter/1e3)*100));var d=a(".countdown-holder"),e=j.timeLeft>=0?j.timeLeft:0;if(i.countdownSmart){var g=Math.floor(e/60),h=e%60,k=g>0?g+"m":"";k.length>0&&(k+=" "),k+=h+"s",d.text(k)}else d.text(e+"s");i.countdownBar&&a(".countdown-bar").css("width",j.percentLeft+"%"),j.timeLeft=j.timeLeft-1,j.timer=setTimeout(function(){f(b)},1e3)}var g,h={title:"Your Session is About to Expire!",message:"Your session is about to expire.",logoutButton:"Logout",keepAliveButton:"Stay Connected",keepAliveUrl:"/keep-alive",ajaxType:"POST",ajaxData:"",redirUrl:"/timed-out",logoutUrl:"/log-out",warnAfter:9e5,redirAfter:12e5,keepAliveInterval:5e3,keepAlive:!0,ignoreUserActivity:!1,onStart:!1,onWarn:!1,onRedir:!1,countdownMessage:!1,countdownBar:!1,countdownSmart:!1},i=h,j={};if(b&&(i=a.extend(h,b)),i.warnAfter>=i.redirAfter)return console.error('Bootstrap-session-timeout plugin is miss-configured. Option "redirAfter" must be equal or greater than "warnAfter".'),!1;if("function"!=typeof i.onWarn){var k=i.countdownMessage?"<p>"+i.countdownMessage.replace(/{timer}/g,'<span class="countdown-holder"></span>')+"</p>":"",l=i.countdownBar?'<div class="progress">                   <div class="progress-bar progress-bar-striped countdown-bar active" role="progressbar" style="min-width: 15px; width: 100%;">                     <span class="countdown-holder"></span>                   </div>                 </div>':"";a("body").append('<div class="modal fade" id="session-timeout-dialog">               <div class="modal-dialog">                 <div class="modal-content">                   <div class="modal-header">                     <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>                     <h4 class="modal-title">'+i.title+'</h4>                   </div>                   <div class="modal-body">                     <p>'+i.message+"</p>                     "+k+"                     "+l+'                   </div>                   <div class="modal-footer">                     <button id="session-timeout-dialog-logout" type="button" class="btn btn-default">'+i.logoutButton+'</button>                     <button id="session-timeout-dialog-keepalive" type="button" class="btn btn-primary" data-dismiss="modal">'+i.keepAliveButton+"</button>                   </div>                 </div>               </div>              </div>"),a("#session-timeout-dialog-logout").on("click",function(){window.location=i.logoutUrl}),a("#session-timeout-dialog").on("hide.bs.modal",function(){d()})}if(!i.ignoreUserActivity){var m=[-1,-1];a(document).on("keyup mouseup mousemove touchend touchmove",function(b){if("mousemove"===b.type){if(b.clientX===m[0]&&b.clientY===m[1])return;m[0]=b.clientX,m[1]=b.clientY}d(),a("#session-timeout-dialog").length>0&&a("#session-timeout-dialog").data("bs.modal")&&a("#session-timeout-dialog").data("bs.modal").isShown&&(a("#session-timeout-dialog").modal("hide"),a("body").removeClass("modal-open"),a("div.modal-backdrop").remove())})}var n=!1;d()}}(jQuery);
91993/*! Idle Timer v1.1.0 2016-03-21 | https://github.com/thorst/jquery-idletimer | (c) 2016 Paul Irish | Licensed MIT */
91994!function(a){a.idleTimer=function(b,c){var d;"object"==typeof b?(d=b,b=null):"number"==typeof b&&(d={timeout:b},b=null),c=c||document,d=a.extend({idle:!1,timeout:3e4,events:"mousemove keydown wheel DOMMouseScroll mousewheel mousedown touchstart touchmove MSPointerDown MSPointerMove"},d);var e=a(c),f=e.data("idleTimerObj")||{},g=function(b){var d=a.data(c,"idleTimerObj")||{};d.idle=!d.idle,d.olddate=+new Date;var e=a.Event((d.idle?"idle":"active")+".idleTimer");a(c).trigger(e,[c,a.extend({},d),b])},h=function(b){var d=a.data(c,"idleTimerObj")||{};if(("storage"!==b.type||b.originalEvent.key===d.timerSyncId)&&null==d.remaining){if("mousemove"===b.type){if(b.pageX===d.pageX&&b.pageY===d.pageY)return;if("undefined"==typeof b.pageX&&"undefined"==typeof b.pageY)return;var e=+new Date-d.olddate;if(200>e)return}clearTimeout(d.tId),d.idle&&g(b),d.lastActive=+new Date,d.pageX=b.pageX,d.pageY=b.pageY,"storage"!==b.type&&d.timerSyncId&&"undefined"!=typeof localStorage&&localStorage.setItem(d.timerSyncId,d.lastActive),d.tId=setTimeout(g,d.timeout)}},i=function(){var b=a.data(c,"idleTimerObj")||{};b.idle=b.idleBackup,b.olddate=+new Date,b.lastActive=b.olddate,b.remaining=null,clearTimeout(b.tId),b.idle||(b.tId=setTimeout(g,b.timeout))},j=function(){var b=a.data(c,"idleTimerObj")||{};null==b.remaining&&(b.remaining=b.timeout-(+new Date-b.olddate),
91994clearTimeout(b.tId))},k=function(){var b=a.data(c,"idleTimerObj")||{};null!=b.remaining&&(b.idle||(b.tId=setTimeout(g,b.remaining)),b.remaining=null)},l=function(){var b=a.data(c,"idleTimerObj")||{};clearTimeout(b.tId),e.removeData("idleTimerObj"),e.off("._idleTimer")},m=function(){var b=a.data(c,"idleTimerObj")||{};if(b.idle)return 0;if(null!=b.remaining)return b.remaining;var d=b.timeout-(+new Date-b.lastActive);return 0>d&&(d=0),d};if(null===b&&"undefined"!=typeof f.idle)return i(),e;if(null===b);else{if(null!==b&&"undefined"==typeof f.idle)return!1;if("destroy"===b)return l(),e;if("pause"===b)return j(),e;if("resume"===b)return k(),e;if("reset"===b)return i(),e;if("getRemainingTime"===b)return m();if("getElapsedTime"===b)return+new Date-f.olddate;if("getLastActiveTime"===b)return f.lastActive;if("isIdle"===b)return f.idle}return e.on(a.trim((d.events+" ").split(" ").join("._idleTimer ")),function(a){h(a)}),d.timerSyncId&&a(window).bind("storage",h),f=a.extend({},{olddate:+new Date,lastActive:+new Date,idle:d.idle,idleBackup:d.idle,timeout:d.timeout,remaining:null,timerSyncId:d.timerSyncId,tId:null,pageX:null,pageY:null}),f.idle||(f.tId=setTimeout(g,f.timeout)),a.data(c,"idleTimerObj",f),e},a.fn.idleTimer=function(b){return this[0]?a.idleTimer(b,this[0]):this}}(jQuery);
91995/*!
91996Waypoints - 4.0.1
91997Copyright © 2011-2016 Caleb Troughton
91998Licensed under the MIT license.
91999https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
92000*/
92001(function() {
92002  'use strict'
92003
92004  var keyCounter = 0
92005  var allWaypoints = {}
92006
92007  /* http://imakewebthings.com/waypoints/api/waypoint */
92008  function Waypoint(options) {
92009    if (!options) {
92010      throw new Error('No options passed to Waypoint constructor')
92011    }
92012    if (!options.element) {
92013      throw new Error('No element option passed to Waypoint constructor')
92014    }
92015    if (!options.handler) {
92016      throw new Error('No handler option passed to Waypoint constructor')
92017    }
92018
92019    this.key = 'waypoint-' + keyCounter
92020    this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options)
92021    this.element = this.options.element
92022    this.adapter = new Waypoint.Adapter(this.element)
92023    this.callback = options.handler
92024    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
92025    this.enabled = this.options.enabled
92026    this.triggerPoint = null
92027    this.group = Waypoint.Group.findOrCreate({
92028      name: this.options.group,
92029      axis: this.axis
92030    })
92031    this.context = Waypoint.Context.findOrCreateByElement(this.options.context)
92032
92033    if (Waypoint.offsetAliases[this.options.offset]) {
92034      this.options.offset = Waypoint.offsetAliases[this.options.offset]
92035    }
92036    this.group.add(this)
92037    this.context.add(this)
92038    allWaypoints[this.key] = this
92039    keyCounter += 1
92040  }
92041
92042  /* Private */
92043  Waypoint.prototype.queueTrigger = function(direction) {
92044    this.group.queueTrigger(this, direction)
92045  }
92046
92047  /* Private */
92048  Waypoint.prototype.trigger = function(args) {
92049    if (!this.enabled) {
92050      return
92051    }
92052    if (this.callback) {
92053      this.callback.apply(this, args)
92054    }
92055  }
92056
92057  /* Public */
92058  /* http://imakewebthings.com/waypoints/api/destroy */
92059  Waypoint.prototype.destroy = function() {
92060    this.context.remove(this)
92061    this.group.remove(this)
92062    delete allWaypoints[this.key]
92063  }
92064
92065  /* Public */
92066  /* http://imakewebthings.com/waypoints/api/disable */
92067  Waypoint.prototype.disable = function() {
92068    this.enabled = false
92069    return this
92070  }
92071
92072  /* Public */
92073  /* http://imakewebthings.com/waypoints/api/enable */
92074  Waypoint.prototype.enable = function() {
92075    this.context.refresh()
92076    this.enabled = true
92077    return this
92078  }
92079
92080  /* Public */
92081  /* http://imakewebthings.com/waypoints/api/next */
92082  Waypoint.prototype.next = function() {
92083    return this.group.next(this)
92084  }
92085
92086  /* Public */
92087  /* http://imakewebthings.com/waypoints/api/previous */
92088  Waypoint.prototype.previous = function() {
92089    return this.group.previous(this)
92090  }
92091
92092  /* Private */
92093  Waypoint.invokeAll = function(method) {
92094    var allWaypointsArray = []
92095    for (var waypointKey in allWaypoints) {
92096      allWaypointsArray.push(allWaypoints[waypointKey])
92097    }
92098    for (var i = 0, end = allWaypointsArray.length; i < end; i++) {
92099      allWaypointsArray[i][method]()
92100    }
92101  }
92102
92103  /* Public */
92104  /* http://imakewebthings.com/waypoints/api/destroy-all */
92105  Waypoint.destroyAll = function() {
92106    Waypoint.invokeAll('destroy')
92107  }
92108
92109  /* Public */
92110  /* http://imakewebthings.com/waypoints/api/disable-all */
92111  Waypoint.disableAll = function() {
92112    Waypoint.invokeAll('disable')
92113  }
92114
92115  /* Public */
92116  /* http://imakewebthings.com/waypoints/api/enable-all */
92117  Waypoint.enableAll = function() {
92118    Waypoint.Context.refreshAll()
92119    for (var waypointKey in allWaypoints) {
92120      allWaypoints[waypointKey].enabled = true
92121    }
92122    return this
92123  }
92124
92125  /* Public */
92126  /* http://imakewebthings.com/waypoints/api/refresh-all */
92127  Waypoint.refreshAll = function() {
92128    Waypoint.Context.refreshAll()
92129  }
92130
92131  /* Public */
92132  /* http://imakewebthings.com/waypoints/api/viewport-height */
92133  Waypoint.viewportHeight = function() {
92134    return window.innerHeight || document.documentElement.clientHeight
92135  }
92136
92137  /* Public */
92138  /* http://imakewebthings.com/waypoints/api/viewport-width */
92139  Waypoint.viewportWidth = function() {
92140    return document.documentElement.clientWidth
92141  }
92142
92143  Waypoint.adapters = []
92144
92145  Waypoint.defaults = {
92146    context: window,
92147    continuous: true,
92148    enabled: true,
92149    group: 'default',
92150    horizontal: false,
92151    offset: 0
92152  }
92153
92154  Waypoint.offsetAliases = {
92155    'bottom-in-view': function() {
92156      return this.context.innerHeight() - this.adapter.outerHeight()
92157    },
92158    'right-in-view': function() {
92159      return this.context.innerWidth() - this.adapter.outerWidth()
92160    }
92161  }
92162
92163  window.Waypoint = Waypoint
92164}())
92165;(function() {
92166  'use strict'
92167
92168  function requestAnimationFrameShim(callback) {
92169    window.setTimeout(callback, 1000 / 60)
92170  }
92171
92172  var keyCounter = 0
92173  var contexts = {}
92174  var Waypoint = window.Waypoint
92175  var oldWindowLoad = window.onload
92176
92177  /* http://imakewebthings.com/waypoints/api/context */
92178  function Context(element) {
92179    this.element = element
92180    this.Adapter = Waypoint.Adapter
92181    this.adapter = new this.Adapter(element)
92182    this.key = 'waypoint-context-' + keyCounter
92183    this.didScroll = false
92184    this.didResize = false
92185    this.oldScroll = {
92186      x: this.adapter.scrollLeft(),
92187      y: this.adapter.scrollTop()
92188    }
92189    this.waypoints = {
92190      vertical: {},
92191      horizontal: {}
92192    }
92193
92194    element.waypointContextKey = this.key
92195    contexts[element.waypointContextKey] = this
92196    keyCounter += 1
92197    if (!Waypoint.windowContext) {
92198      Waypoint.windowContext = true
92199      Waypoint.windowContext = new Context(window)
92200    }
92201
92202    this.createThrottledScrollHandler()
92203    this.createThrottledResizeHandler()
92204  }
92205
92206  /* Private */
92207  Context.prototype.add = function(waypoint) {
92208    var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical'
92209    this.waypoints[axis][waypoint.key] = waypoint
92210    this.refresh()
92211  }
92212
92213  /* Private */
92214  Context.prototype.checkEmpty = function() {
92215    var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal)
92216    var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical)
92217    var isWindow = this.element == this.element.window
92218    if (horizontalEmpty && verticalEmpty && !isWindow) {
92219      this.adapter.off('.waypoints')
92220      delete contexts[this.key]
92221    }
92222  }
92223
92224  /* Private */
92225  Context.prototype.createThrottledResizeHandler = function() {
92226    var self = this
92227
92228    function resizeHandler() {
92229      self.handleResize()
92230      self.didResize = false
92231    }
92232
92233    this.adapter.on('resize.waypoints', function() {
92234      if (!self.didResize) {
92235        self.didResize = true
92236        Waypoint.requestAnimationFrame(resizeHandler)
92237      }
92238    })
92239  }
92240
92241  /* Private */
92242  Context.prototype.createThrottledScrollHandler = function() {
92243    var self = this
92244    function scrollHandler() {
92245      self.handleScroll()
92246      self.didScroll = false
92247    }
92248
92249    this.adapter.on('scroll.waypoints', function() {
92250      if (!self.didScroll || Waypoint.isTouch) {
92251        self.didScroll = true
92252        Waypoint.requestAnimationFrame(scrollHandler)
92253      }
92254    })
92255  }
92256
92257  /* Private */
92258  Context.prototype.handleResize = function() {
92259    Waypoint.Context.refreshAll()
92260  }
92261
92262  /* Private */
92263  Context.prototype.handleScroll = function() {
92264    var triggeredGroups = {}
92265    var axes = {
92266      horizontal: {
92267        newScroll: this.adapter.scrollLeft(),
92268        oldScroll: this.oldScroll.x,
92269        forward: 'right',
92270        backward: 'left'
92271      },
92272      vertical: {
92273        newScroll: this.adapter.scrollTop(),
92274        oldScroll: this.oldScroll.y,
92275        forward: 'down',
92276        backward: 'up'
92277      }
92278    }
92279
92280    for (var axisKey in axes) {
92281      var axis = axes[axisKey]
92282      var isForward = axis.newScroll > axis.oldScroll
92283      var direction = isForward ? axis.forward : axis.backward
92284
92285      for (var waypointKey in this.waypoints[axisKey]) {
92286        var waypoint = this.waypoints[axisKey][waypointKey]
92287        if (waypoint.triggerPoint === null) {
92288          continue
92289        }
92290        var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint
92291        var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint
92292        var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint
92293        var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint
92294        if (crossedForward || crossedBackward) {
92295          waypoint.queueTrigger(direction)
92296          triggeredGroups[waypoint.group.id] = waypoint.group
92297        }
92298      }
92299    }
92300
92301    for (var groupKey in triggeredGroups) {
92302      triggeredGroups[groupKey].flushTriggers()
92303    }
92304
92305    this.oldScroll = {
92306      x: axes.horizontal.newScroll,
92307      y: axes.vertical.newScroll
92308    }
92309  }
92310
92311  /* Private */
92312  Context.prototype.innerHeight = function() {
92313    /*eslint-disable eqeqeq */
92314    if (this.element == this.element.window) {
92315      return Waypoint.viewportHeight()
92316    }
92317    /*eslint-enable eqeqeq */
92318    return this.adapter.innerHeight()
92319  }
92320
92321  /* Private */
92322  Context.prototype.remove = function(waypoint) {
92323    delete this.waypoints[waypoint.axis][waypoint.key]
92324    this.checkEmpty()
92325  }
92326
92327  /* Private */
92328  Context.prototype.innerWidth = function() {
92329    /*eslint-disable eqeqeq */
92330    if (this.element == this.element.window) {
92331      return Waypoint.viewportWidth()
92332    }
92333    /*eslint-enable eqeqeq */
92334    return this.adapter.innerWidth()
92335  }
92336
92337  /* Public */
92338  /* http://imakewebthings.com/waypoints/api/context-destroy */
92339  Context.prototype.destroy = function() {
92340    var allWaypoints = []
92341    for (var axis in this.waypoints) {
92342      for (var waypointKey in this.waypoints[axis]) {
92343        allWaypoints.push(this.waypoints[axis][waypointKey])
92344      }
92345    }
92346    for (var i = 0, end = allWaypoints.length; i < end; i++) {
92347      allWaypoints[i].destroy()
92348    }
92349  }
92350
92351  /* Public */
92352  /* http://imakewebthings.com/waypoints/api/context-refresh */
92353  Context.prototype.refresh = function() {
92354    /*eslint-disable eqeqeq */
92355    var isWindow = this.element == this.element.window
92356    /*eslint-enable eqeqeq */
92357    var contextOffset = isWindow ? undefined : this.adapter.offset()
92358    var triggeredGroups = {}
92359    var axes
92360
92361    this.handleScroll()
92362    axes = {
92363      horizontal: {
92364        contextOffset: isWindow ? 0 : contextOffset.left,
92365        contextScroll: isWindow ? 0 : this.oldScroll.x,
92366        contextDimension: this.innerWidth(),
92367        oldScroll: this.oldScroll.x,
92368        forward: 'right',
92369        backward: 'left',
92370        offsetProp: 'left'
92371      },
92372      vertical: {
92373        contextOffset: isWindow ? 0 : contextOffset.top,
92374        contextScroll: isWindow ? 0 : this.oldScroll.y,
92375        contextDimension: this.innerHeight(),
92376        oldScroll: this.oldScroll.y,
92377        forward: 'down',
92378        backward: 'up',
92379        offsetProp: 'top'
92380      }
92381    }
92382
92383    for (var axisKey in axes) {
92384      var axis = axes[axisKey]
92385      for (var waypointKey in this.waypoints[axisKey]) {
92386        var waypoint = this.waypoints[axisKey][waypointKey]
92387        var adjustment = waypoint.options.offset
92388        var oldTriggerPoint = waypoint.triggerPoint
92389        var elementOffset = 0
92390        var freshWaypoint = oldTriggerPoint == null
92391        var contextModifier, wasBeforeScroll, nowAfterScroll
92392        var triggeredBackward, triggeredForward
92393
92394        if (waypoint.element !== waypoint.element.window) {
92395          elementOffset = waypoint.adapter.offset()[axis.offsetProp]
92396        }
92397
92398        if (typeof adjustment === 'function') {
92399          adjustment = adjustment.apply(waypoint)
92400        }
92401        else if (typeof adjustment === 'string') {
92402          adjustment = parseFloat(adjustment)
92403          if (waypoint.options.offset.indexOf('%') > - 1) {
92404            adjustment = Math.ceil(axis.contextDimension * adjustment / 100)
92405          }
92406        }
92407
92408        contextModifier = axis.contextScroll - axis.contextOffset
92409        waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment)
92410        wasBeforeScroll = oldTriggerPoint < axis.oldScroll
92411        nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll
92412        triggeredBackward = wasBeforeScroll && nowAfterScroll
92413        triggeredForward = !wasBeforeScroll && !nowAfterScroll
92414
92415        if (!freshWaypoint && triggeredBackward) {
92416          waypoint.queueTrigger(axis.backward)
92417          triggeredGroups[waypoint.group.id] = waypoint.group
92418        }
92419        else if (!freshWaypoint && triggeredForward) {
92420          waypoint.queueTrigger(axis.forward)
92421          triggeredGroups[waypoint.group.id] = waypoint.group
92422        }
92423        else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) {
92424          waypoint.queueTrigger(axis.forward)
92425          triggeredGroups[waypoint.group.id] = waypoint.group
92426        }
92427      }
92428    }
92429
92430    Waypoint.requestAnimationFrame(function() {
92431      for (var groupKey in triggeredGroups) {
92432        triggeredGroups[groupKey].flushTriggers()
92433      }
92434    })
92435
92436    return this
92437  }
92438
92439  /* Private */
92440  Context.findOrCreateByElement = function(element) {
92441    return Context.findByElement(element) || new Context(element)
92442  }
92443
92444  /* Private */
92445  Context.refreshAll = function() {
92446    for (var contextId in contexts) {
92447      contexts[contextId].refresh()
92448    }
92449  }
92450
92451  /* Public */
92452  /* http://imakewebthings.com/waypoints/api/context-find-by-element */
92453  Context.findByElement = function(element) {
92454    return contexts[element.waypointContextKey]
92455  }
92456
92457  window.onload = function() {
92458    if (oldWindowLoad) {
92459      oldWindowLoad()
92460    }
92461    Context.refreshAll()
92462  }
92463
92464
92465  Waypoint.requestAnimationFrame = function(callback) {
92466    var requestFn = window.requestAnimationFrame ||
92467      window.mozRequestAnimationFrame ||
92468      window.webkitRequestAnimationFrame ||
92469      requestAnimationFrameShim
92470    requestFn.call(window, callback)
92471  }
92472  Waypoint.Context = Context
92473}())
92474;(function() {
92475  'use strict'
92476
92477  function byTriggerPoint(a, b) {
92478    return a.triggerPoint - b.triggerPoint
92479  }
92480
92481  function byReverseTriggerPoint(a, b) {
92482    return b.triggerPoint - a.triggerPoint
92483  }
92484
92485  var groups = {
92486    vertical: {},
92487    horizontal: {}
92488  }
92489  var Waypoint = window.Waypoint
92490
92491  /* http://imakewebthings.com/waypoints/api/group */
92492  function Group(options) {
92493    this.name = options.name
92494    this.axis = options.axis
92495    this.id = this.name + '-' + this.axis
92496    this.waypoints = []
92497    this.clearTriggerQueues()
92498    groups[this.axis][this.name] = this
92499  }
92500
92501  /* Private */
92502  Group.prototype.add = function(waypoint) {
92503    this.waypoints.push(waypoint)
92504  }
92505
92506  /* Private */
92507  Group.prototype.clearTriggerQueues = function() {
92508    this.triggerQueues = {
92509      up: [],
92510      down: [],
92511      left: [],
92512      right: []
92513    }
92514  }
92515
92516  /* Private */
92517  Group.prototype.flushTriggers = function() {
92518    for (var direction in this.triggerQueues) {
92519      var waypoints = this.triggerQueues[direction]
92520      var reverse = direction === 'up' || direction === 'left'
92521      waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint)
92522      for (var i = 0, end = waypoints.length; i < end; i += 1) {
92523        var waypoint = waypoints[i]
92524        if (waypoint.options.continuous || i === waypoints.length - 1) {
92525          waypoint.trigger([direction])
92526        }
92527      }
92528    }
92529    this.clearTriggerQueues()
92530  }
92531
92532  /* Private */
92533  Group.prototype.next = function(waypoint) {
92534    this.waypoints.sort(byTriggerPoint)
92535    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
92536    var isLast = index === this.waypoints.length - 1
92537    return isLast ? null : this.waypoints[index + 1]
92538  }
92539
92540  /* Private */
92541  Group.prototype.previous = function(waypoint) {
92542    this.waypoints.sort(byTriggerPoint)
92543    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
92544    return index ? this.waypoints[index - 1] : null
92545  }
92546
92547  /* Private */
92548  Group.prototype.queueTrigger = function(waypoint, direction) {
92549    this.triggerQueues[direction].push(waypoint)
92550  }
92551
92552  /* Private */
92553  Group.prototype.remove = function(waypoint) {
92554    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
92555    if (index > -1) {
92556      this.waypoints.splice(index, 1)
92557    }
92558  }
92559
92560  /* Public */
92561  /* http://imakewebthings.com/waypoints/api/first */
92562  Group.prototype.first = function() {
92563    return this.waypoints[0]
92564  }
92565
92566  /* Public */
92567  /* http://imakewebthings.com/waypoints/api/last */
92568  Group.prototype.last = function() {
92569    return this.waypoints[this.waypoints.length - 1]
92570  }
92571
92572  /* Private */
92573  Group.findOrCreate = function(options) {
92574    return groups[options.axis][options.name] || new Group(options)
92575  }
92576
92577  Waypoint.Group = Group
92578}())
92579;(function() {
92580  'use strict'
92581
92582  var $ = window.jQuery
92583  var Waypoint = window.Waypoint
92584
92585  function JQueryAdapter(element) {
92586    this.$element = $(element)
92587  }
92588
92589  $.each([
92590    'innerHeight',
92591    'innerWidth',
92592    'off',
92593    'offset',
92594    'on',
92595    'outerHeight',
92596    'outerWidth',
92597    'scrollLeft',
92598    'scrollTop'
92599  ], function(i, method) {
92600    JQueryAdapter.prototype[method] = function() {
92601      var args = Array.prototype.slice.call(arguments)
92602      return this.$element[method].apply(this.$element, args)
92603    }
92604  })
92605
92606  $.each([
92607    'extend',
92608    'inArray',
92609    'isEmptyObject'
92610  ], function(i, method) {
92611    JQueryAdapter[method] = $[method]
92612  })
92613
92614  Waypoint.adapters.push({
92615    name: 'jquery',
92616    Adapter: JQueryAdapter
92617  })
92618  Waypoint.Adapter = JQueryAdapter
92619}())
92620;(function() {
92621  'use strict'
92622
92623  var Waypoint = window.Waypoint
92624
92625  function createExtension(framework) {
92626    return function() {
92627      var waypoints = []
92628      var overrides = arguments[0]
92629
92630      if (framework.isFunction(arguments[0])) {
92631        overrides = framework.extend({}, arguments[1])
92632        overrides.handler = arguments[0]
92633      }
92634
92635      this.each(function() {
92636        var options = framework.extend({}, overrides, {
92637          element: this
92638        })
92639        if (typeof options.context === 'string') {
92640          options.context = framework(this).closest(options.context)[0]
92641        }
92642        waypoints.push(new Waypoint(options))
92643      })
92644
92645      return waypoints
92646    }
92647  }
92648
92649  if (window.jQuery) {
92650    window.jQuery.fn.waypoint = createExtension(window.jQuery)
92651  }
92652  if (window.Zepto) {
92653    window.Zepto.fn.waypoint = createExtension(window.Zepto)
92654  }
92655}())
92656;
92657/*!
92658* jquery.counterup.js 1.0
92659*
92660* Copyright 2013, Benjamin Intal http://gambit.ph @bfintal
92661* Released under the GPL v2 License
92662*
92663* Date: Nov 26, 2013
92664*/
92665!function(t){"use strict";t.fn.counterUp=function(e){var u=t.extend({time:400,delay:10},e);return this.each(function(){var e=t(this),n=u,a=function(){var t=n.time/n.delay,u=e.attr("data-value"),a=[u],r=/[0-9]+,[0-9]+/.test(u);u=u.replace(/,/g,"");for(var o=(/^[0-9]+$/.test(u),/^[0-9]+\.[0-9]+$/.test(u)),c=o?(u.split(".")[1]||[]).length:0,d=t;d>=1;d--){var s=parseInt(u/t*d);if(o&&(s=parseFloat(u/t*d).toFixed(c)),r)for(;/(\d+)(\d{3})/.test(s.toString());)s=s.toString().replace(/(\d+)(\d{3})/,"$1,$2");a.unshift(s)}e.data("counterup-nums",a),e.text("0");var i=function(){e.data("counterup-nums")&&(e.text(e.data("counterup-nums").shift()),e.data("counterup-nums").length?setTimeout(e.data("counterup-func"),n.delay):(delete e.data("counterup-nums"),e.data("counterup-nums",null),e.data("counterup-func",null)))};e.data("counterup-func",i),setTimeout(e.data("counterup-func"),n.delay)};e.waypoint(a,{offset:"100%",triggerOnce:!0})})}}(jQuery);
92666
92667(function(t){function z(){for(var a=0;a<g.length;a++)g[a][0](g[a][1]);g=[];m=!1}function n(a,b){g.push([a,b]);m||(m=!0,A(z,0))}function B(a,b){function c(a){p(b,a)}function h(a){k(b,a)}try{a(c,h)}catch(d){h(d)}}function u(a){var b=a.owner,c=b.state_,b=b.data_,h=a[c];a=a.then;if("function"===typeof h){c=l;try{b=h(b)}catch(d){k(a,d)}}v(a,b)||(c===l&&p(a,b),c===q&&k(a,b))}function v(a,b){var c;try{if(a===b)throw new TypeError("A promises callback cannot return that same promise.");if(b&&("function"===
92668typeof b||"object"===typeof b)){var h=b.then;if("function"===typeof h)return h.call(b,function(d){c||(c=!0,b!==d?p(a,d):w(a,d))},function(b){c||(c=!0,k(a,b))}),!0}}catch(d){return c||k(a,d),!0}return!1}function p(a,b){a!==b&&v(a,b)||w(a,b)}function w(a,b){a.state_===r&&(a.state_=x,a.data_=b,n(C,a))}function k(a,b){a.state_===r&&(a.state_=x,a.data_=b,n(D,a))}function y(a){var b=a.then_;a.then_=void 0;for(a=0;a<b.length;a++)u(b[a])}function C(a){a.state_=l;y(a)}function D(a){a.state_=q;y(a)}function e(a){if("function"!==
92669typeof a)throw new TypeError("Promise constructor takes a function argument");if(!1===this instanceof e)throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object c
92669onstructor cannot be called as a function.");this.then_=[];B(a,this)}var f=t.Promise,s=f&&"resolve"in f&&"reject"in f&&"all"in f&&"race"in f&&function(){var a;new f(function(b){a=b});return"function"===typeof a}();"undefined"!==typeof exports&&exports?(exports.Promise=s?f:e,exports.Polyfill=e):"function"==
92670typeof define&&define.amd?define(function(){return s?f:e}):s||(t.Promise=e);var r="pending",x="sealed",l="fulfilled",q="rejected",E=function(){},A="undefined"!==typeof setImmediate?setImmediate:setTimeout,g=[],m;e.prototype={constructor:e,state_:r,then_:null,data_:void 0,then:function(a,b){var c={owner:this,then:new this.constructor(E),fulfilled:a,rejected:b};this.state_===l||this.state_===q?n(u,c):this.then_.push(c);return c.then},"catch":function(a){return this.then(null,a)}};e.all=function(a){if("[object Array]"!==
92671Object.prototype.toString.call(a))throw new TypeError("You must pass an array to Promise.all().");return new this(function(b,c){function h(a){e++;return function(c){d[a]=c;--e||b(d)}}for(var d=[],e=0,f=0,g;f<a.length;f++)(g=a[f])&&"function"===typeof g.then?g.then(h(f),c):d[f]=g;e||b(d)})};e.race=function(a){if("[object Array]"!==Object.prototype.toString.call(a))throw new TypeError("You must pass an array to Promise.race().");return new this(function(b,c){for(var e=0,d;e<a.length;e++)(d=a[e])&&"function"===
92672typeof d.then?d.then(b,c):b(d)})};e.resolve=function(a){return a&&"object"===typeof a&&a.constructor===this?a:new this(function(b){b(a)})};e.reject=function(a){return new this(function(b,c){c(a)})}})("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this);
92673
92674!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Sweetalert2=t()}(this,function(){"use strict";function q(e){return(q="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function a(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}function i(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}function r(){return(r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e}).apply(this,arguments)}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&u(e,t)}function c(e){return(c=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function u(e,t){return(u=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function l(e,t,n){return(l=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}()?Reflect.construct:function(e,t,n){var o=[null];o.push.apply(o,t);var i=new(Function.bind.apply(e,o));return n&&u(i,n.prototype),i}).apply(null,arguments)}function d(e,t){return!t||"object"!=typeof t&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}function p(e,t,n){return(p="undefined"!=typeof Reflect&&Reflect.get?Reflect.get:function(e,t,n){var o=function(e,t){for(;!Object.prototype.hasOwnProperty.call(e,t)&&null!==(e=c(e)););return e}(e,t);if(o){var i=Object.getOwnPropertyDescriptor(o,t);return i.get?i.get.call(n):i.value}})(e,t,n||e)}var t="SweetAlert2:",f=function(e){return Array.prototype.slice.call(e)},R=function(e){console.warn("".concat(t," ").concat(e))},I=function(e){console.error("".concat(t," ").concat(e))},n=[],m=function(e){-1===n.indexOf(e)&&(n.push(e),R(e))},H=function(e){return"function"==typeof e?e():e},D=function(e){return e&&Promise.resolve(e)===e},e=Object.freeze({cancel:"cancel",backdrop:"overlay",close:"close",esc:"esc",timer:"timer"}),h=function(e){var t={};for(var n in e)t[e[n]]="swal2-"+e[n];return t},_=h(["container","shown","height-auto","iosfix","popup","modal","no-backdrop","toast","toast-shown","toast-column","fade","show","hide","noanimation","close","title","header","content","actions","confirm","cancel","footer","icon","icon-text","image","input","file","range","select","radio","checkbox","label","textarea","inputerror","validation-message","progresssteps","activeprogressstep","progresscircle","progressline","loading","styled","top","top-start","to
92674p-end","top-left","top-right","center","center-start","center-end","center-left","center-right","bottom","bottom-start","bottom-end","bottom-left","bottom-right","grow-row","grow-column","grow-fullscreen","rtl"]),g=h(["success","warning","info","question","error"]),b={previousBodyPadding:null},v=function(e,t){return e.classList.contains(t)},N=function(e){if(e.focus(),"file"!==e.type){var t=e.value;e.value="",e.value=t}},y=function(e,t,n){e&&t&&("string"==typeof t&&(t=t.split(/\s+/).filter(Boolean)),t.forEach(function(t){e.forEach?e.forEach(function(e){n?e.classList.add(t):e.classList.remove(t)}):n?e.classList.add(t):e.classList.remove(t)}))},z=function(e,t){y(e,t,!0)},W=function(e,t){y(e,t,!1)},U=function(e,t){for(var n=0;n<e.childNodes.length;n++)if(v(e.childNodes[n],t))return e.childNodes[n]},K=function(e){e.style.opacity="",e.style.display=e.id===_.content?"block":"flex"},F=function(e){e.style.opacity="",e.style.display="none"},Z=function(e){return e&&(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w=function(){return document.body.querySelector("."+_.container)},C=function(e){var t=w();return t?t.querySelector("."+e):null},k=function(){return C(_.popup)},x=function(){var e=k();return f(e.querySelectorAll("."+_.icon))},A=function(){return C(_.title)},B=function(){return C(_.content)},S=function(){return C(_.image)},P=function(){return C(_.progresssteps)},E=function(){return C(_["validation-message"])},L=function(){return C(_.confirm)},O=function(){return C(_.cancel)},Q=function(){return C(_.actions)},Y=function(){return C(_.footer)},$=function(){return C(_.close)},J=function(){var e=f(k().querySelectorAll('[tabindex]:not([tabindex="-1"]):not([tabindex="0"])')).sort(function(e,t){return e=parseInt(e.getAttribute("tabindex")),(t=parseInt(t.getAttribute("tabindex")))<e?1:e<t?-1:0}),t=f(k().querySelectorAll('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable], audio[controls], video[controls]')).filter(function(e){return"-1"!==e.getAttribute("tabindex")});return function(e){for(var t=[],n=0;n<e.length;n++)-1===t.indexOf(e[n])&&t.push(e[n]);return t}(e.concat(t)).filter(function(e){return Z(e)})},T=function(){return!M()&&!document.body.classList.contains(_["no-backdrop"])},M=function(){return document.body.classList.contains(_["toast-shown"])},j=function(){return"undefined"==typeof window||"undefined"==typeof document},V='\n <div aria-labelledby="'.concat(_.title,'" aria-describedby="').concat(_.content,'" class="').concat(_.popup,'" tabindex="-1">\n   <div class="').concat(_.header,'">\n     <ul class="').concat(_.progresssteps,'"></ul>\n     <div class="').concat(_.icon," ").concat(g.error,'">\n       <span class="swal2-x-mark"><span class="swal2-x-mark-line-left"></span><span class="swal2-x-mark-line-right"></span></span>\n     </div>\n     <div class="').concat(_.icon," ").concat(g.question,'">\n       <span class="').concat(_["icon-text"],'">?</span>\n      </div>\n     <div class="').concat(_.icon," ").concat(g.warning,'">\n       <span class="').concat(_["icon-text"],'">!</span>\n      </div>\n     <div class="').concat(_.icon," ").concat(g.info,'">\n       <span class="').concat(_["icon-text"],'">i</span>\n      </div>\n     <div class="').concat(_.icon," ").concat(g.success,'">\n       <div class="swal2-success-circular-line-left"></div>\n       <span class="swal2-success-line-tip"></span> <span class="swal2-success-line-long"></span>\n       <div class="swal2-success-ring"></div> <div class="swal2-success-fix"></div>\n       <div class="swal2-success-circular-line-right"></div>\n     </div>\n     <img class="').concat(_.image,'" />\n     <h2 class="').concat(_.title,'" id="').concat(_.title,'"></h2>\n     <button type="button" class="').concat(_.close,'">×</button>\n   </div>\n   <div class="').concat(_.content,'">\n     <div id="').concat(_.content,'"></div>\n     <input class="').concat(_.input,'" />\n     <input type="file" class="').concat(_.file,'" />\n     <div class="').concat(_.range,'">\n       <input type="range" />\n       <output></output>\n     </div>\n     <select class="').concat(_.select,'"></select>\n     <div class="').concat(_.radio,'"></div>
92674\n     <label for="').concat(_.checkbox,'" class="').concat(_.checkbox,'">\n       <input type="checkbox" />\n       <span class="').concat(_.label,'"></span>\n     </label>\n     <textarea class="').concat(_.textarea,'"></textarea>\n     <div class="').concat(_["validation-message"],'" id="').concat(_["validation-message"],'"></div>\n   </div>\n   <div class="').concat(_.actions,'">\n     <button type="button" class="').concat(_.confirm,'">OK</button>\n     <button type="button" class="').concat(_.cancel,'">Cancel</button>\n   </div>\n   <div class="').concat(_.footer,'">\n   </div>\n </div>\n').replace(/(^|\n)\s*/g,""),X=function(e){var t=w();if(t&&(t.parentNode.removeChild(t),W([document.documentElement,document.body],[_["no-backdrop"],_["toast-shown"],_["has-column"]])),!j()){var n=document.createElement("div");n.className=_.container,n.innerHTML=V;var o="string"==typeof e.target?document.querySelector(e.target):e.target;o.appendChild(n);var i,r=k(),a=B(),s=U(a,_.input),c=U(a,_.file),u=a.querySelector(".".concat(_.range," input")),l=a.querySelector(".".concat(_.range," output")),d=U(a,_.select),p=a.querySelector(".".concat(_.checkbox," input")),f=U(a,_.textarea);r.setAttribute("role",e.toast?"alert":"dialog"),r.setAttribute("aria-live",e.toast?"polite":"assertive"),e.toast||r.setAttribute("aria-modal","true"),"rtl"===window.getComputedStyle(o).direction&&z(w(),_.rtl);var m=function(e){De.isVisible()&&i!==e.target.value&&De.resetValidationMessage(),i=e.target.value};return s.oninput=m,c.onchange=m,d.onchange=m,p.onchange=m,f.oninput=m,u.oninput=function(e){m(e),l.value=u.value},u.onchange=function(e){m(e),u.nextSibling.value=u.value},r}I("SweetAlert2 requires document to initialize")},G=function(e,t){if(!e)return F(t);if(e instanceof HTMLElement)t.appendChild(e);else if("object"===q(e))if(t.innerHTML="",0 in e)for(var n=0;n in e;n++)t.appendChild(e[n].cloneNode(!0));else t.appendChild(e.cloneNode(!0));else e&&(t.innerHTML=e);K(t)},ee=function(){if(j())return!1;var e=document.createElement("div"),t={WebkitAnimation:"webkitAnimationEnd",OAnimation:"oAnimationEnd oanimationend",animation:"animationend"};for(var n in t)if(t.hasOwnProperty(n)&&void 0!==e.style[n])return t[n];return!1}(),te=function(e){var t=Q(),n=L(),o=O();if(e.showConfirmButton||e.showCancelButton?K(t):F(t),e.showCancelButton?o.style.display="inline-block":F(o),e.showConfirmButton?n.style.removeProperty("display"):F(n),n.innerHTML=e.confirmButtonText,o.innerHTML=e.cancelButtonText,n.setAttribute("aria-label",e.confirmButtonAriaLabel),o.setAttribute("aria-label",e.cancelButtonAriaLabel),n.className=_.confirm,z(n,e.confirmButtonClass),o.className=_.cancel,z(o,e.cancelButtonClass),e.buttonsStyling){z([n,o],_.styled),e.confirmButtonColor&&(n.style.backgroundColor=e.confirmButtonColor),e.cancelButtonColor&&(o.style.backgroundColor=e.cancelButtonColor);var i=window.getComputedStyle(n).getPropertyValue("background-color");n.style.borderLeftColor=i,n.style.borderRightColor=i}else W([n,o],_.styled),n.style.backgroundColor=n.style.borderLeftColor=n.style.borderRightColor="",o.style.backgroundColor=o.style.borderLeftColor=o.style.borderRightColor=""},ne=function(e){var t=B().querySelector("#"+_.content);e.html?G(e.html,t):e.text?(t.textContent=e.text,K(t)):F(t)},oe=function(e){for(var t=x(),n=0;n<t.length;n++)F(t[n]);if(e.type)if(-1!==Object.keys(g).indexOf(e.type)){var o=De.getPopup().querySelector(".".concat(_.icon,".").concat(g[e.type]));K(o),e.animation&&z(o,"swal2-animate-".concat(e.type,"-icon"))}else I('Unknown type! Expected "success", "error", "warning", "info" or "question", got "'.concat(e.type,'"'))},ie=function(e){var t=S();e.imageUrl?(t.setAttribute("src",e.imageUrl),t.setAttribute("alt",e.imageAlt),K(t),e.imageWidth?t.setAttribute("width",e.imageWidth):t.removeAttribute("width"),e.imageHeight?t.setAttribute("height",e.imageHeight):t.removeAttribute("height"),t.className=_.image,e.imageClass&&z(t,e.imageClass)):F(t)},re=function(i){var r=P(),a=parseInt(null===i.currentProgressStep?De.getQueueStep():i.currentProgressStep,10);i.progressSteps&&i.progressSteps.length?(K(r),r.innerHTML="",a>=i.progressSteps.length&&R("Invalid currentProgressStep parameter, it should be less than progressSteps.length (currentProgressStep like JS arrays starts from 0)"),i.progressSteps.forEach(function(e,t){var n=document.createElement("li");if(z(n,_.progresscircle),n.innerHTML=e,t===a&&z(n,_.activeprogressstep),r.appendChild(n),t!==i.progressSteps.length-1){var o=document.createElement("li");z(o,_.progressline),i.progressStepsDistance&&(o.style.width=i.progressStepsDistance),r.appendChild(o)}})):F(r)},ae=function(e){var t=A();e.titleText?t.innerText=e.titleText:e.title&&("string"==typeof e.title&&(e.title=e.title.split("\n").join("<br />")),G(e.title,t))},se=function(){null===b.previousBodyPadding&&document.body.scrollHeight>window.innerHeight&&(b.previousBodyPadding=parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right")),document.body.style.paddingRight=b.previousBodyPadding+function(){if("ontouchstart"in window||navigator.msMaxTouchPoints)return 0;var e=document.createElement("div");
92674e.style.width="50px",e.style.height="50px",e.style.overflow="scroll",document.body.appendChild(e);var t=e.offsetWidth-e.clientWidth;return document.body.removeChild(e),t}()+"px")},ce=function(){return!!window.MSInputMethodContext&&!!document.documentMode},ue=function(){var e=w(),t=k();e.style.removeProperty("align-items"),t.offsetTop<0&&(e.style.alignItems="flex-start")},le={},de=function(e,t){var n=w(),o=k();if(o){null!==e&&"function"==typeof e&&e(o),W(o,_.show),z(o,_.hide);var i=function(){M()?pe(t):(new Promise(function(e){var t=window.scrollX,n=window.scrollY;le.restoreFocusTimeout=setTimeout(function(){le.previousActiveElement&&le.previousActiveElement.focus?(le.previousActiveElement.focus(),le.previousActiveElement=null):document.body&&document.body.focus(),e()},100),void 0!==t&&void 0!==n&&window.scrollTo(t,n)}).then(function(){return pe(t)}),le.keydownTarget.removeEventListener("keydown",le.keydownHandler,{capture:le.keydownListenerCapture}),le.keydownHandlerAdded=!1),n.parentNode&&n.parentNode.removeChild(n),W([document.documentElement,document.body],[_.shown,_["height-auto"],_["no-backdrop"],_["toast-shown"],_["toast-column"]]),T()&&(null!==b.previousBodyPadding&&(document.body.style.paddingRight=b.previousBodyPadding,b.previousBodyPadding=null),function(){if(v(document.body,_.iosfix)){var e=parseInt(document.body.style.top,10);W(document.body,_.iosfix),document.body.style.top="",document.body.scrollTop=-1*e}}(),"undefined"!=typeof window&&ce()&&window.removeEventListener("resize",ue),f(document.body.children).forEach(function(e){e.hasAttribute("data-previous-aria-hidden")?(e.setAttribute("aria-hidden",e.getAttribute("data-previous-aria-hidden")),e.removeAttribute("data-previous-aria-hidden")):e.removeAttribute("aria-hidden")}))};ee&&!v(o,_.noanimation)?o.addEventListener(ee,function e(){o.removeEventListener(ee,e),v(o,_.hide)&&i()}):i()}},pe=function(e){null!==e&&"function"==typeof e&&setTimeout(function(){e()})};function fe(e){var t=function e(){for(var t=arguments.length,n=new Array(t),o=0;o<t;o++)n[o]=arguments[o];if(!(this instanceof e))return l(e,n);Object.getPrototypeOf(e).apply(this,n)};return t.prototype=r(Object.create(e.prototype),{constructor:t}),"function"==typeof Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e,t}var me={title:"",titleText:"",text:"",html:"",footer:"",type:null,toast:!1,customClass:"",customContainerClass:"",target:"body",backdrop:!0,animation:!0,heightAuto:!0,allowOutsideClick:!0,allowEscapeKey:!0,allowEnterKey:!0,stopKeydownPropagation:!0,keydownListenerCapture:!1,showConfirmButton:!0,showCancelButton:!1,preConfirm:null,confirmButtonText:"OK",confirmButtonAriaLabel:"",confirmButtonColor:null,confirmButtonClass:null,cancelButtonText:"Cancel",cancelButtonAriaLabel:"",cancelButtonColor:null,cancelButtonClass:null,buttonsStyling:!0,reverseButtons:!1,focusConfirm:!0,focusCancel:!1,showCloseButton:!1,closeButtonAriaLabel:"Close this dialog",showLoaderOnConfirm:!1,imageUrl:null,imageWidth:null,imageHeight:null,imageAlt:"",imageClass:null,timer:null,width:null,padding:null,background:null,input:null,inputPlaceholder:"",inputValue:"",inputOptions:{},inputAutoTrim:!0,inputClass:null,inputAttributes:{},inputValidator:null,validationMessage:null,grow:!1,position:"center",progressSteps:[],currentProgressStep:null,progressStepsDistance:null,onBeforeOpen:null,onAfterClose:null,onOpen:null,onClose:null,useRejections:!1,expectRejections:!1},he=["useRejections","expectRejections","extraParams"],ge=["allowOutsideClick","allowEnterKey","backdrop","focusConfirm","focusCancel","heightAuto","keydownListenerCapture"],be=function(e){return me.hasOwnProperty(e)||"extraParams"===e},ve=function(e){return-1!==he.indexOf(e)},ye=function(e){for(var t in e)be(t)||R('Unknown parameter "'.concat(t,'"')),e.toast&&-1!==ge.indexOf(t)&&R('The parameter "'.concat(t,'" is incompatible with toasts')),ve(t)&&m('The parameter "'.concat(t,'" is deprecated and will be removed in the next major release.'))}
92674,we='"setDefaults" & "resetDefaults" methods are deprecated in favor of "mixin" method and will be removed in the next major release. For new projects, use "mixin". For past projects already using "setDefaults", support will be provided through an additional package.',Ce={};var ke=[],xe=function(){var e=k();e||De(""),e=k();var t=Q(),n=L(),o=O();K(t),K(n),z([e,t],_.loading),n.disabled=!0,o.disabled=!0,e.setAttribute("data-loading",!0),e.setAttribute("aria-busy",!0),e.focus()},Ae=Object.freeze({isValidParameter:be,isDeprecatedParameter:ve,argsToParams:function(n){var o={};switch(q(n[0])){case"object":r(o,n[0]);break;default:["title","html","type"].forEach(function(e,t){switch(q(n[t])){case"string":o[e]=n[t];break;case"undefined":break;default:I("Unexpected type of ".concat(e,'! Expected "string", got ').concat(q(n[t])))}})}return o},adaptInputValidator:function(n){return function(e,t){return n.call(this,e,t).then(function(){},function(e){return e})}},close:de,closePopup:de,closeModal:de,closeToast:de,isVisible:function(){return!!k()},clickConfirm:function(){return L().click()},clickCancel:function(){return O().click()},getContainer:w,getPopup:k,getTitle:A,getContent:B,getImage:S,getIcons:x,getCloseButton:$,getButtonsWrapper:function(){return m("swal.getButtonsWrapper() is deprecated and will be removed in the next major release, use swal.getActions() instead"),C(_.actions)},getActions:Q,getConfirmButton:L,getCancelButton:O,getFooter:Y,getFocusableElements:J,getValidationMessage:E,isLoading:function(){return k().hasAttribute("data-loading")},fire:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return l(this,t)},mixin:function(n){return fe(function(e){function t(){return a(this,t),d(this,c(t).apply(this,arguments))}return s(t,e),i(t,[{key:"_main",value:function(e){return p(c(t.prototype),"_main",this).call(this,r({},n,e))}}]),t}(this))},queue:function(e){var r=this;ke=e;var a=function(){ke=[],document.body.removeAttribute("data-swal2-queue-step")},s=[];return new Promise(function(i){!function t(n,o){n<ke.length?(document.body.setAttribute("data-swal2-queue-step",n),r(ke[n]).then(function(e){void 0!==e.value?(s.push(e.value),t(n+1,o)):(a(),i({dismiss:e.dismiss}))})):(a(),i({value:s}))}(0)})},getQueueStep:function(){return document.body.getAttribute("data-swal2-queue-step")},insertQueueStep:function(e,t){return t&&t<ke.length?ke.splice(t,0,e):ke.push(e)},deleteQueueStep:function(e){void 0!==ke[e]&&ke.splice(e,1)},showLoading:xe,enableLoading:xe,getTimerLeft:function(){return le.timeout&&le.timeout.getTimerLeft()},stopTimer:function(){return le.timeout&&le.timeout.stop()},resumeTimer:function(){return le.timeout&&le.timeout.start()},toggleTimer:function(){var e=le.timeout;return e&&(e.running?e.stop():e.start())},increaseTimer:function(e){return le.timeout&&le.timeout.increase(e)},isTimerRunning:function(){return le.timeout&&le.timeout.isRunning()}}),Be="function"==typeof Symbol?Symbol:function(){var t=0;function e(e){return"__"+e+"_"+Math.floor(1e9*Math.random())+"_"+ ++t+"__"}return e.iterator=e("Symbol.iterator"),e}(),Se="function"==typeof WeakMap?WeakMap:function(n,o,t){function e(){o(this,n,{value:Be("WeakMap")})}return e.prototype={delete:function(e){delete e[this[n]]},get:function(e){return e[this[n]]},has:function(e){return t.call(e,this[n])},set:function(e,t){o(e,this[n],{configurable:!0,value:t})}},e}(Be("WeakMap"),Object.defineProperty,{}.hasOwnProperty),Pe={promise:new Se,innerParams:new Se,domCache:new Se};function Ee(){var e=Pe.innerParams.get(this),t=Pe.domCache.get(this);e.showConfirmButton||(F(t.confirmButton),e.showCancelButton||F(t.actions)),W([t.popup,t.actions],_.loading),t.popup.removeAttribute("aria-busy"),t.popup.removeAttribute("data-loading"),t.confirmButton.disabled=!1,t.cancelButton.disabled=!1}function Le(e){var t=Pe.domCache.get(this);t.validationMessage.innerHTML=e;var n=window.getComputedStyle(t.popup);t.validationMessage.style.marginLeft="-".concat(n.getPropertyValue("padding-left")),t.validationMessage.style.marginRight="-".concat(n.getPropertyValue("padding-right")),K(t.validationMessage);var o=this.getInput();o&&(o.setAttribute("aria-invalid",!0),o.setAttribute("aria-describedBy",_["validation-message"]),N(o),z(o,_.
92674inputerror))}function Oe(){var e=Pe.domCache.get(this);e.validationMessage&&F(e.validationMessage);var t=this.getInput();t&&(t.removeAttribute("aria-invalid"),t.removeAttribute("aria-describedBy"),W(t,_.inputerror))}var Te=function e(t,n){a(this,e);var o,i,r=n;this.running=!1,this.start=function(){return this.running||(this.running=!0,i=new Date,o=setTimeout(t,r)),r},this.stop=function(){return this.running&&(this.running=!1,clearTimeout(o),r-=new Date-i),r},this.increase=function(e){var t=this.running;return t&&this.stop(),r+=e,t&&this.start(),r},this.getTimerLeft=function(){return this.running&&(this.stop(),this.start()),r},this.isRunning=function(){return this.running},this.start()},Me={email:function(e,t){return/^[a-zA-Z0-9.+_-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]{2,24}$/.test(e)?Promise.resolve():Promise.reject(t&&t.validationMessage?t.validationMessage:"Invalid email address")},url:function(e,t){return/^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,63}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)$/.test(e)?Promise.resolve():Promise.reject(t&&t.validationMessage?t.validationMessage:"Invalid URL")}};var je=function(e){var t=w(),n=k();null!==e.onBeforeOpen&&"function"==typeof e.onBeforeOpen&&e.onBeforeOpen(n),e.animation?(z(n,_.show),z(t,_.fade),W(n,_.hide)):W(n,_.fade),K(n),t.style.overflowY="hidden",ee&&!v(n,_.noanimation)?n.addEventListener(ee,function e(){n.removeEventListener(ee,e),t.style.overflowY="auto"}):t.style.overflowY="auto",z([document.documentElement,document.body,t],_.shown),e.heightAuto&&e.backdrop&&!e.toast&&z([document.documentElement,document.body],_["height-auto"]),T()&&(se(),function(){if(/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream&&!v(document.body,_.iosfix)){var e=document.body.scrollTop;document.body.style.top=-1*e+"px",z(document.body,_.iosfix)}}(),"undefined"!=typeof window&&ce()&&(ue(),window.addEventListener("resize",ue)),f(document.body.children).forEach(function(e){e===w()||function(e,t){if("function"==typeof e.contains)return e.contains(t)}(e,w())||(e.hasAttribute("aria-hidden")&&e.setAttribute("data-previous-aria-hidden",e.getAttribute("aria-hidden")),e.setAttribute("aria-hidden","true"))}),setTimeout(function(){t.scrollTop=0})),M()||le.previousActiveElement||(le.previousActiveElement=document.activeElement),null!==e.onOpen&&"function"==typeof e.onOpen&&setTimeout(function(){e.onOpen(n)})};var Ve,qe=Object.freeze({hideLoading:Ee,disableLoading:Ee,getInput:function(e){var t=Pe.innerParams.get(this),n=Pe.domCache.get(this);if(!(e=e||t.input))return null;switch(e){case"select":case"textarea":case"file":return U(n.content,_[e]);case"checkbox":return n.popup.querySelector(".".concat(_.checkbox," input"));case"radio":return n.popup.querySelector(".".concat(_.radio," input:checked"))||n.popup.querySelector(".".concat(_.radio," input:first-child"));case"range":return n.popup.querySelector(".".concat(_.range," input"));default:return U(n.content,_.input)}},enableButtons:function(){var e=Pe.domCache.get(this);e.confirmButton.disabled=!1,e.cancelButton.disabled=!1},disableButtons:function(){var e=Pe.domCache.get(this);e.confirmButton.disabled=!0,e.cancelButton.disabled=!0},enableConfirmButton:function(){Pe.domCache.get(this).confirmButton.disabled=!1},disableConfirmButton:function(){Pe.domCache.get(this).confirmButton.disabled=!0},enableInput:function(){var e=this.getInput();if(!e)return!1;if("radio"===e.type)for(var t=e.parentNode.parentNode.querySelectorAll("input"),n=0;n<t.length;n++)t[n].disabled=!1;else e.disabled=!1},disableInput:function(){var e=this.getInput();if(!e)return!1;if(e&&"radio"===e.type)for(var t=e.parentNode.parentNode.querySelectorAll("input"),n=0;n<t.length;n++)t[n].disabled=!0;else e.disabled=!0},showValidationMessage:Le,resetValidationMessage:Oe,resetValidationError:function(){m("Swal.resetValidationError() is deprecated and will be removed in the next major release, use Swal.resetValidationMessage() instead"),Oe.bind(this)()},showValidationError:function(e){m("Swal.showValidationError() is deprecated and will be removed in the next major release, use Swal.showValidationMessage() instead"),Le.bind(this)(e)},getProgressSteps:function(){return Pe.innerParams.get(this).progressSteps},setProgressSteps:function(e){var t=r({},Pe.innerParams.get(this),{progressSteps:e});Pe.innerParams.set(this,t),re(t)},showProgressSteps:function(){var e=Pe.domCache.get(this);K(e.progressSteps)},hideProgressSteps:function(){var e=Pe.domCache.get(this);F(e.progressSteps)},_main:function(e){var T=this;ye(e);var M=r({},me,e);!function(t){var e;
92674t.inputValidator||Object.keys(Me).forEach(function(e){t.input===e&&(t.inputValidator=t.expectRejections?Me[e]:De.adaptInputValidator(Me[e]))}),t.validationMessage&&("object"!==q(t.extraParams)&&(t.extraParams={}),t.extraParams.validationMessage=t.validationMessage),(!t.target||"string"==typeof t.target&&!document.querySelector(t.target)||"string"!=typeof t.target&&!t.target.appendChild)&&(R('Target parameter is not valid, defaulting to "body"'),t.target="body"),"function"==typeof t.animation&&(t.animation=t.animation.call());var n=k(),o="string"==typeof t.target?document.querySelector(t.target):t.target;e=n&&o&&n.parentNode!==o.parentNode?X(t):n||X(t),t.width&&(e.style.width="number"==typeof t.width?t.width+"px":t.width),t.padding&&(e.style.padding="number"==typeof t.padding?t.padding+"px":t.padding),t.background&&(e.style.background=t.background);for(var i=window.getComputedStyle(e).getPropertyValue("background-color"),r=e.querySelectorAll("[class^=swal2-success-circular-line], .swal2-success-fix"),a=0;a<r.length;a++)r[a].style.backgroundColor=i;var s=w(),c=$(),u=Y();if(ae(t),ne(t),"string"==typeof t.backdrop?w().style.background=t.backdrop:t.backdrop||z([document.documentElement,document.body],_["no-backdrop"]),!t.backdrop&&t.allowOutsideClick&&R('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`'),t.position in _?z(s,_[t.position]):(R('The "position" parameter is not valid, defaulting to "center"'),z(s,_.center)),t.grow&&"string"==typeof t.grow){var l="grow-"+t.grow;l in _&&z(s,_[l])}t.showCloseButton?(c.setAttribute("aria-label",t.closeButtonAriaLabel),K(c)):F(c),e.className=_.popup,t.toast?(z([document.documentElement,document.body],_["toast-shown"]),z(e,_.toast)):z(e,_.modal),t.customClass&&z(e,t.customClass),t.customContainerClass&&z(s,t.customContainerClass),re(t),oe(t),ie(t),te(t),G(t.footer,u),!0===t.animation?W(e,_.noanimation):z(e,_.noanimation),t.showLoaderOnConfirm&&!t.preConfirm&&R("showLoaderOnConfirm is set to true, but preConfirm is not defined.\nshowLoaderOnConfirm should be used together with preConfirm, see usage example:\nhttps://sweetalert2.github.io/#ajax-request")}(M),Object.freeze(M),Pe.innerParams.set(this,M),le.timeout&&(le.timeout.stop(),delete le.t
92674imeout),clearTimeout(le.restoreFocusTimeout);var j={popup:k(),container:w(),content:B(),actions:Q(),confirmButton:L(),cancelButton:O(),closeButton:$(),validationMessage:E(),progressSteps:P()};Pe.domCache.set(this,j);var V=this.constructor;return new Promise(function(t,n){var o=function(e){V.closePopup(M.onClose,M.onAfterClose),M.useRejections?t(e):t({value:e})},c=function(e){V.closePopup(M.onClose,M.onAfterClose),M.useRejections?n(e):t({dismiss:e})},u=function(e){V.closePopup(M.onClose,M.onAfterClose),n(e)};M.timer&&(le.timeout=new Te(function(){c("timer"),delete le.timeout},M.timer)),M.input&&setTimeout(function(){var e=T.getInput();e&&N(e)},0);for(var l=function(t){if(M.showLoaderOnConfirm&&V.showLoading(),M.preConfirm){T.resetValidationMessage();var e=Promise.resolve().then(function(){return M.preConfirm(t,M.extraParams)});M.expectRejections?e.then(function(e){return o(e||t)},function(e){T.hideLoading(),e&&T.showValidationMessage(e)}):e.then(function(e){Z(j.validationMessage)||!1===e?T.hideLoading():o(e||t)},function(e){return u(e)})}else o(t)},e=function(e){var t=e.target,n=j.confirmButton,o=j.cancelButton,i=n&&(n===t||n.contains(t)),r=o&&(o===t||o.contains(t));switch(e.type){case"click":if(i&&V.isVisible())if(T.disableButtons(),M.input){var a=function(){var e=T.getInput();if(!e)return null;switch(M.input){case"checkbox":return e.checked?1:0;case"radio":return e.checked?e.value:null;case"file":return e.files.length?e.files[0]:null;default:return M.inputAutoTrim?e.value.trim():e.value}}();if(M.inputValidator){T.disableInput();var s=Promise.resolve().then(function(){return M.inputValidator(a,M.extraParams)});M.expectRejections?s.then(function(){T.enableButtons(),T.enableInput(),l(a)},function(e){T.enableButtons(),T.enableInput(),e&&T.showValidationMessage(e)}):s.then(function(e){T.enableButtons(),T.enableInput(),e?T.showValidationMessage(e):l(a)},function(e){return u(e)})}else T.getInput().checkValidity()?l(a):(T.enableButtons(),T.showValidationMessage(M.validationMessage))}else l(!0);else r&&V.isVisible()&&(T.disableButtons(),c(V.DismissReason.cancel))}},i=j.popup.querySelectorAll("button"),r=0;r<i.length;r++)i[r].onclick=e,i[r].onmouseover=e,i[r].onmouseout=e,i[r].onmousedown=e;if(j.closeButton.onclick=function(){c(V.DismissReason.close)},M.toast)j.popup.onclick=function(){M.showConfirmButton||M.showCancelButton||M.showCloseButton||M.input||c(V.DismissReason.close)};else{var a=!1;j.popup.onmousedown=function(){j.container.onmouseup=function(e){j.container.onmouseup=void 0,e.target===j.container&&(a=!0)}},j.container.onmousedown=function(){j.popup.onmouseup=function(e){j.popup.onmouseup=void 0,(e.target===j.popup||j.popup.contains(e.target))&&(a=!0)}},j.container.onclick=function(e){a?a=!1:e.target===j.container&&H(M.allowOutsideClick)&&c(V.DismissReason.backdrop)}}M.reverseButtons?j.confirmButton.parentNode.insertBefore(j.cancelButton,j.confirmButton):j.confirmButton.parentNode.insertBefore(j.confirmButton,j.cancelButton);var s=function(e,t){for(var n=J(M.focusCancel),o=0;o<n.length;o++)return(e+=t)===n.length?e=0:-1===e&&(e=n.length-1),n[e].focus();j.popup.focus()};le.keydownHandlerAdded&&(le.keydownTarget.removeEventListener("keydown",le.keydownHandler,{capture:le.keydownListenerCapture}),le.keydownHandlerAdded=!1),M.toast||(le.keydownHandler=function(e){return function(e,t){if(t.stopKeydownPropagation&&e.stopPropagation(),"Enter"!==e.key||e.isComposing)if("Tab"===e.key){for(var n=e.target,o=J(t.focusCancel),i=-1,r=0;r<o.length;r++)if(n===o[r]){i=r;break}e.shiftKey?s(i,-1):s(i,1),e.stopPropagation(),e.preventDefault()}else-1!==["ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Left","Right","Up","Down"].indexOf(e.key)?document.activeElement===j.confirmButton&&Z(j.cancelButton)?j.cancelButton.focus():document.activeElement===j.cancelButton&&Z(j.confirmButton)&&j.confirmButton.focus():"Escape"!==e.key&&"Esc"!==e.key||!0!==H(t.allowEscapeKey)||(e.preventDefault(),c(V.DismissReason.esc));else if(e.target&&T.getInput()&&e.target.outerHTML===T.getInput().outerHTML){if(-1!==["textarea","file"].indexOf(t.input))return;V.clickConfirm(),e.preventDefault()}}(e,M)},le.keydownTarget=M.keydownListenerCapture?window:j.popup,le.keydownListenerCapture=M.keydownListenerCapture,le.keydownTarget.addEventListener("keydown",le.keydownHandler,{capture:le.keydownListenerCapture}),le.keydownHandlerAdded=!0),T.enableButtons(),T.hideLoading(),T.resetValidationMessage(),M.toast&&(M.input||M.footer||M.showCloseButton)?z(document.body,_["toast-column"]):W(document.body,_["toast-column"]);for(var d,p,f=["input","file","range","select","radio","checkbox","textarea"],m=function(e){e.placeholder&&!M.inputPlaceholder||(e.placeholder=M.inputPlaceholder)},h=0;h<f.length;h++){var g=_[f[h]],b=U(j.content,g);if(d=T.getInput(f[h])){for(var v in d.attributes)if(d.attributes.hasOwnProperty(v)){var y=d.attributes[v].name;"type"!==y&&"value"!==y&&d.removeAttribute(y)}for(var w in M.inputAttributes)"range"===f[h]&&"placeholder"===w||d.setAttribute(w,M.inputAttributes[w])}b.className=g,M.inputClass&&z(b,M.inputClass),F(b)}switch(M.input){case"text":case"email":case"password":case"number":case"tel":case"url":d=U(j.content,_.input),"string"==typeof M.inputValue||"number"==typeof M.inputValue?d.value=M.inputValue:D(M.inputValue)||R('Unexpected type of inputValue! Expected "string", "number" or "Promise", got "'.concat(q(M.inputValue),'"')),m(d),d.type=M.input,
92674K(d);break;case"file":m(d=U(j.content,_.file)),d.type=M.input,K(d);break;case"range":var C=U(j.content,_.range),k=C.querySelector("input"),x=C.querySelector("output");k.value=M.inputValue,k.type=M.input,x.value=M.inputValue,K(C);break;case"select":var A=U(j.content,_.select);if(A.innerHTML="",M.inputPlaceholder){var B=document.createElement("option");B.innerHTML=M.inputPlaceholder,B.value="",B.disabled=!0,B.selected=!0,A.appendChild(B)}p=function(e){e.forEach(function(e){var t=e[0],n=e[1],o=document.createElement("option");o.value=t,o.innerHTML=n,M.inputValue.toString()===t.toString()&&(o.selected=!0),A.appendChild(o)}),K(A),A.focus()};break;case"radio":var S=U(j.content,_.radio);S.innerHTML="",p=function(e){e.forEach(function(e){var t=e[0],n=e[1],o=document.createElement("input"),i=document.createElement("label");o.type="radio",o.name=_.radio,o.value=t,M.inputValue.toString()===t.toString()&&(o.checked=!0);var r=document.createElement("span");r.innerHTML=n,r.className=_.label,i.appendChild(o),i.appendChild(r),S.appendChild(i)}),K(S);var t=S.querySelectorAll("input");t.length&&t[0].focus()};break;case"checkbox":var P=U(j.content,_.checkbox),E=T.getInput("checkbox");E.type="checkbox",E.value=1,E.id=_.checkbox,E.checked=Boolean(M.inputValue),P.querySelector("span").innerHTML=M.inputPlaceholder,K(P);break;case"textarea":var L=U(j.content,_.textarea);L.value=M.inputValue,m(L),K(L);break;case null:break;default:I('Unexpected type of input! Expected "text", "email", "password", "number", "tel", "select", "radio", "checkbox", "textarea", "file" or "url", got "'.concat(M.input,'"'))}if("select"===M.input||"radio"===M.input){var O=function(e){return p((t=e,n=[],"undefined"!=typeof Map&&t instanceof Map?t.forEach(function(e,t){n.push([t,e])}):Object.keys(t).forEach(function(e){n.push([e,t[e]])}),n));var t,n};D(M.inputOptions)?(V.showLoading(),M.inputOptions.then(function(e){T.hideLoading(),O(e)})):"object"===q(M.inputOptions)?O(M.inputOptions):I("Unexpected type of inputOptions! Expected object, Map or Promise, got ".concat(q(M.inputOptions)))}else-1!==["text","email","number","tel","textarea"].indexOf(M.input)&&D(M.inputValue)&&(V.showLoading(),F(d),M.inputValue.then(function(e){d.value="number"===M.input?parseFloat(e)||0:e+"",K(d),d.focus(),T.hideLoading()}).catch(function(e){I("Error in inputValue promise: "+e),d.value="",K(d),d.focus(),T.hideLoading()}));je(M),M.toast||(H(M.allowEnterKey)?M.focusCancel&&Z(j.cancelButton)?j.cancelButton.focus():M.focusConfirm&&Z(j.confirmButton)?j.confirmButton.focus():s(-1,1):document.activeElement&&"function"==typeof document.activeElement.blur&&document.activeElement.blur()),j.container.scrollTop=0})}});function Re(){if("undefined"!=typeof window){"undefined"==typeof Promise&&I("This package requires a Promise library, please include a shim to enable it in this browser (See: https://github.com/sweetalert2/sweetalert2/wiki/Migration-from-SweetAlert-to-SweetAlert2#1-ie-support)"),Ve=this;for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];var o=Object.freeze(this.constructor.argsToParams(t));Object.defineProperties(this,{params:{value:o,writable:!1,enumerable:!0}});var i=this._main(this.params);Pe.promise.set(this,i)}}Re.prototype.then=function(e,t){return Pe.promise.get(this).then(e,t)},Re.prototype.catch=function(e){return Pe.promise.get(this).catch(e)},Re.prototype.finally=function(e){return Pe.promise.get(this).finally(e)},r(Re.prototype,qe),r(Re,Ae),Object.keys(qe).forEach(function(t){Re[t]=function(){var e;if(Ve)return(e=Ve)[t].apply(e,arguments)}}),Re.DismissReason=e,Re.noop=function(){};var Ie,He,De=fe((Ie=Re,He=function(e){function t(){return a(this,t),d(this,c(t).apply(this,arguments))}return s(t,Ie),i(t,[{key:"_main",value:function(e){return p(c(t.prototype),"_main",this).call(this,r({},Ce,e))}}],[{key:"setDefaults",value:function(t){if(m(we),!t||"object"!==q(t))throw new TypeError("SweetAlert2: The argument for setDefaults() is required and has to be a object");ye(t),Object.keys(t).forEach(function(e){Ie.isValidParameter(e)&&(Ce[e]=t[e])})}},{key:"resetDefaults",value:function(){m(we),Ce={}}}]),t}(),"undefined"!=typeof window&&"object"===q(window._swalDefaults)&&He.setDefaults(window._swalDefaults),He));return De.default=De}),"undefined"!=typeof window&&window.Sweetalert2&&(window.Sweetalert2.version="7.33.1",window.swal=window.sweetAlert=window.Swal=window.SweetAlert=window.Sweetalert2);
92675//== Set defaults
92676swal.setDefaults({
92677	width: 400,
92678	heightAuto: false,
92679	padding: '2.5rem',
92680	buttonsStyling: false,
92681	confirmButtonClass: 'btn btn-success m-btn m-btn--custom',
92682	confirmButtonColor: null,
92683	cancelButtonClass: 'btn btn-secondary m-btn m-btn--custom',
92684	cancelButtonColor: null
92685});

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.