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 || ' ')+'</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 || ' ')+'</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"> </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:"«",rightArrow:"»"},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"> </td><td><a href="#" data-action="incrementMinute"><span class="'+this.icons.up+'"></span></a></td>'+(this.showSeconds?'<td class="separator"> </td><td><a href="#" data-action="incrementSecond"><span class="'+this.icons.up+'"></span></a></td>':"")+(this.showMeridian?'<td class="separator"> </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"> </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"> </td><td><a href="#" data-action="decrementSecond"><span class="'+this.icons.down+'"></span></a></td>':"")+(this.showMeridian?'<td class="separator"> </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">×</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: ' ', 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 '&': '&', 10019 '<': '<', 10020 '>': '>', 10021 '"': '"', 10022 "'": ''', 10023 '`': '`' 10024 }; 10025 10026 var unescapeMap = { 10027 '&': '&', 10028 '<': '<', 10029 '>': '>', 10030 '"': '"', 10031 ''': "'", 10032 '`': '`' 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">×</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> ' + 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 '&': '&', 15194 '<': '<', 15195 '>': '>', 15196 '"': '"', 15197 "'": ''', 15198 '`': '`', 15199 '=': '=' 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-9ï¼-ï¼]", 20979 cardinality: 1, 20980 definitionSymbol: "*" 20981 }, 20982 a: { 20983 validator: "[A-Za-zÐ-ÑÐÑÃ-ÿµ]", 20984 cardinality: 1, 20985 definitionSymbol: "*" 20986 }, 20987 "*": { 20988 validator: "[0-9ï¼-ï¼A-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' + '">‹</span>', 28870 '<span aria-label="' + 'Next' + '">›</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">×</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 36496 * - [workaround] IE11 and other browser works with bogus br 36497 */ 36498 var blankHTML = env.isMSIE && env.browserVersion < 11 ? ' ' : '<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> </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 + '&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 " 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, "&" ) 44712 .replace( /</g, "<" ) 44713 .replace( />/g, ">" ) 44714 .replace( /"/g, """ ) 44715 .replace( /'/g, "'" ); 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('+'")'); 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( / | /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">×</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">×</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,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")}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;"') + "> <"+"/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'> <"+"/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;"') + "> <"+"/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"> </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 = ' '; 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 `<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, 100, 0)</code>â)</li> 59098 # <li>rgb(â¢â¢â¢%, â¢â¢â¢%, â¢â¢â¢%) â same as above, but in %: (â<code>rgb(100%, 175%, 0%)</code>â)</li> 59099 # <li>hsb(â¢â¢â¢, â¢â¢â¢, â¢â¢â¢) â hue, saturation and brightness values: (â<code>hsb(0.5, 0.25, 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>â<â or âeaseInâ or âease-inâ</li> 62249 # <li>â>â or âeaseOutâ or âease-outâ</li> 62250 # <li>â<>â 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‐bezier(XX, XX, XX, 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‐bezier(XX, XX, XX, 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‐bezier(XX, XX, XX, 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, 100, 0)</code>â)</li> 65119 # <li>rgb(â¢â¢â¢%, â¢â¢â¢%, â¢â¢â¢%) â same as above, but in %: (â<code>rgb(100%, 175%, 0%)</code>â)</li> 65120 # <li>rgba(â¢â¢â¢, â¢â¢â¢, â¢â¢â¢, â¢â¢â¢) â red, green and blue channelsâ values: (â<code>rgba(200, 100, 0, .5)</code>â)</li> 65121 # <li>rgba(â¢â¢â¢%, â¢â¢â¢%, â¢â¢â¢%, â¢â¢â¢%) â same as above, but in %: (â<code>rgba(100%, 175%, 0%, 50%)</code>â)</li> 65122 # <li>hsb(â¢â¢â¢, â¢â¢â¢, â¢â¢â¢) â hue, saturation and brightness values: (â<code>hsb(0.5, 0.25, 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, 1, .5)</code>â or, if you want to go fancy, â<code>hsl(240°, 1, .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, "<").replace(/&/g, "&").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 '&': '&', 68669 '<': '<', 68670 '>': '>', 68671 '"': '"', 68672 '\'': ''' 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">×</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.